What scope do JAX-RS 2 filters have?

那年仲夏 提交于 2019-12-04 16:00:24

For RestEasy, the answer is given in the RestEasy documentation concerning CDI integration:

A CDI bean that does not explicitly define a scope is @Dependent scoped by default. This pseudo scope means that the bean adapts to the lifecycle of the bean it is injected into. Normal scopes (request, session, application) are more suitable for JAX-RS components as they designate component's lifecycle boundaries explicitly. Therefore, the resteasy-cdi module alters the default scoping in the following way:

If a JAX-RS root resource does not define a scope explicitly, it is bound to the Request scope.

If a JAX-RS Provider or javax.ws.rs.Application subclass does not define a scope explicitly, it is bound to the Application scope.

Therefor JAX-RS filters annotated with @Provider are @ApplicationScoped.

The documentation also says that a JAX-RS provider can be associated with any scope by putting the proper annotation to it. So in general, the scope of a JAX-RS filter can be customized.

It is important to notice that it is safe to inject @RequestScoped objects into an @ApplicationScoped filter. This is, because CDI does not inject a reference to the actual object but to a proxy. When a method is invoked on the proxy, a separate instance of the object will be used for each request behind the scenes.

Here the according WELD documentation:

4.9. Client proxies

Clients of an injected bean do not usually hold a direct reference to a bean instance, unless the bean is a dependent object (scope @Dependent).

Imagine that a bean bound to the application scope held a direct reference to a bean bound to the request scope. The application-scoped bean is shared between many different requests. However, each request should see a different instance of the request scoped bean—the current one!

...

Therefore, unless a bean has the default scope @Dependent, the container must indirect all injected references to the bean through a proxy object. This client proxy is responsible for ensuring that the bean instance that receives a method invocation is the instance that is associated with the current context. The client proxy also allows beans bound to contexts such as the session context to be serialized to disk without recursively serializing other injected beans.

I used the following code to validate this (assume that the entityManager is produced as @RequestScoped in the example):

@Provider
public class OtherTestFilter implements ContainerRequestFilter {

    @Inject
    EntityManager entityManager;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        Session session =  (Session) entityManager.getDelegate();
        System.out.println(session.hashCode());
    }
} 

This gives a different hash value of session for every request processed by the filter. So theory and practice match here.

The way it's defined, it looks like it is DependentScoped. The only other possibility would be a silent RequestScoped, but that isn't very likely.

What scope do JAX-RS 2 filters have?

Providers such as filters are singleton by default.


What the documentation says

From the Application documentation:

The default life-cycle for resource class instances is per-request. The default life-cycle for providers (registered directly or via a feature) is singleton.

From the JAX-RS specification:

By default a single instance of each provider class is instantiated for each JAX-RS application. First the constructor is called, then any requested dependencies are injected, then the appropriate provider methods may be called multiple times (simultaneously), and finally the object is made available for garbage collection.

And the JAX-RS specification also mentions the following regarding CDI integration:

Providers and Application subclasses MUST be singletons or use application scope.

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