Is it possible, that a session-scoped backing bean is accessed by multiple threads at the same time?
The servlet spec says, it is possible:
Multiple servlets executing request threads may have active access to the same
session object at the same time. The container must ensure that manipulation of
internal data structures representing the session attributes is performed in a thread
safe manner. The Developer has the responsibility for thread safe access to the
attribute objects themselves. This will protect the attribute collection inside the
HttpSession object from concurrent access, eliminating the opportunity for an
application to cause that collection to become corrupted.
However I could not make the server (JBoss) use different threads for the same session. When I opened multiple tabs and started a long running request in one tab, and then started a request in another tab, the second tab had to wait for a response until the action started in the first tab was completed.
I also verified this by blocking the thread with a breakpoint in the backing bean. It was not possible to do anything in other tabs of the same session until I resumed the thread.
Despite this we have some strange exceptions in the production log and so far the only possible explanation we have is, that multiple threads concurrently access the same session-scoped backing bean.
Yes, A Servlet session is thread safe. But, if you are putting mutable object in the session. The application should take care of the synchronization.
In your case, if your Bean is Mutable i.e, has state. Yes it has to be thread safe.
And about your test case, it depends on the browser you are using. Most browsers support upto 6 connections in parallel for every server. But, Not sure if they use parallel connections if there have cookies.
Related
What does someone mean when I am asked that whether my web application is thread safe or not , considering that I have not used Multiple threads in my webapplication.
In a normal web-application Servlet treats as Singleton class, it means if you are using instance variable in Servlet that is not thread safe in that case it will create an issue for multiple request that is served simultaneously.
A Java servlet container / web server is typically multithreaded. That means, that multiple requests to the same servlet may be executed at the same time. Therefore, you need to take concurrency into consideration when you implement your servlet.
Read more...
What does someone mean when I am asked that whether my web application is thread safe or not
You have to make sure that all the Servlet/JSP are thread-safe. Do it for all server side classes that is treated as Singleton.
I have not used Multiple threads in my webapplication.
Container/web server starts a new thread for each request.
The servlet specification requires a web application to be thread safe, because the servlet container may (and usually does) process requests concurrently. That is, even if you do not start any threads of your own, the servlet container will, and you must ensure your code is still correct in that case.
That involves protecting any objects shared by several threads (such as the contents of the HttpSession, or any singleton objects) from concurrent access.
An excellent answer to a similar question is witten by BalusC here. Also have a look at Tomasz's answer
Generally, instance variables or state can be shared across threads (threads created by application or the container). So any class(object) that exposes its state for modification, can be considered unsafe. So if your service layer calls some data access object method and the dao is an instance variable inside the service class, the question to ask is this - can this dao or the state of that dao itself be changed by some other client?
You can make your objects immutable. Your custom objects, dates and collections can be mutable. Some of the examples where even getter methods can be dangerous are collections, dates, etc. Use something like ConcurrentHashMap or return a list something like Collections.unmodifiablelist
Another example, instead of returning this.someDate, you should write
public Date getSomeDate() {
return new Date(someDate.getTime());
}
This way some other thread (which may have been spawned by container for another request from another user) holding a reference to the variable someDate will not be able to mess up with this thread.
If you cannot make the state of an object immutable because you want to allow its clients to change its state, you can make all the clients of that object agree to share the state. So if one thread changes the state of a shared object and another thread is ok with the state changed by the first thread, then such monostate object can be ok to have in your application.
As other answers have mentioned the container spawns threads even if your application does not. I have focused here mainly on the topics not directly covered in the answers here so as to avoid duplication. Hope this helps.
I am using approach from the "Accessing scoped proxy beans within Threads of" answer. However I am seeing rare deadlocks involving RequestAttributes object. The main reason of the deadlock is between the synchronized (this.sessionAttributesToUpdate) statement in the object and servlet session hash-map. Normally the instances of the object are created for each request, so they don't clash, but if I pass the object to another thread to use the session beans, the same object is used and it causes deadlock sometimes.
The deadlock happens if current http request is not completed while the another thread starts using a session bean passed with RequestContextHolder.setRequestAttributes.
I think this guy mentions the same problem, but his question is unanswered: Session scoped bean encountering deadlock.
So, any ideas how to avoid the deadlock?
Here's an answer that provides alternative solution considering the objective is to calculate something in background while user is navigating pages.
Possibility 1:
Create a service bean with processing method that is annotated with #Async (http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html) that returns a result of computation in a Future object. Store the Future object in the session. Access the result in subsequent requests through Future object if task is completed. Cancel the the task via Future.cancel if session is to be destroyed before task is completed.
Possibility 2:
Take a look if new features of Spring 3.2 and Servlet 3.0 async processing can help you:
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-async
Possibility 3:
Emulate a task queue. Create a singleton service that can put objects to structure like ConcurrentMap where key would be some job id (you can than store key into session) and value the result of background processing. Background thread would then store objects there (this is perhaps not much better than accessing session directly, but you can make sure it's thread safe).
Our portlets keep state in the HttpSession, which is shared by all request processing threads for the same session.
The portlet spec (JSR-168) writes:
PLT.5.2.4.3 Multithreading Issues During Request Handling
The portlet container handles concurrent requests to the same portlet by concurrent
execution of the request handling methods on different threads. Portlet developers must
design their portlets to handle concurrent execution from multiple threads from within the
processAction and render methods at any particular time.
I wonder how I am supposed to achieve that? Sure, I can use synchronization to achieve mutual exclusion during both processAction and render, but I don't see how I can enforce atomicity of request processing as a whole. In particular, I worry about the following scenario:
Thread 1 executes processAction, loading data into the session for later rendering
Thread 2 executes processAction, discarding that data from the session
Thread 1 executes render, reading the data to render from the session, and throws a NullPointerException because the prepared data is no longer there ...
How is that scenario usually prevented? In particular, when using the JBoss portlet bridge to adapt JSF to a Portlet environment?
I'd say that if there are two portlets operating on the same data, especially one reading it while the other deletes it, there's most likely a serious flaw in the design.
You might then want to store the data per portlet/thread, i.e. if portlet1 reads some data you should write lock it until reading is finished and put it into the session using a unique key.
If it is legal to delete data that should be rendered, then you should account for that and check again during render.
From the javadoc for Session it states:
A Session object is a single-threaded context for producing and consuming messages.
So I understand that you shouldn't use a Session object from two different threads at the same time. What I'm unclear on is if you could use the Session object (or children such as a Queue) from a different thread than the one it created.
In the case I'm working on, I'm considering putting my Session objects into a pool of available sessions that any thread could borrow from, use, and return to the pool when it is finished with it.
Is this kosher?
(Using ActiveMQ BTW, if that impacts the answer at all.)
I think the footnote from section 4.4 in the JMS 1.1 spec sheds some light:
There are no restrictions on the number of threads that can use a Session object or those it creates. The restriction is that the resources of a Session should not be used concurrently by multiple threads. It is up to the user to insure that this concurrency restriction is met. The simplest way to do this is to use one thread. In the case of asynchronous delivery, use one thread for setup in stopped mode and then start asynchronous delivery. In more complex cases the user must provide explicit synchronization.
By my reading of the spec what you want to do is OK, provided you correctly manage concurrency.
Sadly the JMS docs are often not written as clearly or precisely as we might like :o(
But reading the spec I'm now pretty convinced you really shouldn't access the session from other threads, even if you guarantee there's no concurrent access. The bit of the javadoc that swung it for me was:
Once a connection has been started,
any session with a registered message
listener(s) is dedicated to the thread
of control that delivers messages to
it. It is erroneous for client code to
use this session or any of its
constituent objects from another
thread of control. The only exception
to this is the use of the session or
connection close method.
Note the clear use of 'thread of control' and the singling out of 'close()' as the only exception.
They seem to be saying that even if you're using asynchronous message consumption (i.e. setMessageListener) - which means you get called back on another thread created by JMS to receive messages - you're never allowed to touch the session or related objects again from any other thread, because the session is now 'dedicated' to the JMS delivery thread. For example, I assume this means you couldn't even call message.acknowledge() from another thread.
Having said that, I only just noticed that we haven't been obeying this constraint, and have yet to notice any ill effects (using SonicMQ). But of course if you don't obey the standard, all bets are off, so I guess we need to obey the 1-thread 1-session rule to stay safe.
Are the threadlocals variables global to all the requests made to the servlet that owns the variables?
I am using resin for the server.
Thanks for awnser.
I think I can make my self more clear.
The specific Case:
I want to:
initialize a static variable when the request starts the execution.
be able to query the value of the variable in the further executions of methods called from the servlet in a thread safety way until the request ends the execution
Short answer: Yes.
A bit longer one: This is how Spring does its magic. See RequestContextHolder (via DocJar).
Caution is needed though - you have to know when to invalidate the ThreadLocal, how to defer to other threads and how (not) to get tangled with a non-threadlocal context.
Or you could just use Spring...
I think they are global to all requests made with that specific thread only. Other threads get other copies of the thread-local data. This is the key point of thread-local storage:
http://en.wikipedia.org/wiki/Thread-local_storage#Java.
Unless you check the appropriate option in the servlets config, the servlet container will use your servlet with multiple threads to handle requests in parallel. So effectively you would have separate data for each thread that's up serving clients.
If your WebApplication isn't distributed (runs on multiple Java Virtual Machines), you can use the ServletContext object to store shared data across requests and threads (be sure to do proper locking then).
Like Adiel says, the proper way to do this is probably to use the request context (i.e. HttpServletRequest), not to create a ThreadLocal. While it's certainly possible to use a ThreadLocal here, you have to be careful to clean up your thread if you do that, since otherwise the next request that gets the thread will see the value associated with the previous request. (When the first request is done with the thread, the thread will go back into the pool and so the next request will see it.) No reason to have to manage that kind of thing when the request context exists for precisely this purpose.
Using ThreadLocal to store request scoped information has the potential to break if you use Servlet 3.0 Suspendable requests (or Jetty Continuations)
Using those API's multiple threads process a single request.
Threadlocal variables are always defined to be accessed globally, since the point is to transparently pass information around a system that can be accessed anywhere. The value of the variable is bound to the thread on which it is set, so even though the variable is global, it can have different values depending on the thread from which it is accessed.
A simple example would be to assign a user identity string to a thread in a thread local variable when the request is received in the servlet. Anywhere along the processing chain of that request (assuming it is on the same thread in the same VM), the identity can be retrieved by accessing this global variable. It would also be important to remove this value when the request is processed, since the thread will be put back in a thread pool.