I've got a Vaadin application and I'm getting some strange behaviour when running two instances of the application at the same time (one in FF, another in IE). I've already removed most static objects (these caused the application to completely reload when used parallel to another open application) and now I can interact normally with the UI without the complete reset. However, I'm now noticing that I'm getting only one user's data in both interfaces. I assume this is caused by singleton objects I'm using to manage some data caching and a SOAP connection. I'd like to know if it's the singleton pattern itself that's causing the strange output or is it just the static instance object I'm keeping?
I've tried using ThreadLocal with my singleton, but all my variables are always null when I try to use them in my singleton's functions. Currently my singleton contains this, which is probably terribly, terribly wrong since it doesn't work.
private static ThreadLocal<SoapClient> instance = new ThreadLocal<SoapClient>();
public static synchronized SoapClient getInstance(){
if (instance.get() == null) {
instance.set(new SoapClient());
}
return instance.get();
}
I chose a singleton object so I'd always have access to the cached data and my user's soap connection everywhere in my application instance, and the only other way I can think of for doing that is to have a static object somewhere, but the static keyword seems to be the cause of all my problems in the first place. Is there any way around this or is there something else causing it?
A better way to instantiate your thread local would be this
ThreadLocal<SoapClient> instance = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return new SoapClient();
}
}
However, your problem here is web app servers "pool" and re-use threads. In Vaadin terms,not every request for an application is processed same thread - i.e. Thread1 could process requests for both App instance 1 and App Instance 2. If your SoapClient caches information appropriate to App instance 1, the UI for App 2 could end up using the SoapClient for App 1.
Assuming (from your description) that "app specific" information is cached in the SoapClient, I would suggest that you
Create and store the SoapClient on your Application object as a normal field (not static, not threadlocal)
If you need to access the application (in order to get the SoapClient), and it's tricky from where you are, use the ThreadLocal access pattern. See the second example on the link. Note that the ThreadLocal is set at the beginning of the HttpRequest, and "unset" at the end, ensuring that any subsequent requests on the same thread do NOT get the same application instance.