Can I create a request-scoped object and access it from anywhere, and avoid passing it around as a parameter in JAX-RS?

安稳与你 提交于 2019-12-12 06:36:25

问题


Say I have a web service / a REST resource that is called with some HTTP header parameters. The resource method builds a complex data object (currently a POJO) and eventually returns it to the client (via Gson as JSON, but that doesn't matter).

So I have this call hierarchy:

@Path(foo) ProjectResource @GET getProject()
-> new Project()
-> new List<Participant> which contains lots of new Participant()s
-> new Affiliation()

If I want the Affiliation object to be e.g. populated in English or German depending on a header parameter, I have to pass that as a parameter down the chain. I want to avoid having to do that. Maybe this is just fundamentally impossible, but it feels so wrong. All these objects only live inside the request, so wouldn't it be convenient to be able to access information tied to the request from anywhere?

I was hoping I could e.g. define a CDI @RequestScoped object that initialized itself (or gets populated by some WebFilter) and that I can then inject where I might need it.

But obviously that doesn't work from inside the POJOs, and I also had trouble getting hold of the headers from inside the request-scoped object.

I've read many SO questions/answers about EJBs and JAX-RS Context and CDI but I can't wrap my head around it.

Am I expecting too much? Is passing down the parameter really the preferred option?


回答1:


If I understand what you need, you can try the following (just wrote this solution from the top of my head, but it should work):

Defining a class to store the data you need

Define a class annotated with @RequestScoped which will store the data you need:

@RequestScoped
public class RequestMetadata {

    private Locale language;

    // Default constructor, getters and setters ommited
}

Ensure you are using the @RequestScoped annotation from the javax.enterprise.context package.

Creating a request filter

Create a ContainerRequestFilter to populate the RequestMetadata:

@Provider
@PreMatching
public class RequestMetadataFilter implements ContainerRequestFilter {

    @Inject
    private RequestMetadata requestMetadata;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestMetadata.setLanguage(requestContext.getLanguage());
    }
}

Performing the injection

And then you can finally perform the injection of the RequestMetadata using @Inject:

@Stateless
public class Foo {

    @Inject
    private RequestMetadata requestMetadata;

    ...
}

Please, be aware that anywhere is too broad: The injection will work into beans managed by the container, such as servlets, JAX-RS classes, EJB and CDI beans, for example.

You won't be able to perform injections into beans created by yourself neither into JPA entities.



来源:https://stackoverflow.com/questions/36356118/can-i-create-a-request-scoped-object-and-access-it-from-anywhere-and-avoid-pass

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!