Have the scheduled actions persister startup at the correct point, and start to make use of the new Quartz triggers (for ALF-4346)

Also update the documentation at the top of bootstrap-context.xml to reflect using AbstractLifecycleBean, rather than the raw spring interfaces


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21835 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Nick Burch
2010-08-17 12:02:17 +00:00
parent 637495973d
commit f3ce6ac130
4 changed files with 96 additions and 67 deletions

View File

@@ -9,18 +9,21 @@
The pattern for adding new initialisation to the bootstrap sequence is as follows: The pattern for adding new initialisation to the bootstrap sequence is as follows:
1) Develop a bean that implements the Spring interface ApplicationListener 1) Develop a bean that extends the Spring Surf class AbstractLifecycleBean
2) Place the initialisation logic in the method onApplicationEvent(ApplicationEvent event)... 2) Place the initialisation logic in the method onBootstrap(ApplicationEvent event)...
public void onApplicationEvent(ApplicationEvent event) public void onBootstrap(ApplicationEvent event)
{ {
if (event instanceof ContextRefreshedEvent) // initialisation logic here
{ }
// initialisation logic here 3) Place the shutdown logic (if any) in the method onShutdown(ApplicationEvent event)...
}
public void onShutdown(ApplicationEvent event)
{
// cleanup logic here
} }
3) Add the bean definition to this file - Note: the beans are initialised in the order they are specified. 4) Add the bean definition to this file - Note: the beans are initialised in the order they are specified.
--> -->
<beans> <beans>
@@ -603,6 +606,11 @@
<property name="companyHomePath"><value>/${spaces.company_home.childname}</value></property> <property name="companyHomePath"><value>/${spaces.company_home.childname}</value></property>
</bean> </bean>
<!-- Scheduled persisted actions - load into quartz -->
<bean id="scheduledPersistedActionServiceBootstrap" class="org.alfresco.repo.action.scheduled.ScheduledPersistedActionServiceImpl$ScheduledPersistedActionServiceBootstrap">
<property name="scheduledPersistedActionService" ref="scheduledPersistedActionService" />
</bean>
<!-- Startup Message --> <!-- Startup Message -->
<bean id="startupLog" class="org.alfresco.repo.descriptor.DescriptorStartupLog"> <bean id="startupLog" class="org.alfresco.repo.descriptor.DescriptorStartupLog">

View File

