package org.jboss.seam.ioc.spring;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.async.AbstractDispatcher;
import org.jboss.seam.async.Asynchronous;
import org.jboss.seam.async.AsynchronousEvent;
import org.jboss.seam.async.AsynchronousInvocation;
import org.jboss.seam.async.Dispatcher;
import org.jboss.seam.async.Schedule;
import org.jboss.seam.async.TimerSchedule;
import org.jboss.seam.core.Expressions.ValueExpression;
import org.jboss.seam.intercept.InvocationContext;
import org.springframework.core.task.TaskExecutor;
/**
* Dispatcher that can utilizes SpringTaskExecutors for non scheduled
* asynchronous events but defer to another ScheduledDispatcher for Scheduled
* asynchronous events.
*
* @author Mike Youngstrom
*/
@Scope(ScopeType.APPLICATION)
@Name("org.jboss.seam.async.dispatcher")
@Install(value=false, precedence=BUILT_IN)
public class SpringTaskExecutorDispatcher<T, S extends Schedule> extends AbstractDispatcher<T, S>
{
private ValueExpression<Dispatcher<T, S>> scheduleDispatcher;
private ValueExpression<TaskExecutor> taskExecutor;
public T scheduleAsynchronousEvent(String type, Object... parameters)
{
taskExecutor.getValue().execute(
new RunnableAsynchronous(new AsynchronousEvent(type, parameters)));
return null;
}
public T scheduleInvocation(InvocationContext invocation, Component component)
{
Schedule schedule = createSchedule(invocation);
if (!TimerSchedule.ONCE_IMMEDIATELY.equals(schedule))
{
return getScheduleDispatcher().scheduleInvocation(invocation, component);
}
taskExecutor.getValue().execute(
new RunnableAsynchronous(new AsynchronousInvocation(invocation, component)));
return null;
}
public T scheduleTimedEvent(String type, S schedule, Object... parameters)
{
return getScheduleDispatcher().scheduleTimedEvent(type, schedule, parameters);
}
protected Dispatcher<T, S> getScheduleDispatcher()
{
Dispatcher<T, S> dispatcher = (scheduleDispatcher==null) ? null : scheduleDispatcher.getValue();
if (dispatcher == null) {
throw new IllegalStateException(
"SpringTaskExecutorDispatcher does not support scheduled Events. Provide a fallback scheduleDispatcher for timed events.");
}
return dispatcher;
}
/**
* The dispatcher to handle scheduled events
*
* @param scheduleDispatcher
*/
public void setScheduleDispatcher(ValueExpression<Dispatcher<T, S>> scheduleDispatcher)
{
this.scheduleDispatcher = scheduleDispatcher;
}
/**
* The Spring TaskExecutor to handle immediate asynchronous events
*
* @param taskExecutor
*/
public void setTaskExecutor(ValueExpression<TaskExecutor> taskExecutor)
{
this.taskExecutor = taskExecutor;
}
/**
* Same as the one in ThreadPoolDispatcher. Perhaps area for reuse?
*/
static class RunnableAsynchronous implements Runnable
{
private Asynchronous async;
RunnableAsynchronous(Asynchronous async)
{
this.async = async;
}
public void run()
{
async.execute(null);
}
}
}