On Sun, Nov 1, 2009 at 8:08 PM, Chris Hubick <chris_at_hubick.com> wrote:
> On Sun, 2009-11-01 at 19:36 -0800, Craig McClanahan wrote:
>> On Sun, Nov 1, 2009 at 6:59 PM, Chris Hubick <chris_at_hubick.com> wrote:
>> > OK, so I finished enough of my conversion to the JAX-RS API to re-enable
>> > threading, and immediately got a ConcurrentModificationException inside
>> > java.util.ArrayList$Itr.next() when multiple threads (all inside the
>> > request scope) try to simultaneously iterate (read-only) through the
>> > List<Locale> returned by HttpHeaders.getAcceptableLanguages().
>> >
>>
>> If you are accessing servlet request objects from more than one
>> thread, you're breaking the rules of the Servlet Specification,
>> whether or not you are using Jersey.
>
> As mentioned in my initial email to this thread, when using the Servlet
> API, I perform my own synchronization around any access I make to those
> methods. I am not breaking any rules.
>
> This question is, however, not about the Servlet API, which I mentioned
> I am migrating away from.
Well, you're perhaps migrating away from *direct* use of these APIs,
but when you deploy Jersey in a webapp you're still using them
indirectly :-).
> This question is about the thread safety of
> JAX-RS API methods, which is determined by that specification,
> regardless of whether it is implemented on top of the Servlet API or
> not.
>
>> What are you doing that needs to
>> access this kind of thing from multiple threads?
>
> I utilize the "Acceptable Languages" ("Accept-Language" header) to
> determine the language of content to return to the client, as designed.
>
> I have multiple threads, each generating separate pieces of that
> content, which are later aggregated together.
>
>> If there is indeed a valid use case for this, then yes, you are going
>> to need to take responsibility for synchronizing access yourself.
>
> Jersey could choose to offer a thread-safe JAX-RS implementation, even
> if not strictly required by the specification. I am requesting
> clarification as to if there is an intention to offer such a thing, as
> well as the thread-safety requirements of the JAX-RS specification.
If you are operating inside a servlet container, you need to obey the
rules of the entire stack. If you're deploying a standalone Java SE
app, one might argue that these don't apply ... but the concurrency
rules stated in Section 5.1 of the JAX-RS spec still do apply. In
particular, thread local variables are explicitly endorsed as a
mechanism to pass per-request information without explicitly including
it as method parameters. Trying to access per-request data, passed in
thread locals, from multiple threads for the same request will fail
because the data will only be visible to the original request
processing thread, even if the passed objects happened to support
concurrent access.
(This, by the way, is the same reason that an EJB is prohibited even
starting additional threads ... the app servers use thread local
variables to manage things like the transaction context.)
The only safe ways to deal with this are either synchronize access to
the underlying data, or (better) pull out everything you need as part
of original processing in the resource method, then pass your own data
objects to the various threads generating the content pieces. This is
also likely to improve your overall architecture's modularity and
testability, because the content producing logic in each thread would
no longer be tied to either Servlet or JAX-RS APIs directly.
>
> Thanks.
>
> --
> Chris Hubick
> mailto:chris_at_hubick.com
> http://www.hubick.com/chris/
Craig