I know that every request is served by a servlet thread, but will it be possible for one user session, two request served by two different thread?
If the situation above really happens, what about thread local variable stored by first request-serving thread be read by second request-serving thread?
I'm afraid that if I store user credential in Spring Security's SecurityContextHolder(which uses thread local variable) in first thread, the second thread will not be able to access the user credential...
I know that every request is served by a servlet thread, but will it be possible for one user session, two request served by two different thread?
Yes, that's possible.
I'm afraid that if I store user credential in Spring Security's SecurityContextHolder(which uses thread local variable) in first thread, the second thread will not be able to access the user credential...
Security is established separately for each request by Spring, you do not have to handle this yourself.
No, one request will not be served by several threads. What can really happen is serving of 2 requests by one thread. This is the reason that you should be very careful using thread local variables yourself. However you can trust Spring framework: it does things right. It can for example use session or request ID when using thread local, so 2 request being processed by one thread will not be confused.
Two separate requests of the same user are handled (most likely) by two different threads.
I am not sure what Spring does, but the Servlet api provides a way to retrieve data that is specific to the user session (how the server tracks the session is irrelevant, but have a look at cookies and url rewriting).
Now, If I wanted to have the user credentials on a threadlocal variable (which is not unusual, as the ThreadLocal pseudo-singleton is the most convenient way of injection I know), I would store them on the users HttpSession (which is persistent across all requests of the same user) and use a servlet filter to put them on the threadlocal at the beginning of each request.
I hope this makes things a bit clearer for you. I find it is better to know what's happening under the hood even when using the most up to date framework :)
Related
I've sent the same request to a Spring MVC project with two browsers, but I got the same threadlocal, so the instances in threadlocal are the same.,Why?
Threadlocal is bound to a thread / process, not to a session. JVM does not really know or care about the concept of web sessions, that's a higher level of abstraction.
It is well possible that two web requests with two sessions are handled by the same thread. Most servers use a pool of threads that they reuse rather than create a new thread for each request or even session. If the processing of the first request leaves something in the threadlocal after it's done processing the request, well, that's what the next request will find there.
Store the data you need to keep per-session in HttpServletRequest.getSession() instead.
If multiple requests are handled by a server to run a single servlet then where we need to take care of synchronization?
I have got the answer from How does a single servlet handle multiple requests from client side how multiple requests are handled. But then again there is a question that why we need synchronization if all requests are handled separately?
Can you give some real life example how a shared state works and how a servlet can be dependent? I am not much interested in code but looking for explanation with example of any portal application? Like if there is any login page how it is accessed by n number of users concurrently.
If more than one request is handled by the server.. like what I read is server make a thread pool of n threads to serve the requests and I guess each thread will have their own set of parameters to maintain the session... so is there any chance that two or more threads (means two or more requests) can collide with each other?
Synchronization is required when multiple threads are modifying a shared resources.
So, when all your servlets are independent of each other, you don't worry about the fact that they run in parallel.
But, if they work on "shared state" somehow (for example by reading/writing values into some sort of centralized data store); then you have to make sure that things don't go wrong. Of course: the layer/form how to provide the necessary synchronization to your application depends on your exact setup.
Yes, my answer is pretty generic; but so is your question.
Synchronization in Java will only be needed if shared object is mutable. if your shared object is either read-only or immutable object, then you don't need synchronization, despite running multiple threads. Same is true with what threads are doing with an object if all the threads are only reading value then you don't require synchronization in Java.
Read more
Basically if your servlet application is multi-threaded, then data associated with servlet will not be thread safe. The common example given in many text books are things like a hit counter, stored as a private variable:
e.g
public class YourServlet implements Servlet {
private int counter;
public void service(ServletRequest req, ServletResponse, res) {
//this is not thread safe
counter ++;
}
}
This is because the service method and Servlet is operated on by multiple thread incoming as HTTP requests. The unary increment operator has to firstly read the current value, add one and the write the value back. Another thread doing the same operation concurrently, may increment the value after the first thread has read the value, but before it is written back, thus resulting in a lost write.
So in this case you should use synchronisation, or even better, the AtomicInteger class included as part of Java Concurrency from 1.5 onwards.
I'm trying to implement a tricky thing and need some fresh ideas.
The problem is:
Imagine Component1, that is performing some action for each User in a collection.
Just like
for (User user : users) {
doSomeStuff(user);
}
These actions have some common parts, that are time-consuming, so the goal is to perform them only once (they include some database queries and so on).
Imagine one of this time consuming methods:
public Object buildSomething(Object context) {
// some business logic here
}
The idea was to store the result and share it for other users, like this
public Object buildSomething(Object context) {
if (sharedResource.contains('something') {
return sharedResource.get('something');
} else {
// some business logic here
sharedResource.put('something', something)
return something;
}
}
The riddle is - how to implement this shared resource?
Must say, this is a huge multi layer web application and we can't just change doSomeStuff method and add a context holder parameter there, or something similar.
I analyzed the following variants:
Session scope bean (the one that makes the buildSomething stuff)
Problems: User can logout from application, login with another username/pass, he will still have same Http session and that means he will get the same bean with previous request state
upd: Another problem of using session scope is spring based thread pool scheduler, that can invoke Component1 without any http session.
ThreadLocal variable
Problems: We are in a web application context, and when thread is returned to pool, it can be used for other user requests
I tried to find a workaround for second problem and my question is:
Is it possible to analyze stack trace elements and ensure, that two invocations of buildSomething method were caused by a single user request?
Tx for attention
I think session scoped beans are the better solution. You can manage when a session is destroyed or created. You need to call "HttpSession.invalidate()" when a user logs out.
There is a good article about session lifecycle management.
http://docstore.mik.ua/orelly/java-ent/servlet/ch07_05.htm
You also can use the HttpSession utils to store information in session (such as username).
Salut!
I decided to post my solution to this problem, that now works on production server.
It is based on a ThreadLocal variable, that holds the information in a request scope.
The original problem was in a fact, that different clients can reuse a single thread, because threads are stored in a pool. This fact didn't allow to use session beans and thread locals as is.
So I had to review all entry points, where user requests come to my application layer. When I detected a request, I cleaned thread local context for a request. It worked, because there are only few ways for request to come to application layer: it could be a service request from another layer, that could be intercepted with AOP and a scheduler job, that can be intercepted by custom ThreadPoolExecutor.
This is a recent interview question to my friend:
How would you handle a situation where users enter some data in the screen and let's say 5 of them clicked on the Submit button *the SAME time ?*
(By same time,the interviewer insisted that they are same to the level of nanoseconds)
My answer was just to make the method that handles the request synchronized and only one request can acquire the lock on the method at a given time.
But it looks like the interviewer kept insisting there was a "better way" to handle it .
One other approach to handle locking at the database level, but I don't think it is "better".
Are there any other approaches. This seems to be a fairly common problem.
If you have only one network card, you can only have one request coming down it at once. ;)
The answer he is probably looking for is something like
Make the servlet stateless so they can be executed concurrently.
Use components which allow thread safe concurrent access like Atomic* or Concurrent*
Use locks only where you obsolutely have to.
What I prefer to do is to make the service so fast it can respond before the next resquest can come in. ;) Though I don't have the overhead of Java EE or databases to worry about.
Does it matter that they click at the same time e.g. are they both updating the same record on a database?
A synchronized method will not cut it, especially if it's a webapp distributed amongst multiple JVMs. Also the synchronized method may block, but then the other threads would just fire after the first completes and you'd have lost writes.
So locking at database level seems to be the option here i.e. if the record has been updated, report an error back to the users whose updates were serviced after the first.
You do not have to worry about this as web server launches each request in isolated thread and manages it.
But if you have some shared resource like some file for logging then you need to achieve concurrency and put thread lock on it in request and inter requests
I am running into a situation where I use ThreadLocal static variable to hold a bean that contains various metrics values from different classes during the lifecycle of the request. In a filter I create the bean and set it in a thread local variable and remove it from the thread local variable in the same filter after request has been processed. What I am running into is that the bean containing values from other requests! The only explanation for this is the thread being shared to process multiple requests at the same time. So the question in the title.
While one thread will generally process a single request (speaking about tomcat, for sure), the thread may process multiple requests over time but not w/o finishing the existing request, unless using include/forward alikes.
I'd VERY strognly recommend you to use attribute (setAttribute()) of the said request w/ your bean and use it for profiling. If you can't provide the request to various methods... well you are stuck w/ the ThreadLocal [which is not so bad solution].
Alternatively you can post the code how you install/remove the threadLocal bean.
Keep in mind that you have to to some managing the of that bean as well (it will not be available outside the request).
Edit: forgot to ask: do you use try/finally calling doFilter(...)?
the code should be like that
installBean();
try{
chain.doFilter(req, resp);
}finally{
Bean b = deinstallBean();
useTheMetrics(b);
//potentially, process exception, etc
}
It could also be that your filter is not always called in the sequence you expect it to be. Threads are reused to process multiple requests one after another, so if the removal of the value in the ThreadLocal does not happen, it will still be there when the thread processes its next request.
Yes, you can assume that a single thread will process each request.
Use a finally block to clear (set to null) the ThreadLocal in the filter after processing the rest of the chain. That will prevent data from previous requests from being mingled with the current request.