The Scheduler Swiftlet is an enterprise job scheduler to run registered jobs at a configurable schedule which can be based on stackable calendars.
Jobs are registered from other Swiftlets at the Scheduler Swiftlet. The registration takes place in job groups, one for each Swiftlet. Each registered job consists of meta data that describes the job and its job parameters.
A schedule must be created to run a job. This is done by the user/administrator via SwiftMQ Explorer/CLI. After the schedule has been enabled, the Scheduler Swiftlet takes care to create and run job instances on base of the schedule's time expression. A job is stopped when it reaches the maximum runtime or the job instance marks itself as finished.
A schedule can be based on a calendar. e.g. to run a job on business days only. See next section. The time when a job should start is specified as a time expression. It can be a 'at' or a 'repeat' expression to start the job at fixed time points during a day or in a repeat interval, respectively. If the job requires parameters, they must be specified in the schedule and will be passed to the job instance during the job start. Optionally, a maximum runtime can be specified. If this amount of time is reached, the job instance is stopped by the Scheduler Swiftlet. A schedule has a date range in which it is valid. For example, one can specify a start date 15th February 2003 and an end date of 14th April 2003. The defaults for start/end date are "now" and "forever", respectively.
A calendar decides at which day a job will run whereas a schedule's time expression decides at which time. A schedule can be optionally based on a calendar. If not, the job will run every day.
A calendar has multiple parts which can be enabled separately. Parts are week days, month days, last day in month, annual days, date ranges. The type of a calendar is either "include" or "exclude". A "include" calendar includes the calendar dates whereas "exclude" excludes it.
One or more parts of a calendar can be enabled. It is also possible to stack calendars by using another calendar as a base calendar for a new calendar. For example, one may create a calendar "Business Days" with Mo-Fr enabled and another calendar "Bank Holidays" which is based on "Business Days" to exclude bank holidays from business days. Arbitrary trees of calendars can be build with stacked calendars to create whatever final custom calendar.
To create your own jobs with other scheduler products, you have to use their scheduler classes, implement their interfaces, and you become locked into their product. Not so with SwiftMQ! All jobs in SwiftMQ are provided from Swiftlets. They are already there. No need to implement anything. A bunch of functionality is already implemented, for example, a job to move the content of a local queue to a queue on a remote router, a job to perform a backup on the store, or a job to schedule a routing connector, and much more.
However, that's not all. The JMS Application Container Swiftlet provides a generic "Application Invoker" job that can invoke any static JMS application (one which runs embedded in SwiftMQ). Thus, any Java application, no matter what it does (it doesn't need to use JMS at all), is a potential job. You only have to configure it in the JMS Application Container Swiftlet as a static application and you can schedule it as a job out of the box. The only pre-condition is to have a custom shutdown method in your application to ensure it can be stopped. This method is discovered by Java reflection, so no vendor lock-in, no proprietary interfaces!
If that is not yet enough, you can of course use the Swiftlet API, create your own Swiftlets and register your own jobs.
Any JMS client can use the Scheduler Swiftlet to schedule a message job. For this the Scheduler Swiftlet listens on a queue "swiftmqscheduler" of the local router. To schedule such a message job, a JMS client creates a JMS message of whatever type, fills it with content and sets some JMS-vendor properties to define the schedule. The Scheduler Swiftlet accepts the message, verifies it and automatically creates a schedule of a "Message Sender" job which is provided from the Scheduler Swiftlet itself. This job sends the very same message to the specified destination on the schedule, specified via the JMS properties in the message.
MapMessage msg = session.createMapMessage();
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_COMMAND","add");
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_DESTINATION","testqueue@router1");
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_DESTINATION_TYPE","queue");
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_CALENDAR","Business Days");
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_DATE_FROM","2003-02-17");
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_DATE_TO","2003-02-28");
msg.setStringProperty("JMS_SWIFTMQ_SCHEDULER_TIME_EXPRESSION","start 09:00 stop 18:00 delay 10s");
msg.setBooleanProperty("JMS_SWIFTMQ_SCHEDULER_ENABLE_LOGGING",true);
msg.setLongProperty("JMS_SWIFTMQ_SCHEDULER_EXPIRATION",60000);
msg.setStringProperty("prop",args[3]);
msg.setJMSReplyTo(tq);
msg.setBoolean("b1",true);
msg.setBytes("bytes1",new byte[]{1,2,3,4});
msg.setFloat("float1",10.0f);
msg.setString("s1","String1");
sender.send(msg);
QueueReceiver receiver = session.createReceiver(tq);
Message reply = receiver.receive();
boolean error = reply.getBooleanProperty("JMS_SWIFTMQ_SCHEDULER_ERROR");
if (!error)
System.out.println("ID: "+reply.getStringProperty("JMS_SWIFTMQ_SCHEDULER_ID"));
else
System.out.println("Error: "+reply.getStringProperty("JMS_SWIFTMQ_SCHEDULER_ERROR_TEXT"));
With this it is possible to schedule a message to be delivered 2 hours later or in a repeat interval (like a heart beat message) and so on. Such a message job can be programmatically removed by a JMS client or is removed automatically when the schedule expires. A message job survives reboots if the message is persistent.
The Scheduler Swiftlets provides 2 scheduler tables to view the status of all scheduled "normal" jobs and all message jobs. Each job contains a history with the last 20 job events. A schedule can be "log-enabled" to log each start/stop in the router's log file.