[jboss-cvs] jboss-seam/src/main/org/jboss/seam/async ...
Gavin King
gavin.king at jboss.com
Tue Jun 19 15:08:46 EDT 2007
User: gavin
Date: 07/06/19 15:08:46
Added: src/main/org/jboss/seam/async
AbstractDispatcher.java CronSchedule.java
Dispatcher.java LocalTimerServiceDispatcher.java
LocalTransactionListener.java QuartzDispatcher.java
Schedule.java ThreadPoolDispatcher.java
TimerSchedule.java TimerServiceDispatcher.java
package-info.java
Log:
repackaged built-in components
sorry for breakage, but it had to happen eventually :-(
Revision Changes Path
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/AbstractDispatcher.java
Index: AbstractDispatcher.java
===================================================================
package org.jboss.seam.async;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.timer.IntervalCron;
import org.jboss.seam.annotations.timer.Duration;
import org.jboss.seam.annotations.timer.Expiration;
import org.jboss.seam.annotations.timer.FinalExpiration;
import org.jboss.seam.annotations.timer.IntervalDuration;
import org.jboss.seam.bpm.BusinessProcess;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.core.Events;
import org.jboss.seam.core.Init;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.util.Reflections;
/**
* Abstract Dispatcher implementation
*
* @author Gavin King
*
*/
public abstract class AbstractDispatcher<T, S> implements Dispatcher<T, S>
{
public static final String EXECUTING_ASYNCHRONOUS_CALL = "org.jboss.seam.core.executingAsynchronousCall";
public static Dispatcher instance()
{
if ( !Contexts.isApplicationContextActive() )
{
throw new IllegalStateException("no application context active");
}
return (Dispatcher) Component.getInstance("org.jboss.seam.core.dispatcher");
}
public static abstract class Asynchronous implements Serializable
{
static final long serialVersionUID = -551286304424595765L;
private Long processId;
private Long taskId;
protected Asynchronous()
{
if ( Init.instance().isJbpmInstalled() )
{
BusinessProcess businessProcess = BusinessProcess.instance();
processId = businessProcess.getProcessId();
taskId = BusinessProcess.instance().getTaskId();
}
}
public void execute(Object timer)
{
//TODO: shouldn't this take place in a Seam context anyway??!? (bug in EJB3?)
Lifecycle.beginCall();
Contexts.getEventContext().set(EXECUTING_ASYNCHRONOUS_CALL, true);
try
{
if (taskId!=null)
{
BusinessProcess.instance().resumeTask(taskId);
}
else if (processId!=null)
{
BusinessProcess.instance().resumeProcess(processId);
}
Contexts.getEventContext().set("timer", timer);
call();
}
finally
{
Contexts.getEventContext().remove(EXECUTING_ASYNCHRONOUS_CALL);
Lifecycle.endCall();
}
}
protected abstract void call();
}
protected static class AsynchronousInvocation extends Asynchronous
{
static final long serialVersionUID = 7426196491669891310L;
private String methodName;
private Class[] argTypes;
private Object[] args;
private String componentName;
public AsynchronousInvocation(Method method, String componentName, Object[] args)
{
this.methodName = method.getName();
this.argTypes = method.getParameterTypes();
this.args = args==null ? new Object[0] : args;
this.componentName = componentName;
}
public AsynchronousInvocation(InvocationContext invocation, Component component)
{
this( invocation.getMethod(), component.getName(), invocation.getParameters() );
}
@Override
protected void call()
{
Object target = Component.getInstance(componentName);
Method method;
try
{
method = target.getClass().getMethod(methodName, argTypes);
}
catch (NoSuchMethodException nsme)
{
throw new IllegalStateException(nsme);
}
Reflections.invokeAndWrap(method, target, args);
}
}
protected static class AsynchronousEvent extends Asynchronous
{
static final long serialVersionUID = 2074586442931427819L;
private String type;
private Object[] parameters;
public AsynchronousEvent(String type, Object[] parameters)
{
this.type = type;
this.parameters = parameters;
}
@Override
public void call()
{
Events.instance().raiseEvent(type, parameters);
}
}
// TODO: Throw exception when there are multiple interval params
// Make use of finalExpiration
// Make use of NthBusinessDay
protected Schedule createSchedule(InvocationContext invocation)
{
Long duration = null;
Date expiration = null;
Date finalExpiration = null;
Long intervalDuration = null;
String cron = null;
// NthBusinessDay intervalBusinessDay = null;
Annotation[][] parameterAnnotations = invocation.getMethod().getParameterAnnotations();
for ( int i=0; i<parameterAnnotations.length; i++ )
{
Annotation[] annotations = parameterAnnotations[i];
for (Annotation annotation: annotations)
{
if ( annotation.annotationType().equals(Duration.class) )
{
duration = (Long) invocation.getParameters()[i];
}
else if ( annotation.annotationType().equals(IntervalDuration.class) )
{
intervalDuration = (Long) invocation.getParameters()[i];
}
else if ( annotation.annotationType().equals(Expiration.class) )
{
expiration = (Date) invocation.getParameters()[i];
}
else if ( annotation.annotationType().equals(FinalExpiration.class) )
{
finalExpiration = (Date) invocation.getParameters()[i];
}
else if ( annotation.annotationType().equals(IntervalCron.class) )
{
cron = (String) invocation.getParameters()[i];
}
}
}
if ( cron!=null )
{
return new CronSchedule(duration, expiration, cron, finalExpiration);
}
else
{
return new TimerSchedule(duration, expiration, intervalDuration, finalExpiration);
}
}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/CronSchedule.java
Index: CronSchedule.java
===================================================================
package org.jboss.seam.async;
import java.util.Date;
/**
* A "cron schedule" for a timed event executed by
* the Quartz CronTrigger.
*
* @author Michael Yuan
*
*/
public class CronSchedule extends Schedule
{
private String cron;
String getCron()
{
return cron;
}
/**
* @param duration the delay before the first event occurs
* @param cron the unix cron string to control how the events are repeated
*/
public CronSchedule(Long duration, String cron)
{
super(duration);
this.cron = cron;
}
/**
* @param expiration the datetime at which the first event occurs
* @param cron the unix cron string to control how the events are repeated
*/
public CronSchedule(Date expiration, String cron)
{
super(expiration);
this.cron = cron;
}
CronSchedule(Long duration, Date expiration, String cron, Date finalExpiration)
{
super(duration, expiration, finalExpiration);
this.cron = cron;
}
CronSchedule() {}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/Dispatcher.java
Index: Dispatcher.java
===================================================================
package org.jboss.seam.async;
import org.jboss.seam.Component;
import org.jboss.seam.intercept.InvocationContext;
/**
* Interface to be implemented by any strategy for dispatching
* asynchronous method calls and asynchronous events.
*
* @author Gavin King
*
* @param <T> the type of the timer object
*/
public interface Dispatcher<T, S>
{
/**
* Schedule an asynchronous method call, examining annotations
* upon the method to determine the schedule
*
* @return some kind of timer object, or null
*/
public T scheduleInvocation(InvocationContext invocation, Component component);
/**
* Schedule a timed (delayed and/or periodic) event
*
* @return some kind of timer object, or null
*/
public T scheduleTimedEvent(String type, S schedule, Object... parameters);
/**
* Schedule an immediate asynchronous event
*
* @return some kind of timer object, or null
*/
public T scheduleAsynchronousEvent(String type, Object... parameters);
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/LocalTimerServiceDispatcher.java
Index: LocalTimerServiceDispatcher.java
===================================================================
package org.jboss.seam.async;
import java.util.concurrent.Callable;
import javax.ejb.Local;
import javax.ejb.Timer;
/**
* Local interface for TimerServiceDispatcher.
*
* @author Gavin King
*
*/
@Local
public interface LocalTimerServiceDispatcher extends Dispatcher<Timer, TimerSchedule>
{
public Object call(Callable task);
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/LocalTransactionListener.java
Index: LocalTransactionListener.java
===================================================================
package org.jboss.seam.async;
import javax.ejb.Local;
import javax.transaction.Synchronization;
@Local
public interface LocalTransactionListener
{
public void scheduleEvent(String type, Object... parameters);
public void registerSynchronization(Synchronization sync);
public void destroy();
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/QuartzDispatcher.java
Index: QuartzDispatcher.java
===================================================================
package org.jboss.seam.async;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.io.Serializable;
import java.rmi.server.UID;
import java.util.Date;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
/**
* Dispatcher implementation that uses the Quartz library.
*
* @author Michael Yuan
*
*/
@Scope(ScopeType.APPLICATION)
@Name("org.jboss.seam.core.dispatcher")
@Install(value=false, precedence=BUILT_IN)
public class QuartzDispatcher extends AbstractDispatcher<QuartzDispatcher.QuartzTriggerHandle, Schedule>
{
private static final LogProvider log = Logging.getLogProvider(QuartzDispatcher.class);
private static Scheduler scheduler;
@Create
public void initScheduler()
{
SchedulerFactory schedulerFactory = new org.quartz.impl.StdSchedulerFactory();
try
{
scheduler = schedulerFactory.getScheduler();
scheduler.start();
log.info("The QuartzDispatcher has started");
}
catch (SchedulerException se) {
log.error("Cannot get or start a Quartz Scheduler");
se.printStackTrace ();
}
}
public QuartzTriggerHandle scheduleAsynchronousEvent(String type, Object... parameters)
{
String jobName = nextUniqueName();
String triggerName = nextUniqueName();
JobDetail jobDetail = new JobDetail(jobName, null, QuartzJob.class);
jobDetail.getJobDataMap().put("async", new AsynchronousEvent(type, parameters));
SimpleTrigger trigger = new SimpleTrigger(triggerName, null);
log.info("In the scheduleAsynchronousEvent()");
try
{
scheduler.scheduleJob(jobDetail, trigger);
return new QuartzTriggerHandle(triggerName);
}
catch (SchedulerException se)
{
log.error("Cannot Schedule a Quartz Job");
se.printStackTrace ();
return null;
}
}
public QuartzTriggerHandle scheduleTimedEvent(String type, Schedule schedule, Object... parameters)
{
log.info("In the scheduleTimedEvent()");
try
{
return scheduleWithQuartzService( schedule, new AsynchronousEvent(type, parameters) );
}
catch (SchedulerException se)
{
log.error("Cannot Schedule a Quartz Job");
se.printStackTrace ();
return null;
}
}
public QuartzTriggerHandle scheduleInvocation(InvocationContext invocation, Component component)
{
log.info("In the scheduleInvocation()");
try
{
return scheduleWithQuartzService(
createSchedule(invocation),
new AsynchronousInvocation(invocation, component)
);
}
catch (SchedulerException se) {
log.error("Cannot Schedule a Quartz Job");
se.printStackTrace ();
return null;
}
}
private static Date calculateDelayedDate (long delay)
{
Date now = new Date ();
now.setTime(now.getTime() + delay);
return now;
}
private QuartzTriggerHandle scheduleWithQuartzService(Schedule schedule, Asynchronous async) throws SchedulerException
{
log.info("In the scheduleWithQuartzService()");
String jobName = nextUniqueName();
String triggerName = nextUniqueName();
JobDetail jobDetail = new JobDetail(jobName, null, QuartzJob.class);
jobDetail.getJobDataMap().put("async", async);
if (schedule instanceof CronSchedule)
{
CronSchedule cronSchedule = (CronSchedule) schedule;
try
{
CronTrigger trigger = new CronTrigger (triggerName, null);
trigger.setCronExpression(cronSchedule.getCron());
trigger.setEndTime(cronSchedule.getFinalExpiration());
if ( cronSchedule.getExpiration()!=null )
{
trigger.setStartTime (cronSchedule.getExpiration());
}
else if ( cronSchedule.getDuration()!=null )
{
trigger.setStartTime (calculateDelayedDate(cronSchedule.getDuration()));
}
scheduler.scheduleJob( jobDetail, trigger );
}
catch (Exception e)
{
log.error ("Cannot submit cron job");
e.printStackTrace ();
return null;
}
}
else if (schedule instanceof TimerSchedule && ((TimerSchedule) schedule).getIntervalDuration() != null)
{
TimerSchedule timerSchedule = (TimerSchedule) schedule;
if ( timerSchedule.getExpiration()!=null )
{
SimpleTrigger trigger = new SimpleTrigger(triggerName, null, timerSchedule.getExpiration(), timerSchedule.getFinalExpiration(), SimpleTrigger.REPEAT_INDEFINITELY, timerSchedule.getIntervalDuration());
scheduler.scheduleJob( jobDetail, trigger );
}
else if ( timerSchedule.getDuration()!=null )
{
SimpleTrigger trigger = new SimpleTrigger(triggerName, null, calculateDelayedDate(timerSchedule.getDuration()), timerSchedule.getFinalExpiration(), SimpleTrigger.REPEAT_INDEFINITELY, timerSchedule.getIntervalDuration());
scheduler.scheduleJob( jobDetail, trigger );
}
else
{
SimpleTrigger trigger = new SimpleTrigger(triggerName, null, null, timerSchedule.getFinalExpiration(), SimpleTrigger.REPEAT_INDEFINITELY, timerSchedule.getIntervalDuration());
scheduler.scheduleJob( jobDetail, trigger );
}
}
else
{
if ( schedule.getExpiration()!=null )
{
SimpleTrigger trigger = new SimpleTrigger (triggerName, null, schedule.getExpiration());
scheduler.scheduleJob(jobDetail, trigger);
}
else if ( schedule.getDuration()!=null )
{
SimpleTrigger trigger = new SimpleTrigger (triggerName, null, calculateDelayedDate(schedule.getDuration()));
scheduler.scheduleJob(jobDetail, trigger);
}
else
{
SimpleTrigger trigger = new SimpleTrigger(triggerName, null);
scheduler.scheduleJob(jobDetail, trigger);
}
}
return new QuartzTriggerHandle (triggerName);
}
private String nextUniqueName ()
{
return (new UID()).toString();
}
@Destroy
public void destroy()
{
log.info("The QuartzDispatcher is shut down");
try {
scheduler.shutdown();
} catch (SchedulerException se) {
log.error("Cannot shutdown the Quartz Scheduler");
se.printStackTrace ();
}
}
public static class QuartzJob implements Job
{
private AbstractDispatcher.Asynchronous async;
public QuartzJob() { }
public void execute(JobExecutionContext context)
throws JobExecutionException
{
log.info("Start executing Quartz job");
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
async = (AbstractDispatcher.Asynchronous)dataMap.get("async");
async.execute(null);
log.info("End executing Quartz job");
}
}
public static class QuartzTriggerHandle implements Serializable
{
private String triggerName;
public QuartzTriggerHandle(String triggerName)
{
this.triggerName = triggerName;
}
public void cancel() throws SchedulerException
{
log.info("Cancel executing Quartz job");
scheduler.unscheduleJob(triggerName, null);
}
public void pause() throws SchedulerException
{
log.info("Pause executing Quartz job");
scheduler.pauseTrigger(triggerName, null);
}
public void resume() throws SchedulerException
{
log.info("Resume executing Quartz job");
scheduler.resumeTrigger(triggerName, null);
}
}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/Schedule.java
Index: Schedule.java
===================================================================
package org.jboss.seam.async;
import java.io.Serializable;
import java.util.Date;
/**
* A "schedule" for a timed event executed by
* a timer service which supports delayed
* timed events. It is the base class for the more
* useful TimerSchedule and CronSchedule classes.
*
* @author Michael Yuan
*
*/
public class Schedule implements Serializable
{
private Long duration;
private Date expiration;
private Date finalExpiration;
Long getDuration()
{
return duration;
}
Date getExpiration()
{
return expiration;
}
Date getFinalExpiration()
{
return finalExpiration;
}
/**
* @param duration the delay before the event occurs
* @param expiration the datetime at which the event occurs
*/
Schedule(Long duration, Date expiration)
{
this.duration = duration;
this.expiration = expiration;
}
/**
* @param duration the delay before the event occurs
* @param expiration the datetime at which the event occurs
* @param finalExpiration the datetime at which the event ends
*/
Schedule(Long duration, Date expiration, Date finalExpiration)
{
this.duration = duration;
this.expiration = expiration;
this.finalExpiration = finalExpiration;
}
/**
* @param duration the delay before the event occurs
*/
public Schedule(Long duration)
{
this.duration = duration;
}
/**
* @param expiration the datetime at which the event occurs
*/
public Schedule(Date expiration)
{
this.expiration = expiration;
}
public Schedule () { }
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((duration == null) ? 0 : duration.hashCode());
result = prime * result + ((expiration == null) ? 0 : expiration.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final Schedule other = (Schedule) obj;
if (duration == null)
{
if (other.duration != null) return false;
}
else if (!duration.equals(other.duration)) return false;
if (expiration == null)
{
if (other.expiration != null) return false;
}
else if (!expiration.equals(other.expiration)) return false;
return true;
}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/ThreadPoolDispatcher.java
Index: ThreadPoolDispatcher.java
===================================================================
package org.jboss.seam.async;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.intercept.InvocationContext;
/**
* Dispatcher implementation that uses a java.util.concurrent
* ScheduledThreadPoolExecutor.
*
* @author Gavin King
*
*/
@Scope(ScopeType.APPLICATION)
@Name("org.jboss.seam.core.dispatcher")
@Install(precedence=BUILT_IN)
public class ThreadPoolDispatcher extends AbstractDispatcher<Future, TimerSchedule>
{
private int threadPoolSize = 10;
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(threadPoolSize);
public Future scheduleAsynchronousEvent(String type, Object... parameters)
{
return executor.submit( new RunnableAsynchronous( new AsynchronousEvent(type, parameters) ) );
}
public Future scheduleTimedEvent(String type, TimerSchedule schedule, Object... parameters)
{
return scheduleWithExecutorService( schedule, new RunnableAsynchronous( new AsynchronousEvent(type, parameters) ) );
}
public Future scheduleInvocation(InvocationContext invocation, Component component)
{
return scheduleWithExecutorService(
(TimerSchedule) createSchedule(invocation),
new RunnableAsynchronous( new AsynchronousInvocation(invocation, component) )
);
}
private static long toDuration(Date expiration)
{
return expiration.getTime() - new Date().getTime();
}
private Future scheduleWithExecutorService(TimerSchedule schedule, Runnable runnable)
{
if ( schedule.getIntervalDuration()!=null )
{
if ( schedule.getExpiration()!=null )
{
return executor.scheduleAtFixedRate( runnable, toDuration( schedule.getExpiration() ), schedule.getIntervalDuration(), TimeUnit.MILLISECONDS );
}
else if ( schedule.getDuration()!=null )
{
return executor.scheduleAtFixedRate( runnable, schedule.getDuration(), schedule.getIntervalDuration(), TimeUnit.MILLISECONDS );
}
else
{
return executor.scheduleAtFixedRate( runnable, 0l, schedule.getIntervalDuration(), TimeUnit.MILLISECONDS );
}
}
else if ( schedule.getExpiration()!=null )
{
return executor.schedule( runnable, toDuration( schedule.getExpiration() ), TimeUnit.MILLISECONDS );
}
else if ( schedule.getDuration()!=null )
{
return executor.schedule( runnable, schedule.getDuration(), TimeUnit.MILLISECONDS );
}
else
{
return executor.schedule(runnable, 0l, TimeUnit.MILLISECONDS);
}
}
@Destroy
public void destroy()
{
executor.shutdown();
try
{
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException ie)
{
}
}
static class RunnableAsynchronous implements Runnable
{
private AbstractDispatcher.Asynchronous async;
RunnableAsynchronous(Asynchronous async)
{
this.async = async;
}
public void run()
{
async.execute(null);
}
}
public int getThreadPoolSize()
{
return threadPoolSize;
}
public void setThreadPoolSize(int threadPoolSize)
{
this.threadPoolSize = threadPoolSize;
}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/TimerSchedule.java
Index: TimerSchedule.java
===================================================================
package org.jboss.seam.async;
import java.util.Date;
/**
* A "schedule" for a timed event executed by
* the EJB timer service or some other timer
* service which supports delayed and/or periodic
* timed events.
*
* @author Gavin King
*
*/
public class TimerSchedule extends Schedule
{
private Long intervalDuration;
Long getIntervalDuration()
{
return intervalDuration;
}
/**
* @param duration the delay before the event occurs
*/
public TimerSchedule(Long duration)
{
super(duration);
}
/**
* @param expiration the datetime at which the event occurs
*/
public TimerSchedule(Date expiration)
{
super(expiration);
}
/**
* @param duration the delay before the first event occurs
* @param intervalDuration the period between the events
*/
public TimerSchedule(Long duration, Long intervalDuration)
{
super(duration);
this.intervalDuration = intervalDuration;
}
/**
* @param expiration the datetime at which the first event occurs
* @param intervalDuration the period between the events
*/
public TimerSchedule(Date expiration, Long intervalDuration)
{
super(expiration);
this.intervalDuration = intervalDuration;
}
TimerSchedule(Long duration, Date expiration, Long intervalDuration)
{
super(duration, expiration);
this.intervalDuration = intervalDuration;
}
TimerSchedule(Long duration, Date expiration, Long intervalDuration, Date finalExpiration)
{
super(duration, expiration, finalExpiration);
this.intervalDuration = intervalDuration;
}
TimerSchedule() {}
public static final TimerSchedule ONCE_IMMEDIATELY = new TimerSchedule();
@Override
public int hashCode()
{
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((intervalDuration == null) ? 0 : intervalDuration.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (!super.equals(obj)) return false;
final TimerSchedule other = (TimerSchedule) obj;
if (intervalDuration == null)
{
if (other.intervalDuration != null) return false;
}
else if (!intervalDuration.equals(other.intervalDuration)) return false;
return true;
}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/TimerServiceDispatcher.java
Index: TimerServiceDispatcher.java
===================================================================
package org.jboss.seam.async;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.Callable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.EJBException;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;
import javax.ejb.TimerService;
import javax.interceptor.Interceptors;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.ejb.SeamInterceptor;
import org.jboss.seam.intercept.InvocationContext;
/**
* Dispatcher implementation that uses the EJB
* TimerService.
*
* @author Gavin King
*
*/
@Stateless
@Name("org.jboss.seam.core.dispatcher")
@Interceptors(SeamInterceptor.class)
@Install(value=false, precedence=BUILT_IN)
public class TimerServiceDispatcher
extends AbstractDispatcher<Timer, TimerSchedule>
implements LocalTimerServiceDispatcher
{
@Resource TimerService timerService;
@PostConstruct
public void postConstruct() {} //workaround for a bug in EJB3
@Timeout
public void dispatch(Timer timer)
{
( (Asynchronous) timer.getInfo() ).execute(timer);
}
public Timer scheduleTimedEvent(String type, TimerSchedule schedule, Object... parameters)
{
return new TimerProxy( scheduleWithTimerService( schedule, new AsynchronousEvent(type, parameters) ) );
}
public Timer scheduleAsynchronousEvent(String type, Object... parameters)
{
return new TimerProxy( timerService.createTimer( 0l, new AsynchronousEvent(type, parameters) ) );
}
public Timer scheduleInvocation(InvocationContext invocation, Component component)
{
return new TimerProxy( scheduleWithTimerService( (TimerSchedule) createSchedule(invocation), new AsynchronousInvocation(invocation, component) ) );
}
private Timer scheduleWithTimerService(TimerSchedule schedule, Asynchronous asynchronous)
{
if ( schedule.getIntervalDuration()!=null )
{
if ( schedule.getExpiration()!=null )
{
return timerService.createTimer( schedule.getExpiration(), schedule.getIntervalDuration(), asynchronous );
}
else if ( schedule.getDuration()!=null )
{
return timerService.createTimer( schedule.getDuration(), schedule.getIntervalDuration(), asynchronous );
}
else
{
return timerService.createTimer( 0l, schedule.getIntervalDuration(), asynchronous );
}
}
else if ( schedule.getExpiration()!=null )
{
return timerService.createTimer( schedule.getExpiration(), asynchronous );
}
else if ( schedule.getDuration()!=null )
{
return timerService.createTimer( schedule.getDuration(), asynchronous );
}
else
{
return timerService.createTimer(0l, asynchronous);
}
}
static class TimerProxy
implements Timer
{
Timer timer;
public TimerProxy(Timer timer)
throws IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
this.timer = timer;
}
public void cancel()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
instance().call(new Callable() {
public Object call()
{
timer.cancel();
return null;
}
});
}
public TimerHandle getHandle()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
TimerHandle handle = (TimerHandle)
instance().call(new Callable() {
public Object call()
{
return timer.getHandle();
}
});
return new TimerHandleProxy(handle);
}
public Serializable getInfo()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
return (Serializable)
instance().call(new Callable() {
public Object call()
{
return timer.getInfo();
}
});
}
public Date getNextTimeout()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
return (Date)
instance().call(new Callable() {
public Object call()
{
return timer.getNextTimeout();
}
});
}
public long getTimeRemaining()
throws IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
return (Long)
instance().call(new Callable() {
public Object call()
{
return timer.getTimeRemaining();
}
});
}
}
static class TimerHandleProxy
implements TimerHandle,
Serializable
{
private static final long serialVersionUID = 6913362944260154627L;
TimerHandle handle;
public TimerHandleProxy(TimerHandle handle)
{
this.handle = handle;
}
public Timer getTimer()
throws IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
Timer timer = (Timer) instance().call(new Callable() {
public Object call()
{
try
{
return handle.getTimer();
}
catch (NoSuchObjectLocalException nsoe)
{
return null;
}
}
});
if (timer==null)
{
throw new NoSuchObjectLocalException();
}
else
{
return new TimerProxy(timer);
}
}
}
public Object call(Callable task)
{
try
{
return task.call();
}
catch (RuntimeException e)
{
// just pass along runtime exceptions
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public static LocalTimerServiceDispatcher instance()
{
return ( (LocalTimerServiceDispatcher) AbstractDispatcher.instance() );
}
}
1.1 date: 2007/06/19 19:08:46; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/async/package-info.java
Index: package-info.java
===================================================================
@Namespace(value="http://jboss.com/products/seam/async", prefix="org.jboss.seam.async")
package org.jboss.seam.async;
import org.jboss.seam.annotations.Namespace;
More information about the jboss-cvs-commits
mailing list