users@jersey.java.net

Re: [Jersey] Re: Jersey's use of ThreadLocals

From: Paul Sandoz <Paul.Sandoz_at_oracle.com>
Date: Tue, 5 Oct 2010 15:18:58 +0200

On Sep 29, 2010, at 6:32 PM, jwheeler79 wrote:

>
> Hi Martin,
>
> I think the main exception of concern is the IllegalArgumentException.
> Again, I am able to get this to work with ThreadLocals, but not
> straight
> req/res. I also think this has something to do with this post, where
> paul
> sandoz calls injecting threadlocals a feature. I guess I am just
> trying to
> understand why one would inject threadlocals over the regular
> httpservletrequest/respose objects--why that's a feature and what's
> going on
> so I can wrap my head around things. Here's a recap of what's going
> on:
>
> This code doesn't throw an exception
>
> @POST
> @Path("{caseImageId}/attach")
> @Consumes(MediaType.MULTIPART_FORM_DATA)
> public void attach(@Context ServletContext context,
> @Context ThreadLocal<HttpServletRequest> reqTL, // thread
> locals
> @Context ThreadLocal<HttpServletResponse> resTL,
> @PathParam("caseFileId") Long caseFileId,
> @PathParam("caseImageId") Long caseImageId) {
>
> This code throws an IllegalArgumentException
>
> @POST
> @Path("{caseImageId}/attach")
> @Consumes(MediaType.MULTIPART_FORM_DATA)
> public void attach(@Context ServletContext context,
> @Context HttpServletRequest req, // no thread locals
> @Context HttpServletResponse res,
> @PathParam("caseFileId") Long caseFileId,
> @PathParam("caseImageId") Long caseImageId) {
>

What is your implementation doing? are you passing the references to
HttpServletRequest and HttpServletResponse to something else? If those
references cross thread boundaries then there can be issues (as to the
email you linked to).

 From the stack trace my guess is your implementation is forwarding to
another servlet. Then the IllegalStateException occurs when access the
proxy to the thread local because there is no thread local value set
for the thread, then GAE gets itself stuck in a loop.

I cannot quite ascertain what is going on here:

   java.lang.IllegalStateException
        at
com
.sun
.jersey.server.impl.ThreadLocalInvoker.invoke(ThreadLocalInvoker.java:
93)
        at $Proxy11.getSession(Unknown Source)
        at
org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:193)
        at
org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:
418)
        at
com
.google
.apphosting
.utils
.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:
70)
        at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:327)
        at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:126)
        at
info
.johnwheeler
.casemgmt.server.CaseImageResource.attach(CaseImageResource.java:95)


Can you try two things in the "attach" method:

1) For the injection of HttpServletRequest access a value on the req
e.g. req.getPath() and see if an IllegalStateException occurs?

2) For the injection of ThreadLocal<HttpServletRequest> req, check if
req.get() == null.

These will help ascertain if GAE is doing something odd with thread
local values.

Paul.