why use threadlocal?

Hi all,

I know I’ve asked this before, but it came up again in this
thread about Application#get
and this one
Static and ThreadLocal problem in Vaadin
. My question: is there a use case for using ThreadLocal objects that can’t be accomplished some other,
possibly simpler
, way?

If you know what you’re doing, then ThreadLocal is a great tool (when you need it – I don’t believe you need it in most web apps). But I think the learning curve for writing Java SE and Java EE apps has become very shallow compared with the old J2EE model. So people are moving to writing Java web apps, and Vaadin makes writing them simple enough that people can follow/copy/alter examples without really understanding what’s going on in the container. (This is to the credit of Vaadin, not to its detriment.)

So the existing examples out there using ThreadLocal may confuse people, in my opinion, and I’m wondering what problem they actually solve. I
think
the general use case is to have something that looks like a global variable, but which is scoped to a given user. If that’s the case, then there are at least 2 issues in my thinking:

  1. There’s always some other way to get the Application object (even if it involves a cast) to get some data that’s specific to the session. Alternatively, the main application object can pass ‘this’ into child components, but I know that’s not for everyone when apps get complicated.
  2. In a complicated application, other threads may be involved that have no access to the original ThreadLocal data.

I admit I have a blind spot about ThreadLocal usage, but I’m hoping that’s just because I haven’t seen the need (I generally know a fair bit about Java threads). This obviously isn’t an urgent request, but am curious about why people have used ThreadLocal objects in their Vaadin applications.

Cheers,
Bobby

Getting the current application and current locale is just a tiny bit too difficult and error prone in Vaadin 6.

I keep stumbling on the occasional situation where getApplication() returns null, deep down some listener, for some obscure reason – forgot one magic incantation or initialization somewhere, dunno. MyApplication.getCurrentApp() (a utility method using a InheritableThreadLocal) works all the time. So I really have no incentive to mend my ways. Same for getting the current locale.

Count +1 for laziness.

Jean, any Vaadin UI component returns null to getApplication call if it is not yet attached to your application. It means that componentInstance.getApplication() will return null if you have not added it to a layout which actually exists on your application UI structure.

This will throw an NPE because button instance is not yet attached to the application


		Button button = new Button();
                // Next line will throw an NPE
		button.getApplication().getVersion();

But this wont as the UI component is attached to the application UI structure:


	        Button button = new Button();
                // This works assuming this == Application instance, it ensures button is attached to the app
		this.getMainWindow().addComponent(button);
		button.getApplication().getVersion();

My advice too is, use ThreadLocal and be happy, no need to clutter your API’s by passing application instance etc. :slight_smile:

Interesting question, indeed. I would pretty much appreciate if the Vaadin team could summarize info concerning threadlocal.
There are also some details over here:

devblog.mycorner.fi

and here:

uservoice

So why use threadlocal?
What if not using threadlocal?

How will this change in V7?

TIA

No need to worry about it when you finally switch to Vaadin 7. Vaadin 7 already has a ThreadLocal defined internally to provide you the Application object at any time within any of your application specific threads.

Heh heh. Knowing when to be lazy is something you only get after a lot of experience!

Thanks for sharing your thinking about it. As Jani pointed out (and I’m sure you know), you shouldn’t hit problems getting the Application unless some object isn’t attached. But I see how that can happen in a complex system.

I still have this nagging suspicion that there’s a problem with using thread locals, but it’s hard to place. I think the use case in which it would fail is in a clustered environment where the instance failed
during an http request
and had to be handled by another one, in which case the threadlocal value wouldn’t be deserialized on the other server. But even in this case I’m not positive that anything could work (maybe the request would simply be replayed to the new server, so it’s ok unless you try to get the App object from within a server transaction that’s being recovered). Ugh, I’ve spent too much time working on clustering (my previous work) to even think of such things. Ignore me!

I think the thread local bit might not work if you have an external thread that needs to get the App object to find a Push component, but if you’re coding that kind of thing you’ll know what to do.

Thanks,
Bobby

Don’t know about that but I see at least one possible issue with threadlocals. If any thread would get jammed, they would effectively prevent any object being referenced by that threadlocal to be ever garbage collected, in this case you’d leak one Vaadin application including all the objects that the Vaadin app references into.

I see no issue here :slight_smile: You just have to understand that threadlocal is bound to the specific thread. And also understand how Application Servers / Servlet Containers work. They got pool of threads (or workers if you wish) that serve any random client out there, clients are not affiliated to any specific thread, they might get different thread for every HTTP request. Hence you got to setup the threadlocal at the earliest possible moment for every HTTP request. It is also polite to unset threadlocal just before answering back to that HTTP request, then again this is never guaranteed as your thread might throw such an exception that the code that unsets threadlocal is never run. But eventually it gets cleared by some other HTTP request which does not throw such an exception.

About the PUSH scenario that contains multiple Vaadin app instances with a single background thread updating all those apps. Let’s say you have one external thread running in 1Hz interval and fetching some data that needs to be pushed periodically to all running application instances. For that you’d implement e.g. a listener mechanism to your background thread so that all apps that are being instantiated can register to that background thread and later de-register when app is closed. Remember to upkeep such list of application instances in thread safe manner, use e.g. a Vector which is threadsafe or make methods synchronized or such.

Now, if you are ever updating any Application instance on an external thread, always remember to first obtain a lock for that Application instance e.g. by running everything on synchronized(myAppInstance) { … } block. Otherwise you’ll hit ConcurrentModificationExceptions and such. This is simple thing to do but some people forget it because they do not have used threads that much. Never allow two separate threads to concurrently access your application instance’s objects.

All I meant was that, when it was time for the background thread to call ‘push,’ it couldn’t look up the Application object via the ThreadLocal like UI components could. But, as you said, it’s simple enough to avoid that by registering the UI component as a listener on the thread for receiving notifications.

My example may not have been well thought out, but I never need to look up the Application object anyway(*), so I was just trying to think of cases that
wouldn’t
work.

(*) I tend to pass needed object references to child objects in their constructors, or else rely on attached components being able to look it up using the Vaadin API.

Cheers,
Bobby

Heh heh – this is mildly ironic.

I have an app that implements HttpServletRequestListener to have the session set/removed at the beginning/end of each request. Due to some unlucky timing, the onRequestEnd() method can be called from one request
after
the onRequestStart() method in a different request. Thus, null session when I need it.

The fix? Store my session in a threadlocal during the request. That will teach me. :wink:

Cheers,
Bobby