First a bit of background. The project is an MVC and it uses Guice to
create a Workflow. Each step of the Workflow does part of the work for
the MVC, until finally an MVC action is invoked and then a result is
generated and sent back to the browser. This Workflow is constructed
in a JEE Filter and then invoked, so, all of the MVC objects are
created at the start of each request and injected before being called.
Okay, now the issue:
I'm using the standard ThreadLocal to store the request and allow it
to be injected into any class using a Provider. The class that is
injected might want to wrap the request and change something, such as
the request URI. They do this by wrapping the request and setting it
back into the ThreadLocal. However, since Guice injects my entire
application up front, everything has already been injected with the
original HttpServletRequest upfront.
Some failed attempts at solving this:
First, I figured I would create a proxy to the HttpServletRequest and
inject that rather than the request itself. Whenever a method is
invoked on the proxy it would grab the real request from the
ThreadLocal and use that one to proxy to. If someone wrapped the proxy
and set it back into the ThreadLocal, that would be grabbed by the
next class in the workflow. This causes some nasty infinite recursions
in some edge cases, specifically if the proxy hasn't been
"initialized" and gets wrapped and set back into the ThreadLocal. Bad
stuff happens. I have a fix for this in the ThreadLocal that looks at
the request being set and if it is a HttpServletRequestWrapper and the
request is is wrapping is a proxy it removes the proxy and re-wraps
everything. This is somewhat nasty though.
Second, I figured I would NOT make the request injectable and instead
inject the Provider. The Provider would also have a setter method that
would allow for wrapping to take place. This works and is probably the
best solution because it also provides a good wrapping API. However,
it is a little rough and introduces a wide spread dependency on the
provider.
Next, I could just remove the proxy, make the request NOT injectable
and just have everyone get it from the ThreadLocal. This also
introduces a dependency and to a static method to boot.
Lastly, I change everything to use the JEE Filter methodology and pass
the request around everywhere via method calls. This isn't too bad,
but still somewhat annoying. Plus, the request still NOT injectable.
If you aren't passed the request, you can't ever get it.
None of these are great solutions and I've been brainstorming for a
while trying to think of something better. Anyone have ideas or
solutions they have implemented to solve this?
Thanks,
-bp