HttpServletRequest.getSession(true) thread safe? - java

I see a lot of questions concerning whether the setAttribute and getAttribute methods on HttpSession are atomic. They are not. But, is the actual call of request.getSession(true) atomic per client?
For example if you had a servlet filter and a client issue two simultaneous calls which simultaneously reach a line request.getSession(true) would the same session object be returned? I assume such a thing would be container specific? Or are you gauranteed a syncronized getSession call per requesting client.

No, it is not.
Servlet Spec says...
2.3.3.4 Thread Safety
Other than the startAsync and complete methods, implementations of the request and response objects are not guaranteed to be thread safe. This means that they should either only be used within the scope of the request handling thread or the application must ensure that access to the request and response objects are thread safe.
If a thread created by the application uses the container-managed objects, such as the request or response object, those objects must be accessed only within the object’s life cycle as defined in sections 3.10 and 5.6. Be aware that other than the startAsync, and complete methods, the request and response objects are not thread safe.If those objects were accessed in the multiple threads, the access should be synchronized or be done through a wrapper to add the thread safety, for instance, synchronizing the call of the methods to access the request attribute, or using a local output stream for the response object within a thread.
And to your question?
Is it possible that two concurrent calls to getSession return a different HttpSession object even they come from the same client?
The answer is "Yes,
it will return two session objects,
two Set-Cookies Will be sent to the client
The latest Set-Cookie might override the first one

Not sure what you are really concerned here:
For example if you had a servlet filter, and a client issues two
simultaneous calls which simultaneously reach the line:
request.getSession(true)
would the same session object be returned?
It depends on what you mean by same session object, ie if you mean s1 == s2 or s1.equals(s2). I can't find anything stating that the object must be the same (==), but even if likely they are all different objects, they eventually can see the same logical session. Imagine these session objects as database clients: they are not the data, but they all view the same data, ie they read and write to a common place.
Now, to answer your question, we must decide if the client issued the second request before reading any other response from the same server: a session must be tracked with a piece of input (either in the URL or in the HTTP headers, in the form of a cookie), so we have the following scenarios:
Client makes request #1, gets a session, and sends the session ID back to the server in two simultaneous requests #2 and #3: they will share the session
Client makes request #1 and #2 almost at the same time, without any previous request to the same application. Since no input is provided to the server (no session ID) two new sessions are created, even if the clients don't hit the getSession() line at the same moment. Depending on the client application, this may be a bug or not.
So this is not a problem with threads at all. It just depends on the input supplied by the client. Same session ID, same session returned. Different (or no) session ID, different sessions.
Just for the sake of correctness, a logical client (a single program, like Firefox) can even make N requests in N separate threads on a N+ cores machine, but the network is usually shared. Assuming it has a multihomed machine, and each NIC is connected to a separate network, you'll need your servlet container to listen to multiple IP addresses and have N processors (or cores). This is just to say that there's no need to have two simultaneous calls, though it's perfectly possible that requests from the same client are processed in parallel and thus reach the same line at the same moment.

