Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for 
change notification.

The following page has been changed by DavorHrg:
http://wiki.apache.org/tapestry/Tapestry5HowToRunTaskInThread

------------------------------------------------------------------------------
- !IMPORTANT this code will work on java 1.6, and will not on java 1.5 until 
[https://issues.apache.org/jira/browse/TAPESTRY-2141 TAPESTRY-2141] is resolved
+ !IMPORTANT this code will work on java 1.6, and will not on java 1.5 until 
[https://issues.apache.org/jira/browse/TAPESTRY-2141 TAPESTRY-2141] is resolved 
(there is a workarround for java 5 on the bottom of this page)
  
  Questions about running tasks in separate thread were asked more than few 
times on the mailing list. The code is simple but some important things must be 
considered.
  
@@ -91, +91 @@

  }
  }}}
  
+ 
+ == Workarround ==
+ 
+ Please notice that this workarround fixes only the issue with 
!ThreadCleanupHub, but other !ThreadLocal dependant code might fail.
+ 
+ the bug mentioned for java 5 happens if !ThreadLocal.initialValue() happens 
inside another !ThreadLocal.initialValue(), this is exactly the case when any 
other threaded service is initialized. It is because !PerThreadServiceCreator 
uses ThreadLocal and inside initValue() generates a new instance of a service 
by calling a build method, and build method for !HibernateSesionManager adds a 
listener to !ThreadCleanupHub (which gets initialized and calls initialValue()) 
and things get messed up... I'm probably not makin much sense ... so here's the 
workarround
+ 
+ declare a dummy listener inside !ThreadSourceImpl:
+ {{{#!java
+     /** dummy listener to force initializing the ThreadLocal and avoid 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5025230*/
+     private static final ThreadCleanupListener dummyListener = new 
ThreadCleanupListener(){public void threadDidCleanup() {}};
+ }}}
+ 
+ then add this as first line in the run method of the new created thread 
(before task.run())
+ adding the dummy listener is just to force creation of !ThreadCleanupHub 
instance
+ {{{
+ _cleanupHub.addThreadCleanupListener(dummyListener);
+ }}}
+ 
+ for unpatient, here's the full code with workarround
+ {{{#!java
+ import org.apache.tapestry.ioc.services.ThreadCleanupHub;
+ import org.apache.tapestry.ioc.services.ThreadCleanupListener;
+ import org.slf4j.Logger;
+ 
+ public class ThreadSourceImpl implements ThreadSource {
+ 
+     private final ThreadCleanupHub _cleanupHub;
+     private final Logger _logger;
+ 
+     public ThreadSourceImpl(ThreadCleanupHub cleanupHub, Logger logger){
+         _cleanupHub = cleanupHub;
+         _logger = logger;
+     }
+     
+     /* (non-Javadoc)
+      * @see tapestryutil.services.ThreadSource#runInThread(java.lang.Runnable)
+      */
+     public void runInThread(Runnable task){
+         runInThread(task,defaultTaskExceptionHandler);
+     }
+ 
+     /* (non-Javadoc)
+      * @see 
tapestryutil.services.ThreadSource#runInThread(java.lang.Runnable, 
tapestryutil.services.TaskExceptionHandler)
+      */
+     public void runInThread(final Runnable task, final TaskExceptionHandler 
taskExceptionHandler){
+         new Thread(new Runnable(){
+ 
+             public void run() {
+                 _cleanupHub.addThreadCleanupListener(dummyListener);
+                 try {
+                    task.run();
+                 } catch (Throwable e) {
+                     taskExceptionHandler.exceptionThrown(task, e);
+                 } finally {
+                     _cleanupHub.cleanup();
+                 }
+             }
+             
+         }).start();
+     }
+     
+     /** dummy listener to force initializing the ThreadLocal and avoid 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5025230*/
+     private static final ThreadCleanupListener dummyListener = new 
ThreadCleanupListener(){public void threadDidCleanup() {}};
+ 
+     /** default exception handler that writes exception to the log */
+     private final TaskExceptionHandler defaultTaskExceptionHandler = new 
TaskExceptionHandler(){
+         public void exceptionThrown(Object task, Throwable exception) {
+             _logger.error("Task failed :"+task, exception);
+         }
+     };
+     
+ }
+ }}}
+ 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to