Switching on/off automatic discovery of resource classes and providers in JAX-RS
The automatic discovery may complicate things when provider classes are included in the libraries used by an application or preinstalled in a server, for example Jackson-related jar in Wildfly. So I prefer to switch off every features I am not aware of. The JAX-RS specification states:
So, essentially if methods getClasses and getSingletons are not overriden the resource classes and providers are discovered automatically. Let's use two root resource classes to illustrate the rule. The full illustration code is available in Github.
@Path("/registered") public class MyRegisteredResource { @GET public String getBook() { return "Hello Registered World!"; } } @Path("/unregistered") public class MyUnregisteredResource { @GET public String getBook() { return "Hello Unregistered World!"; } }
Both resources operate if the Application class is empty:
@ApplicationPath("/api") public class MyApplication extends Application { }
If I override getClasses method, only the resource class returned by the method will function:
@ApplicationPath("/api") public class MyApplication extends Application { @Override public Set<Class<?>> getClasses() { return new HashSet<Class<?>>() { { add(MyRegisteredResource.class); } }; } }
In which method to register a class?
Quotes from the JAX-RS specification on the Lifecyle of providers and resource classes :
- By default a new resource class instance is created for each request to that resource.
- By default a single instance of each provider class is instantiated for each JAX-RS application.
- By default, just like all the other providers, a single instance of each filter or entity interceptor is instantiated for each JAX-RS application.
So the root resource classes should be returned by getClasses, whereas providers, including filters, by getSingletons method.
Getting the standard servlet defined types such as HttpServletRequest in ContainerRequestFilter
The worst feature of JAX-RS filters is there is not straightforward way to access HttpServletRequest instance. The reference to HttpServletRequest can be injected into managed classes using @Context annotation. However, according to the specification the filters have to be instantiated singletons. That means that injection will not work.
If you want to access in a filter any of the standard servlet arguments such as HttpServletRequest, HttpServletResponse, ServletConfig, ServletContext, the filter will have to be registered in getClasses, so that its instance is created and injected for each request. Otherwise injection is impossible and without it there is no way to access the servlet-defined types.
No comments:
Post a Comment