Nothing in the API suggests that the method is synchronized, though I don't know what is going on inside the method. Doing getSession(true) returns a new session if one doesn't exist. The check for an existing session and the creation of a new one is your critical section. If that is reached simultaneously by your threads, then two sessions will have been created and returned to your two different calling entities (filters will be applied before and, possibly, after your servlets so I don't see how you can do this, but for the question's sake let's assume it can happen). If a Session object already exists, then only that one will be returned.

Related

Do session objects take resources in my application? Won't garbage collector remove them?

I came across part in Head First JSP and Servlets page:241 where it says that we have to get rid of sessions as shown in this picture:
Later on they present methods invalidate() and setMaxInactiveInterval() that are used to reduce amount of stale sessions sitting in our server. After reading that, I got a little confused.
To start with, I get session object inside Servlet's code using HttpSession s = request.getSession() and then do some operations. Knowing that one request will make one thread for that Servlet, means that variable s will have scope only for that given thread. Once thread completes, variable s won't exist. Which further means session object in heap won't have active reference from s = garbage collected.
So in case there are no new requests, there shouldn't be any session object taking my resources, right? So why does the book tell me I have to get rid of them? Shouldn't garbage collector do its job alone?
Can someone correct me by saying what I wrote wrong? And are session objects really stored inside the heap? As I can't think of any other place where they could be.
There are quite e few things to unwrap here, so let's take them one by one.
Sessions and cookies
HTTP is a stateless protocol. What that means is that, for the server, each HTTP request is seen as independent for other HTTP requests. So if you make multiple requests to the same server, the server doesn't actually care if they come from the same client or not: a request is received and a response is generated, another request is received and another response is generated, and so on.
But there are however situations in which you need to identify a bunch of requests as coming from the same user as a longer interaction with the server, not just isolated requests. And here is where sessions and cookies come in.
A session identifies multiple interactions of the same user with the server and allows you to maintain the user identity and some useful data whose life time can span across all the requests. That means that a session is stateful as opposed to stateless.
A session is basically an object that the server holds in memory, that acts as a container for whatever data you want to save in between requests. This object can also be persisted on disk or inside a database (like for example, when you restart the server and don't want to lose the active sessions), but for the sake of simplicity just consider it an in memory object. And yes, it is stored inside the HEAP.
So, at the server, you can create a session object if your application needs to store state in between requests. But how do you identify the requests that belong to one session from other requests that don't belong to that session? The answer is cookies.
When an user makes their first request, the server can creates a session and give you back a SESSION_ID that gets added to the response. When the user then makes another request, the SESSION_ID is sent back to the server and now this request is identified as being part of a larger interaction, part of a session. Which session? That identified with the SESSION_ID. So the session is an object stored at the server and any requests that are part of that session interaction need to be identified with the SESSION_ID.
Garbage collecting sessions
Since the session object is a Java object that lives on the HEAP, it can be garbage collected. However, it's not that simple.
Compare for example the following pieces of code. This:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// ...
Object s = new Object();
// ...
}
with this:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// ...
HttpSession s = request.getSession();
// ...
}
In the first example, you create an object that is stored on the HEAP. Once the doGet method ends, this object is eligible for garbage collection because there are no more references to the object apart from s which goes out of scope when the method returns.
The key part here is "no more references". An object is eligible for garbage collection when the object can no longer be accessed from any of the live references that exist inside the JVM. When the doGet method ends, s is gone, so nothing points to the object you created. With a HttpSession things are different.
In the second piece of code, you don't create a session object, you ask the server to "give you" a session object. Imagine a Map retained by the server that contains session objects as values and SESSION_IDs are the keys to access them. When you ask the server to give you a session with HttpSession s = request.getSession() what it does is look at the SESSION_ID cookie from the request to look for a session associated with that request and give you a reference to the session object. Now you have two references to the session object, one held by the server in that Map of sessions, and one you store in s. When the doGet method ends, the s reference is gone, but the server still holds a reference to the session object (because it needs it for further requests that may arrive as part of the larger interaction). In this case, the session object is NOT eligible for garbage collection because it's reachable by a live reference within the JVM, the one held by the server.
So, if you don't get rid of sessions, the server has no way of knowing if that session is useful or useless because it doesn't know if there will be another request made later on to ask for it or not. So the session objects stay in the server forever. With a server being able to run for months or years without ever being restarted or shut down, the session objects can accumulate and consume all the memory. The garbage collector won't remove them because there are references to them hold by the server. You eventually get an OutOfMemory error and your server crashes.
Session timeouts
Of course, you don't want your server to crash. So you need to invalidate the sessions and tell the server that "Hey, I don't need that session object anymore. You can get rid of it". In that case the server removes it from its Map, and without any live references, it can now be garbage collected.
But since all this interaction happens over the network with HTTP, like the example in the book mentions, the browser can crash, the user's computer can crash, the user can just simply go away. So you might not get a chance to invalidate the session and tell the server it's OK to dispose of it, so it will stay there forever.
And here is where session timeouts come in. When you build your application, you also configure a session timeout to tell the server "Hey, if there is an inactivity on this session for X minutes, you can get rid of it". So now, if the client just goes away without invalidating the session, the server can have a fail safe mechanism to get rid of expired session so that they don't stick around forever in memory.
This question and its accepted answer give a good indication of what the HTTP Session mechanism is intended to achieve.
If you want to persist state between requests then that state needs to be stored somewhere. I believe that most application servers will use the heap for this by default. You can think of it being Map with the users session id as Key, and and object containing the stored data as its value.
This Map will grow forever unless you take action to remove objects from it, either by invalidating the session object when the user logs out or having some sort of inactivity limit which lets the application server itself tidy out the old entries after a set period of time.

Thread safety in java web application?

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.

Closing an HTTP Session for Writing in Java / Tomcat

When working on an ASP.NET application, I discovered that placing something in the session cache, or really, accessing variables in the session cache, caused my Ajax queries to stop being asynchronous. I learned that this was because the session basically blocks - if I fire two Ajax requests from my browser at the same time, and the first one takes a bit to return, the session is locked in the first request until that request is completed, at which point my second Ajax request starts working.
In PHP I gather that there is an option to close the session for writing (and / or open it in a read-only way) so that session variable access is non blocking and things stay asynchronous.
I'm building an application that will be Java, probably running on Tomcat (though I could change to some other container if I needed) and I am not able to find out whether Java has the same issue (session variable reads block) or has the same remedy (early close, read only mode). Has anyone encountered that issue before?
In Tomcat, HttpSession is implemented in org.apache.catalina.session.StandardSession (source here).
If you look at the source, you will see that calls to HttpSession.getAttribute(String) and HttpSession.setAttribute(String, Object) are pretty much channelled to a ConcurrentHashMap without any additional synchronization.
This means that these calls derive the contract of ConcurrentHashMap. Quoting its Javadoc:
retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. <..> Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove)
The table is internally partitioned to try to permit the indicated number of concurrent updates without contention. Because placement in hash tables is essentially random, the actual concurrency will vary.
It looks like blocking takes place because of threads synchronization of access to HttpSession as described in this SO answer
So, it must be that 2nd request is blocked only while 1st one is working with HttpSession (or if you have some shared lock which is held for long time by 1st request, but this has nothing to do with Tomcat).
Since this synch is required by Servlets spec, you shouldn't try to violate it. Instead, make your app so it minimizes time it needs to read from or write to HttpSession.
Additionally, as I wrote above, blocking may occur if you have additional lock which makes several requests execute sequentially. Try to make several thread dumps of Tomcat when you have sent 2nd request to Tomcat and see if there's any such lock which is waited by 2nd requet for.

Does a session-scoped backing bean have to be implemented thread-safe?

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.

threadlocal variables in a servlet

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.

Categories

Resources