You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Apache Wiki <wi...@apache.org> on 2008/02/07 12:10:38 UTC

[Tapestry Wiki] Update of "Tapestry5HowToRunTaskInThread" by DavorHrg

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

New 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.

Most important thing is to call !ThreadCleanupHub.cleanup() after the thread is finished.

Other thing is that the separate thread will have different instances of any threaded services and will not have any user specific data. For example if you load an Hibernate entity inside the request thread and pass it to the task, the task will get a different Hibernate Session instance and will fail if you try to save the instance while the task is running (in a separate thread that is)

To save you some trouble I've created a simple service that runs tasks in a separate thread and makes sure ThreadCleanupHub.cleanup()is called. You can inject it anywhere and call:
{{{#!java
_threadSource.runInThread(new Runnable(){
    public void run(){
        //do something
    }
});
}}}


interface !ThreadSource
{{{#!java
public interface ThreadSource {

    /** runs the task using default exception handler, which writes exception to the log */
    public abstract void runInThread(Runnable task);

    /** runs a task in a separate thread and makes sure that tapestry ioc resources are freed after
     * thread finishes.*/
    public abstract void runInThread(final Runnable task, final TaskExceptionHandler taskExceptionHandler);

}
}}}

interface !TaskExceptionHandler 
{{{#!java
public interface TaskExceptionHandler {
    public void exceptionThrown(Object task, Throwable exception);
}
}}}

implementation (you can implement it way you like it, and even add a thread pool)
{{{#!java

import org.apache.tapestry.ioc.services.ThreadCleanupHub;
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() {
                try {
                   task.run();
                } catch (Throwable e) {
                    taskExceptionHandler.exceptionThrown(task, e);
                } finally {
                    _cleanupHub.cleanup();
                }
            }
            
        }).start();
    }
    
    /** 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: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org