Search code examples
javajerseyjax-rs

Jersey + Spring Context Outside of Controller


I have a Spring bean that needs information from the request, but isn't directly called from the controller (although it could be - but I'd like to try this without it)

Basically, my API makes requests to other services over thrift. When it makes the request, there's a service call like this:

authenticationService.authenticate(null, "username", "password");

The first parameter (the null) is usually a "placeholder" instance of a request context. The request context contains information about the user making the request, the originating IP, etc. This way, I get all of the details about the original caller without letting my API infrastructure leak into the backend.

However, to do this, I have an InvocationHandler that intercepts method calls made against a proxy of my service interfaces. Inside of that proxy handler, I have a RequestContextFactory wired in that creates instances of a RequestContext. Inside of this factory, I need to get information from the request. Particularly, the SecurityContext, so I can identify the user making the call.

Right now, I have:

@Provider
@Component
public class WebRequestContextFactory implements RequestContextFactory {
    @Context private ContainerRequest containerRequest;

    public RequestContext createRequestContext() {

    }
}

Unfortunately, containerRequest is always null.


Solution

  • You can use ServletRequestAttributes to get the information from the request and the ServletRequestAttributes can be obtained from RequestContextHolder:

    ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                    .currentRequestAttributes();
    

    If the request is processed by the Spring DispatcherServlet, there is no need of any special setup. DispatcherServlet already expose all relevant state. But if the requests are processed outside of Spring's DispatcherServlet, then you need to add javax.servlet.ServletRequestListener in your application's web.xml file:

        <listener>
            <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
        </listener>
    

    This will associate the request with the current thread and the associated request attributes can then be retrieved via RequestContextHolder.