jersey
jersey copied to clipboard
ServletContext is invalid in MessageBodyWriter if handling async CompletionStage
My resources return CompletionStage<MyType> and then I have a MessageBodyWriter for MyType. The issue is that if the CompletionStage is not immediately complete upon returning from resource method then the MessageBodyWriter fails because the ServletContext accessed from HttpServletRequest has already been invalidated and set to null (by Jetty 11).
Is there a way around this so that the HttpServletRequest (injected with Provider<HttpServletRequest> in MessageBodyWriter constructor and accessed in the writeTo method) becomes valid again? Or is this just a bug that needs to be fixed in Jersey?
The MessageBodyWriter
is a singleton, it is not recreated for each request. Whatever injected, it would not be aligned with the current request.
Possibly, you can try to inject InjectionManager
class and try to call injectionManager.getInstance(HttpServletRequest.class)
in the writeTo
method.
The lifecycle of HttpServletRequest
class is handled by the Servlet container, i.e. by Jetty. If Jetty invalidates, Jersey cannot prevent that.
I'm injecting Provider<HttpServletRequest>into the MessageBodyWriter constructor, which in writeTo returns a proxy to the correct object. This part is fine. The issue is that because of the asynchronous nature of returning a CompletionStage<MyType> from the resource the request has not been reassociated correctly with the servletcontext. There's some scope fixing (or similar) that needs to happen before calling writeTo, when the result is a CompletionStage. The main issue is that HttpServletRequest.getServletContext needs to return the correct value.
There are two possibilities:
- The injected HttpServletRequest provided does not belong to the current request
- Jetty ended the current request and set the HttpServletRequest.getServletContext to return null.
You might be trying to provide request-scoped information outside of a request. The JAX-RS way which avoids the injection is to utilize WriterInterceptor.getProperty during the entity writing and setting up the property in the resource class or in the ContainerFilter where the request-scoped information is available.