JAX-RS (Jersey) ExceptionMapper - injecting @Context into a static / singleton class - this works, but why?

I have a single instance class that implements ExceptionMapper. This is not a static class, but the class for which I know only one instance is created (I checked - the constructor is called only once).

My class uses @Context HttpServletRequest, and I can clearly notice that when calling ExceptionMapper.toResponse (), the @Context parameter "request" has a value that is relevant to the request in which the exception is thrown.

Doc says this is a really supported feature, and this is done using a "proxy".

I wonder how exactly this is implemented - how can one instance have different values โ€‹โ€‹of member variables at the same time?

Thanks,
AG

PS: here is the test code:

@Provider public class MyExceptionMapper implements ExceptionMapper<Exception> { public MyExceptionMapper() { System.out.println("CTOR!!"); } @Context HttpServletRequest req; public static boolean done = false; public Response toResponse(Exception ex) { if (!done) { done = true; Thread.sleep(10000); } System.out.println(req.getRequestURI()); return null; } } 

The handler method of my REST throws an exception, so when I execute the following two requests "in parallel" (the above dream ensures that the first one will not be completed when the second one arrives, and IMHO must change the same "req" field):

 - http://localhost/app/one - http://localhost/app/two 

my program prints:

 CTOR! http://localhost/app/one http://localhost/app/two 
+8
java rest jersey jax-rs
source share
1 answer

The easiest way to achieve the effect that you are observing is to have the HttpServletRequest nested object actually be a proxy object, a thread support delegate for the real HttpServletRequest . When you call methods on a delegate, all they do is search for the correct real object (for example, through a local thread variable) and transfer the call to it. This strategy is relatively simple to get right, and since it is an interface, we definitely do not need to worry about accessing the field (which is quite difficult for a proxy server).

There are several different ways to build such a proxy object. In particular, this can be done by directly implementing the HttpServletRequest interface, or it can be outlined through Java a general dynamic proxy mechanism (which can build proxies for any interface). There are other more complex features, such as generating runtime code, but they are not needed here. OTOH, I would not be surprised if HttpServletRequest was implemented; this is a somewhat important class for implementing JAX-RS ...

+5
source share

All Articles