Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is ThreadLocal preferable to HttpServletRequest.setAttribute("key", "value")?

The servlet spec (see my previous question) guarantees that the same thread will execute all Filters and the associated Servlet. Given this, I do not see any use for passing data using HttpServletRequest.setAttribute if there is the option to use a ThreadLocal (assuming you clean up properly). I feel that there are two benefits to using ThreadLocal: type-safety and better performance because no string keys or maps are being used (except probably into a thread collection by (non-string) thread id).

Could someone please confirm if I am right so I can proceed with abandoning setAttribute?

like image 782
necromancer Avatar asked Apr 10 '12 21:04

necromancer


People also ask

When should I use ThreadLocal?

Java ThreadLocal is used to create thread local variables. We know that all threads of an Object share it's variables, so the variable is not thread safe. We can use synchronization for thread safety but if we want to avoid synchronization, we can use ThreadLocal variables.

Is ThreadLocal slow?

Rust thread-locals are slower than they could be. This is because they violate zero-cost abstraction principle, specifically the “you don't pay for what you don't use bit”.

What is the use of setAttribute in Servlet?

The setAttribute() method of a SimpleScriptContext class is used to set the value of an attribute in a given scope where the name of the attribute, the value of attribute and scope of the attribute is passed as parameters.

How do you clean ThreadLocal?

The java. lang. ThreadLocal. remove() method removes the current thread's value for this thread-local variable.


4 Answers

Is ThreadLocal preferable to HttpServletRequest.setAttribute(“key”, “value”)?

Depends on the concrete functional requirement.

JSF, for example, stores the FacesContext in a ThreadLocal. This enables you to access all of the JSF artifacts, including the "raw" HttpServletRequest and HttpServletResponse anywhere in the code which is executed by the FacesServlet, such as managed beans. Most other Java based MVC frameworks follow the same example.

As per your comment,

I primarily need to transport the User and EntityManager objects from the user and database Filters to the Servlet. I also find that these are frequently and unexpectedly needed in code further down the line and I am tempted to use them well beyond the Servlet (i. e. in nested code called by doGet). I feel there may be a better way for deeper code - suggestions?

As to the User example for which I assume that this is a session attribute, I'd rather follow the same approach as JSF. Create a ThreadLocal<Context> where the Context is your custom wrapper class holding references to the current HttpServletRequest and maybe also HttpServletResponse so that you can access them anywhere down in your code. If necessary provide convenience methods to get among others the User directly from the Context class.

As to the EntityManager example, you could follow the same approach, but I'd personally not put it in the same ThreadLocal<Context>, but rather a different one. Or, better, just obtain it from JNDI in the service layer, which would allow you more finer grained control over transactions. In any case, please make absolutely sure that you handle the commit/close properly. Taking over the persistence and transaction management from the container should be done with extreme care. I'd really reconsider the aversion against using the existing and well-designed APIs/frameworks like EJB/JPA, otherwise you'll risk a complete waste of time of reinventing all the already-standardized APIs and stuffs.

See also:

  • Retrieving Web Session from a POJO Outside the Web Container
  • Design Patterns web based applications
like image 90
BalusC Avatar answered Sep 26 '22 02:09

BalusC


thread local works better if you are trying to set "global" variables for code "behind" whatever is dealing with the HttpServletRequest. If you're using JSP/JSF pages, or some other web UI component that reads from HttpServletRequest, then you'll end up having to pull the information out of the ThreadLocal yourself. The 2 are not equivalent for most web programming.

like image 26
Jim Barrows Avatar answered Sep 25 '22 02:09

Jim Barrows


Using a ThreadLocal in this fashion implies your are relying on some type of singleton to maintain shared state. Ultimately, this is usually considered poor design since it has a number of drawbacks, including difficulty in encapsulating functionality, being aware of dependencies, and an inability to swap (or mock) out functionality.

The performance overhead of using attributes or a session is probably worth it as compared to dealing with the less usual proposal of ThreadLocal variables in a singleton. However, this of course depends on your specific use case and project. Using singletons in servlets as a way to maintain application state is somewhat common due to the difficulty in sharing application state with servlets (difficult to inject the dependencies), but it is unusual for those objects singleton objects to maintain per user state (outside of EJBs).

If using a session or setting a container object as an attribute, you would only be dealing with a single fetch via String (which would be O(1)), and then a single case to your container type (which that has specific accessors for all of the values you want). Calling code further down the line should take parameters as appropriate and avoid as best you can using any type of global or singleton.

Ultimately, before considering a somewhat unusual (although clever) solution in the name of performance, always test the straightforward implementation first to see if its performance is adequate. The 2ns that might be saved here are most likely insignificant compared to the 20+ms being spent on db queries and tcp connection establishment.

like image 36
Trevor Freeman Avatar answered Sep 26 '22 02:09

Trevor Freeman


I'd advise against ThreadLocal.

I can see why you're considering it, but I think you're falling into the premature optimization trap. ThreadLocals are essentially global variables - rarely a good design. The time-savings will be negligible. I guarantee this will never be the bottleneck in your server's throughput.

Using ThreadLocal may also give you problems if you want to start using asynchronous responses to some requests (e.g. to support long-polling) as the threading model is quite different.

like image 36
ᴇʟᴇvᴀтᴇ Avatar answered Sep 26 '22 02:09

ᴇʟᴇvᴀтᴇ