When Using a thread-local database connection, closure of the connection is required when the thread exists.
This I can only do if I can override the run() method of the calling thread. Even that is not a great solution, since at time of exit, I don't know if a connection has ever been opened by that thread.
The problem is in fact more general: How to force a thread to call some finalisation method of a thread-local object when it exits.
I looked at the sources of java 1.5 and found that the thread local map is set to null, which will eventually cause the garbage collection to call finalize(), but I don't want to count on the garbage collector.
The following override seems inevitable to make sure that a database connection is closed:
@Override
public void remove() {
get().release();
super.remove();
}
where release() closes the database connection, if it has been opened. But we don't know if the thread has ever used this thread-local. If get() has never been called by this thread, then there's quite a waste of effort here: ThreadLocal.initialValue() will be called, a map will be created on this thread, etc.
-
Further clarification and example as per Thorbjørn's comment:
java.lang.ThreadLocal is a type of factory for an object that is bound to a thread. This type has a getter for the object and a factory method (typically written by the user). When the getter is called it calls the factory method only if it has never been called before by this thread.
Using ThreadLocal allows a developer to bind a resource to a thread even if the thread code was written by a third party.
Example: Say we have a resource Type called MyType and we want to have one and only one of it per thread.
Define in the using class: private static ThreadLocal resourceFactory = new ThreadLocal(){ @override protected MyType initialValue(){ return new MyType(); } }
Use in local context in this class: public void someMethod(){ MyType resource = resourceFactory.get(); resource.useResource(); }
get() can call initialValue() only once in the life cycle of the calling thread. At that point an instance of MyType gets instantiated and bound to this thread. Subsequent calls to get() by this thread refer again to this object.
The classic usage example is when MyType is some thread-unsafe text/date/xml formatter.
But such formatters usually don't need to be released or closed, database connections do and I am using java.lang.ThreadLocal to have a one database connection per thread.
The way I see it, java.lang.ThreadLocal is almost perfect for that. Almost because there's no way to guarantee closure of the resource if the calling thread belongs to a third party application.
I need your brains squires: By extending java.lang.ThreadLocal I managed to bind one database connection for every thread, for it's exclusive usage - including threads that I can not modify or override. I managed to make sure that the connections get closed in case the thread dies on uncaught exception.
In case of normal thread exit, the garbage collector closes the connection (because MyType overrides the finalize()). In actual fact it happens quite quickly, but this is not ideal.
If I had my way, there would have been another method on the java.lang.ThreadLocal:
protected void release() throws Throwable {}
If this method existed on java.lang.ThreadLocal, called by JVM upon any thread exit/death, then in my own override of it I could close my connection (and the redeemer would have come to Zion).
In the absence of such method, I'm looking for another way to confirm closure. A way that won't rely on the JVM garbage collection.
Thanks