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.
Related
As we know Tomcat has approx 200 threads and Jetty has some default count threads in their respective thread pools. So if we set something in a ThreadLocal per request, will it be there in the thread for life time or will Tomcat clear the ThreadLocal after each request.
If we set something in userContext in a filter do we need to clear it every time the filter exits?
Or will the web server create a new thread every time, if we don't have a thread pool configuration?
public static final ThreadLocal<UserContextDto> userContext = new ThreadLocal<>();
Yes, you need to clear ThreadLocal. Tomcat won't clear ThreadLocals.
No, new thread is not created every time. A thread from the pool is used to serve a request, and returned back to pool once request is complete.
This not only applies to Tomcat, it applies to Jetty and Undertow as well. Thread creation for every request is expensive in terms of both resources and time.
No, Tomcat will not clear ThreadLocals that your code creates, which means they will remain and could pollute subsequent requests.
So whenever you create one, make sure you clear it out before that same request or whatever exits.
It should also be noted that subsequent requests - even using the identical URL - could well be executed in a totally different thread, so ThreadLocals are not a mechanism for saving state between requests. For this, something like SessionBeans could be used.
If you put something in a ThreadLocal in a Thread that is not 100% under your control (i.e. one in which you are invoked from other code, like for a HTTP request), you need to clear whatever you set before you leave your code.
A try/finally structure is a good way to do that.
A threadpool can't do it for you, because the Java API does not provide a way to clear a thread's ThreadLocal variables. (Which is arguably a shortcoming in the Java API)
Not doing so risks a memory leak, although it's bounded by the size of the thread pool if you have one.
Once the same thread gets assigned again to the code that knows about the ThreadLocal, you'll see the old value from the previous request if you didn't remove it. It's not good to depend on that. It could lead to hard to trace bugs, security holes, etc.
I have 2 servers.
Server A has a cron system, which given a trigger requirement, calls the Server B through a servlet
In server B, when receiving the server A's call, i store serveral informations on the HttpSession and then i start a new thread, so i could free server A.
I have found, thought logs, that in several cases, when the thread in Server B is reaching the HttpSession, the values that were set before are different. They are not null or blank, they have acctual values, but not the ones i put.
The server A fires like, 30 notifications each 5 minutes. This means i will have several concurrent threads.
Why is the HttpSession being overriden by another thread?
Section 2.3.3.4 of the Servlet Specification v 3.0 says,
If a thread created by the application uses the container-managed
objects, such as the request or response [or session] object, those objects
must be accessed only within the object’s life cycle [...].
HttpSession objects are certainly container-managed objects, but their life cycle is not clearly defined by the Servlet specification. It seems plausible, however, to consider the life cycle to end when the session has been invalidated, whether explicitly or by time out, and no request belonging to that session is being serviced. After that point, if you continue to access the session object then all bets are off. In particular, the container is permitted to cache and re-use managed objects, including session objects.
If your server A does not participate in session tracking, then every request will be assigned to a new session, and each one's lifetime will be a single timeout period. In this case, you could consider setting the [default] timeout long enough to ensure that sessions do not time out during the course of one computation (but see below). If your server A does participate in session tracking, on the other hand, then the session object will be open for modification on each request.
Whether server A participates in session tracking or not, however, it is poor form for an application thread such as those you start manually to access container-managed objects. It would be better all around to use a different mechanism to provide data to them.
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 :)
I am confused about how should I handle http sessions in a standalone java app. Here are the details :
The java client connects to 3 tomcat 7 servlets.
When the client boots up, it starts 2 scheduled threads /downloader and uploader/ polling 2 of the servlets every 3mins. They both retrieve and store the jsessionid cookie in private fields in their respective classes.
This results in 2 sessions in tomcat reused for the lifetime of the webapp. So far so good.
There is a 3rd service /connected to the 3rd servlet/ using multiple instances of a threaded "WebDispather" class which retrieves and stores the session similarly to the above mentioned threads but this time - in a private static field.
The dispatcher is heavily used, there might be as many as 150 instances running concurrently depending on the load. Dispatcher threads hit the servlet ever second or so.
Making the dispatcher sessionid field non static creates a session per instance - not good.
What are the implications of having all dispatcher threads bound to the same tomcat http session?
Thank you
EDIT:
although dispather threads a bound to same session the session itself doesn't hold any information.
Servlet processes only the request params.
I.e. dispatcher 1:
localhost/messagecontrol?id=123&state
Dispatcher thread 2:
localhost/messagecontrol?id=123&state=finished
//Servlet processes and forgets id and state
As far as I can see the implications are all client threads will share the same session information, if any information not meant to be shared this will be a bug on your code
IF you're worried about the number of threads created (performance-wise), consider implementing a thread pool in your code.
we have been using ThreadLocal so far to carry some data so as to not clutter the API. However below are some of issues of using thread local that which I dont like
1) over the years the data items being carried in thread local has increased
2) Since we started using threads (for some light weight processing), we have also migrating these data to the threads in the pool and copying them back again
I am thinking of using an in memory DB for these (we doesnt want to add this to the API). I wondering if this approach is good. What r the pros and cons.
ok here is a simple scenario
user logs in and submits a request
system establishes context for this entire request which include
- unique id for this request
- username
- system looged in (user can log into multiple systems)
- some DOMAIN EVENTS for later use
the request passes through multiple logical layers (presentation, business domain,
rules, integration) etc
in the integration layer, we borrow few threads from pool to parallel pull data from
multiple partners. each of the pulls need some data stored earlier in thread local, so we migrate those to the pooled threads
after all data is received from partners, we migrate back the new thread local data accumulated in the child threads to the main thread
at the end of the interaction we persist the DOMAIN events to DB
you may want to introduce a request context: http://www.corej2eepatterns.com/Patterns2ndEd/ContextObject.htm
you can handle creation/destruction of such an object in a Filter if you're using a WebContainer or an Interceptor if you're using an ApplicationServer.