-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hello,
I have an "EventThreadListener" that implements EventThreadCleanup, EventThreadSuspend, EventThreadInit, EventThreadResume. EventThreadCleanup.cleanup() and EventThreadSuspend.beforeSuspend() release a database connection that is on a ThreadLocal variable. I have a Textbox with a Constraint added to it. Constraint.validate(...) gets a database connection and runs a query. The connection is not being released, which is to say the cleanup routine is not being called on the thread that is active during Constraint.validate(...). I've added debugging to my EventThreadListener. When I enter something in the textbox and trigger the validation routine I get this in the log:
DEBUG 01/27 13:25:23 : EventThreadInit.prepare() - on http-8080-2 DEBUG 01/27 13:25:23 : EventThreadInit.init() - on Thread-33 DEBUG 01/27 13:25:23 : EventThreadCleanup.cleanup() - on Thread-33 DEBUG 01/27 13:25:23 : EventThreadCleanup.complete() - on http-8080-2 DEBUG 01/27 13:25:23 : EventThreadInit.prepare() - on http-8080-2 DEBUG 01/27 13:25:23 : EventThreadInit.init() - on Thread-33 DEBUG 01/27 13:25:23 : EventThreadCleanup.cleanup() - on Thread-33 DEBUG 01/27 13:25:23 : EventThreadCleanup.complete() - on http-8080-2 DEBUG 01/27 13:25:23 : Constraint.validate() on http-8080-2
The event threads usually have a name like "Thread-##". Here is appears Constraint.validate() is being run on the http request thread rather than an event thread. This looks like a bug to me. (It also looks odd that Constraint.validate() is called after completion of the event thread.) Is this expected behavior? Should I also be cleaning up my database connection on EventThreadCleanup.complete() since this appears to run on the http request thread?
/Daryl
Hey Daryl,
Good to know that you have found this condition. I am pleased it was all sorted.
The validate is run on the HTTP thread as it is received as an HTTP request, if you ever want to cleanup on the HTTP thread you can so with ExecutionCleanup.cleanup().
Thanks,
Tim
Tim,
I've discovered a severe race condition in my handling of database connections. Fixing the condition makes this problem go away, so it appears it's my fault, which is fine since I could fix it pretty quickly. While I still think Constraint.validate() should run on an event thread, it really doesn't matter from a practical standpoint.
Anyway, I did learn from you about ExecutionCleanup.cleanup(), so do appreciate your attention.
Thanks.
/Daryl
ExecutionCleanup.cleanup() runs only on the HTTP thread, therefore it doesn't clean up my connections acquired in events. Can we go back to the original message? Constraint.validate() is being run on the http request thread rather than an event thread. Why is that? If Constraint.validate() ran on an event thread, I don't think I'd have any problem. Are you sure it's supposed to run on the HTTP thread?
/Daryl
Hey Daryl,
>You should only cleanup in ... ExecutionCleanup.cleanup() Are you saying I don't need the other 3? ExecutionCleanup.cleanup() is always called after all the others?
Yes, you should not need the other 3, ExecutionCleanup should suffice!
Please let me if it works!
Thanks,
Tim
ConnectionResource.cleanUp() is the method that does the actual cleanup. It is called from
EventThreadCleanup.cleanup()
ExecutionCleanup.cleanup()
EventThreadCleanup.complete()
EventThreadSuspend.beforeSuspend()
>You should only cleanup in ... ExecutionCleanup.cleanup()
Are you saying I don't need the other 3? ExecutionCleanup.cleanup() is always called after all the others?
>A very simple way to solve your problem is to turn the event thread off. If you are not using modal dialogs it is the best solution.
Ah, but I am using modal dialogs. While it may solve the problem, it's a workaround rather than a fix. If the problem is my code I'm happy to fix it, but I should not have to work around it if the problem is in Zk. I'm not convinced the problem is mine yet.
Thanks for sticking with me on this.
/Daryl
Hey Daryl,
Why are you cleaning up in
DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - removing from Thread-33
and
DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - removing from http-8080-1?
You should only cleanup in DEBUG 03/01 12:49:06 : ExecutionCleanup.cleanup() - on http-8080-1 and that should solve your problem.
A very simple way to solve your problem is to turn the event thread off. If you are not using modal dialogs it is the best solution.
I've done as you say, and if I simply TAB off the textbox it works as expected and I get this logging:
DEBUG 03/01 12:51:36 : Constraint.validate() on http-8080-1 DEBUG 03/01 12:51:36 : ConnectionResource.get() conn ...Connection@392cf455 on http-8080-1 DEBUG 03/01 12:51:36 : Constraint.validate() got connection ...Connection@392cf455 DEBUG 03/01 12:51:36 : Constraint.validate() exiting DEBUG 03/01 12:51:36 : ExecutionCleanup.cleanup() - on http-8080-1 DEBUG 03/01 12:51:36 : ConnectionResource.cleanUp() - connectionRetrieved = true DEBUG 03/01 12:51:36 : ConnectionResource.cleanUp() - removing from http-8080-1
The second line shows the connection being retrieved. The second to last shows that the ThreadLocal variable knows the connection was retrieved and it is closed (not shown). But if instead of TABBING off the field, I click the Save button, I get a different set of log entries and it fails:
DEBUG 03/01 12:49:06 : Constraint.validate() on http-8080-1 DEBUG 03/01 12:49:06 : ConnectionResource.get() conn ...Connection@393d701a on http-8080-1 DEBUG 03/01 12:49:06 : Constraint.validate() got connection ...Connection@393d701a DEBUG 03/01 12:49:06 : Constraint.validate() exiting DEBUG 03/01 12:49:06 : EventThreadInit.prepare() - on http-8080-1 DEBUG 03/01 12:49:06 : EventThreadInit.init() - on Thread-33 DEBUG 03/01 12:49:06 : EventThreadCleanup.cleanup() - on Thread-33 DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - connectionRetrieved = true DEBUG 03/01 12:49:06 : ConnectionResource.get() conn ...Connection@5a3bb53f on Thread-33 DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - removing from Thread-33 DEBUG 03/01 12:49:06 : EventThreadCleanup.complete() - on http-8080-1 DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - connectionRetrieved = false DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - removing from http-8080-1 DEBUG 03/01 12:49:06 : ExecutionCleanup.cleanup() - on http-8080-1 DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - connectionRetrieved = false DEBUG 03/01 12:49:06 : ConnectionResource.cleanUp() - removing from http-8080-1
Again, the second line shows the connection being retrieved and the constraint runs. Then Thread-33 is spun up presumably to handle the Save click. On the third line of the "second paragraph" it appears as though Thread-33 has retrieved a connection, though there is no corresponding retrieval line. I then expected the third line of the third paragraph to show that the connection had been retrieved on http-8080-1, but it doesn't show this. It appears as though the state of my ThreadLocal jumped from one thread to the other. Since it doesn't think the connection was ever retrieved, it doesn't try to close it.
Do you have any insight as to what may be going on here?
Thanks.
/Daryl
Hey Daryl,
Here are some steps:
1. Implement the interface ExecutionCleanup. Let's name the implementing class "CycleCleanup"
2. Get your db connection in the Validate routine and make sure the data is valid
3. In CycleCleanup's clean up routine implement your cleanup code, checking to see whether the db connection is active and if it is release the resource
This should now work.
Well, I thought that would work, but it doesn't. Here's my current log of happenings:
DEBUG 02/12 09:11:00 : EventThreadInit.prepare() - on http-8080-4 DEBUG 02/12 09:11:00 : EventThreadInit.init() - on Thread-65 DEBUG 02/12 09:11:00 : EventThreadCleanup.cleanup() - on Thread-65 DEBUG 02/12 09:11:00 : EventThreadCleanup.complete() - on http-8080-4 DEBUG 02/12 09:11:00 : EventThreadInit.prepare() - on http-8080-4 DEBUG 02/12 09:11:00 : EventThreadInit.init() - on Thread-65 DEBUG 02/12 09:11:00 : EventThreadCleanup.cleanup() - on Thread-65 DEBUG 02/12 09:11:00 : EventThreadCleanup.complete() - on http-8080-4 DEBUG 02/12 09:11:00 : Constraint.validate() on http-8080-4
EventThreadCleanup.complete() is called BEFORE Constraint.validate(), thus missing the opportunity to close the database connection. This certainly has to be a bug as EventThreadCleanup can't do what it's supposed to be able to do. Unless there's another interface I could implement to clean up the main thread after Constraint.validate()?
/Daryl
Asked: 2010-01-27 13:05:08 +0800
Seen: 816 times
Last updated: Mar 12 '10