I have a RESTful server implementation as well as a library for clients to make the calls, all using JAX-RS. The server components are divided up into interface FooResource
and implementation FooResourceService
.
In order for the client and server libraries to share RESTful path and other definitions, I wanted to split out the FooResource
interface into its own project:
@Path(value = "foo")
public interface FooResource {
@GET
public Bar getBar(@PathParam(value = "{id}") int id) {
I want to set some headers in the response. One easy way to do this is to use @Context HttpServletResponse
in the method signature:
public Bar getBar(@PathParam(value = "{id}") int id, @Context HttpServletResponse servletResponse) {
But the problem is that this exposes implementation details in the interface. More specifically, it suddenly requires my REST definition project (which is shared between the client and server library) to pull in the javax.servlet-api
dependency---something the client has no need up (or desire for).
How can my RESTful resource service implementation set HTTP response headers without pulling in that dependency in the resource interface?
I saw one post recommending I inject the HttpServletResponse as a class member. But how would this work if my resource service implementation is a singleton? Does it use some sort of proxy with thread locals or something that figures out the correct servlet response even though the singleton class is used simultaneously by multiple threads? Are there any other solutions?
So injecting
HttpServletResponse
seems like a no go. Only certain proxy-able types are inject-able into singletons. I believe the complete list is as follows:This is somewhat pointed out in the JAX-RS spec, but is explained more clearly in the Jersey reference guide
SecurityContext
may be Jersey specific, as it's not stated in the spec, but I'm not sure.Now those types mentioned above don't really do much for you because they are all request contexts and nothing to set the response.
One Idea though is to use a
javax.ws.rs.container.ContainerResponseFilter
, along with theHttpHeaders
to set a temporary request header. You can access that header through theContainerRequestContext
passed to thefilter
method. Then just set the response header through theContainerResponseContext
, also passed to thefilter
method. If the the header is not specific to the context of that resource method, then it's even easier. Just set the header in the filter.But let's say the header is dependent on the execution of the resource method. Then you could do something like
Then the
ContainerResponseFilter
might look something like thisAnd just so only the singleton classes run through this filter, we can simply use a
@NameBinding
annotationThis is the only way I can think to handle this situation.
Resources:
The correct answer seems to be to inject an
HttpServletResponse
in the member variable of the implementation, as I noted that another post had indicated.Even though peeskillet indicated that the semi-official list for Jersey doesn't list
HttpServletResponse
as one of the proxy-able types, when I traced through the code at least RESTEasy seems to be creating a proxy (org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy@xxxxxxxx
). So as far as I can tell, thread-safe injection of a singleton member variable seems to be occurring.Returns a JSON representation of the instance of
bar
with a status code 200 and headerheader-name
with valueheader-value
. It should look something along the lines of: