Scout/Concepts/Scheduler
Scout |
Wiki Home |
Website |
Download • Git |
Community |
Forums • Blog • Twitter • G+ |
Bugzilla |
Bugzilla |
Scout provides a scheduler to run jobs.
Contents
Facts
- The instance for the Job is created exactly once. Every run of a job is executed by that instance.
- The timer (when to start) is hardcoded (see example).
Usage
- Derive a class from
AbstractSchedulerJob
- implement a constructor calling
super(groupId, jobId);
- implement / override
execAcceptTick
- implement / override
run
- In the ServerApplication you need something like
public class ServerApplication implements IApplication{ public Object start(IApplicationContext context) throws Exception { //start the scheduler Scheduler scheduler=new Scheduler(Activator.getDefault().getBackendSubject(),ServerSession.class); scheduler.addJob(new LoadJobs()); // scheduler.addJob(new FetchMailSchedulerJob()); scheduler.addJob(new LdapSchedulerJob()); scheduler.addJob(new UpdatePLAOrdersJob()); scheduler.start(); Activator.getDefault().setScheduler(scheduler); ...
Example
public class MyJob extends AbstractSchedulerJob { private static IScoutLogger s_logger =ScoutLogManager.getLogger(MyJob.class); private final static String groupId = "MyGroup"; private final static String jobId = "MyJob"; /** * <p><code>true</code> the job is currently running, <code>false</code> else&</p> * <p>Access needs to be guarded / synchronized by <code>this</code>, because it is possible, that the same reference to the job * is called twice.</p>. */ private boolean m_running; public MyJob() { super(groupId, jobId); } @Override protected boolean execAcceptTick(TickSignal signal, int second, int minute, int hour, int day, int week, int month, int year, int dayOfWeek, int dayOfMonthReverse, int dayOfYear, int secondOfDay) { return (second==0 && minute%10==0); /* start every 10 minutes */ } @Override public void run(IScheduler scheduler, TickSignal signal) throws ProcessingException { synchronized (this) { if (m_running) { /* prevent the job from being started twice */ s_logger.warn("The Job " + getGroupId() + "." + getJobId() + " is already running, but should be started. Job was not started."); return; } m_running = true; } try { s_logger.info("Started scheduled job: " + getGroupId() + "." + getJobId() + ", process all PLA Orders."); IXYZService service = SERVICES.getService(IXYZService.class); try { service.doStuff(); } catch (Exception e) { s_logger.error("Error in Job " + getGroupId() + "." + getJobId(), e); } s_logger.info("Finished scheduled job: " + getGroupId() + "." + getJobId() + ", process all PLA Orders"); } finally { synchronized (this) { m_running = false; } } } }
Permissions
If such a server job is scheduled before a user is logged in, you might see the following exception:
!ENTRY org.eclipse.minicrm.server 4 0 2012-12-03 15:15:35.902
!MESSAGE org.eclipse.minicrm.server.ServerSession.execLoadSession(ServerSession.java:52) attempted login by server!ENTRY org.eclipse.osgi 4 0 2012-12-03 15:15:35.933
!MESSAGE Application error
!STACK 1
ProcessingException[ProcessingStatus[ERROR code=0 Unexpected java.lang.SecurityException: access denied]]
at org.eclipse.scout.commons.job.JobEx.throwOnError(JobEx.java:69)
at org.eclipse.scout.rt.server.services.common.session.ServerSessionRegistryService.newServerSession(ServerSessionRegistryService.java:61)
at org.eclipse.scout.rt.server.services.common.session.ServerSessionRegistryService.newServerSession(ServerSessionRegistryService.java:35)
at org.eclipse.scout.rt.server.scheduler.Scheduler.<init>(Scheduler.java:58)
at org.eclipse.scout.rt.server.scheduler.Scheduler.<init>(Scheduler.java:49)
at org.eclipse.minicrm.server.ServerApplication.start(ServerApplication.java:41)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
[snip]
This can be solved in ServerSession by letting the system user load a session before anyone is logged in:
@Override protected void execLoadSession() throws ProcessingException { SQL.selectInto("SELECT PERSON_NR FROM PERSON WHERE UPPER(USERNAME) = UPPER(:userId) INTO :personNr"); if (getPersonNr() == null && !getUserId().equals("server")) { logger.error("attempted login by " + getUserId()); throw new ProcessingException("Unknown User: " + getUserId(), new SecurityException("access denied")); } logger.warn("created a new session for " + getUserId()); }