@@ -23,6 +23,7 @@ import java.util.Date;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.scheduled.ScheduledPersistedAction; import org.alfresco.service.cmr.action.scheduled.ScheduledPersistedAction;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.quartz.DateIntervalTrigger;
import org.quartz.SimpleTrigger; import org.quartz.SimpleTrigger;
import org.quartz.Trigger; import org.quartz.Trigger;
@@ -39,6 +40,7 @@ public class ScheduledPersistedActionImpl implements ScheduledPersistedAction
private NodeRef persistedAtNodeRef; private NodeRef persistedAtNodeRef;
private Action action; private Action action;
private Date scheduleStart; private Date scheduleStart;
private Date scheduleEnd;
private Integer intervalCount; private Integer intervalCount;
private IntervalPeriod intervalPeriod; private IntervalPeriod intervalPeriod;
@@ -82,6 +84,24 @@ public class ScheduledPersistedActionImpl implements ScheduledPersistedAction
this.scheduleStart = startDate; this.scheduleStart = startDate;
} }
/**
* Not yet publicly available - get the date after
* which the action should no longer be run.
*/
protected Date getScheduleEnd()
{
return scheduleEnd;
}
/**
* Not yet publicly available - set the date after
* which the action should no longer be run.
*/
protected void setScheduleEnd(Date endDate)
{
this.scheduleEnd = endDate;
}
/** /**
* How many {@link #getScheduleIntervalPeriod()} periods * How many {@link #getScheduleIntervalPeriod()} periods
@@ -149,58 +169,40 @@ public class ScheduledPersistedActionImpl implements ScheduledPersistedAction
// Use our nodeRef as the unique title // Use our nodeRef as the unique title
String triggerName = persistedAtNodeRef.toString(); String triggerName = persistedAtNodeRef.toString();
// Monthly is a special case, since the period
// will vary // If they don't want it to repeat, and didn't set any
// TODO - Make more things use DateIntervalTrigger // dates, then we can't schedule it!
if(intervalPeriod == IntervalPeriod.Month) if(getScheduleInterval() == null && scheduleStart == null)
{ {
// TODO return null;
// DateIntervalTrigger trigger = new DateIntervalTrigger(
// triggerName, null,
// scheduleStart, null,
// DateIntervalTrigger.IntervalUnit.MONTH,
// intervalCount
// );
// trigger.setMisfireInstruction( DateIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_NOW );
} }
SimpleTrigger trigger = null;
// Is it Start Date + Repeat Interval? // If they don't want it to repeat, just use a simple interval
if(scheduleStart != null && getScheduleInterval() != null) if(getScheduleInterval() == null)
{ {
trigger = new SimpleTrigger( SimpleTrigger trigger = new SimpleTrigger(
triggerName, null,
scheduleStart, null,
SimpleTrigger.REPEAT_INDEFINITELY,
intervalCount * intervalPeriod.getInterval()
);
}
// Is it a single Start Date?
if(scheduleStart != null && getScheduleInterval() == null)
{
trigger = new SimpleTrigger(
triggerName, null, triggerName, null,
scheduleStart scheduleStart
); );
}
// Is it start now, run with Repeat Interval?
if(getScheduleInterval() != null)
{
trigger = new SimpleTrigger(
triggerName, null,
SimpleTrigger.REPEAT_INDEFINITELY,
intervalCount * intervalPeriod.getInterval()
);
}
if(trigger != null)
{
// If we miss running, run as soon after as we can
trigger.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW); trigger.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
return trigger;
} }
// There are some repeating rules
// Create a Date Interval trigger
DateIntervalTrigger.IntervalUnit quartzInterval =
DateIntervalTrigger.IntervalUnit.valueOf(
intervalPeriod.toString().toUpperCase()
);
DateIntervalTrigger trigger = new DateIntervalTrigger(
triggerName, null,
scheduleStart, scheduleEnd,
quartzInterval, intervalCount
);
trigger.setMisfireInstruction( DateIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW );
return trigger; return trigger;
} }
} }

View File

@@ -43,6 +43,8 @@ import org.quartz.JobDetail;
import org.quartz.Scheduler; import org.quartz.Scheduler;
import org.quartz.SchedulerException; import org.quartz.SchedulerException;
import org.quartz.Trigger; import org.quartz.Trigger;
import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
/** /**
* A service which handles the scheduling of the execution of persisted actions. * A service which handles the scheduling of the execution of persisted actions.
@@ -118,6 +120,7 @@ public class ScheduledPersistedActionServiceImpl implements ScheduledPersistedAc
this.namespaceService = namespaceService; this.namespaceService = namespaceService;
} }
/** /**
* Find all our previously persisted scheduled actions, and tell the * Find all our previously persisted scheduled actions, and tell the
* scheduler to start handling them. Called by spring when startup is * scheduler to start handling them. Called by spring when startup is
@@ -259,4 +262,30 @@ public class ScheduledPersistedActionServiceImpl implements ScheduledPersistedAc
return detail; return detail;
} }
/**
* This is used to trigger the loading of previously persisted schedules on
* an application startup. It is an additional bean to make the context
* files cleaner.
*/
public static class ScheduledPersistedActionServiceBootstrap extends AbstractLifecycleBean
{
private ScheduledPersistedActionServiceImpl service;
public void setScheduledPersistedActionService(ScheduledPersistedActionServiceImpl scheduledPersistedActionService)
{
this.service = scheduledPersistedActionService;
}
public void onBootstrap(ApplicationEvent event)
{
service.schedulePreviouslyPersisted();
}
public void onShutdown(ApplicationEvent event)
{
// We don't need to do anything here, as the scheduler shutdown
// will stop running our jobs for us
}
}
} }

View File

@@ -86,28 +86,18 @@ public interface ScheduledPersistedAction
public static enum IntervalPeriod { public static enum IntervalPeriod {
Month ('M', -1), Month ('M'),
Week ('W', 7*24*60*60*1000), Week ('W'),
Day ('D', 24*60*60*1000), Day ('D'),
Hour ('h', 60*60*1000), Hour ('h'),
Minute ('m', 60*1000); Minute ('m');
private final char letter; private final char letter;
private final long interval; IntervalPeriod(char letter) {
IntervalPeriod(char letter, long interval) {
this.letter = letter; this.letter = letter;
this.interval = interval;
} }
public char getLetter() { public char getLetter() {
return letter; return letter;
} }
/**
* Returns the interval of one of these
* periods, in milliseconds
*/
public long getInterval() {
return interval;
}
} }
} }