Provides information about the Event Scheduler
Often, you need to generate events executed not immediately but postponed for a specific moment of time (relative to the current moment or fixed). The Event Scheduler Service (exported by the packages/system/scheduler.jar bundle) of RM allows you to schedule for later execution events transmitted over the RM Event Service. These events are received by the listeners registered for the corresponding event type (see RM Event Service: Subscribing for Events).
Only backend-located services can use the Event Scheduler for scheduling of events because in the RM system only backend server hosts can generate events.
Scheduling Events
If you need to schedule an event for a specific moment of time, use the Event Scheduler Service (com.prosyst.mprm.backend.event.scheduler.EventSchedulerService) on that host. You can schedule an event for a single execution when the appointed time arrives, or you can schedule an event for periodic execution at a given interval.
Event Generators
Creating Event Generators
An event generator (com.prosyst.mprm.backend.event.scheduler.EventGenerator) is responsible for creating the event at the scheduled time. If the event is to be re-sent periodically, the event generator creates the event every time the defined time period elapses.
Creating an event generator is done by calling the createEventGenerator(String id, String eventType) method of the Event Scheduler Service. The first parameter, the id, shows the unique identifier of the event generator. It is NOT assigned internally by the system but is to be explicitly set by the service developer. The developer must make sure the generator's ID is unique within the RM system. The eventType parameter indicates the type of events generated by this generator. This parameter is analogous to the eventType parameter passed to the event method of the Events Service by backend event creators. The eventType allows event listeners to receive the events they are interested in by registering for the particular event type (see RM Event Service: Registering the Event Listener). There is no difference between the events created by an event generator for a given eventType, and the events with the same eventType created directly through the Event Service. They will both be received by the appropriate event listeners.
Starting/Stopping the Event Generators
An event generator has start time and end time, describing the period during which the generator produces events. You need to explicitly start the generator in order to enable it to produce events because it is not automatically started when it is created. To start the generator, call its start()method. If you want to postpone the starting for a particular time, invoke the setStartTime(java.util.Date startTime) method of EventGenerator before calling start(). Otherwise, if you don't invoke setStartTime, the generator will be started at the current moment.
As described in the RM Event Service document, an event must have content holding the information of the event. The content of an event created by an event generator is set using the setEventData(Object data) method of EventGenerator. The Object supplied as data parameter can be one of the object types supported by the Event Service.
The Event Scheduler service running on each RM backend server host is responsible for having the Event Service send the event with the appropriate content and type when the defined time for generating the event has arrived.
Defining the stop time of the generator is done using the setEndTime(java.util.Date endTime) method respectively. If you don't specify an end time through this method, the event generator will continue to function endlessly during the runtime session of the RM backend. When the backend is restarted, the generator will start again too.
If you want the event generator to generate a set of successive events, you need to define the time period between two generated events. This is done through the setPeriod(long period) method of EventGenerator.
An event generator can be removed after it is no longer necessary using the discardEventGenerator(String id) method of the Event Scheduler Service.
Defining Execution Delays
Event generators support two modes that define the rate of event generation when unexpected delays (such as temporary stopping of the RM or the system is too busy) occur in the system:
- Fixed-rate mode - In this mode, the execution of scheduled events is relative to the scheduled start time of the generator. If an execution is delayed for any reason, two or more executions will occur in rapid succession to "catch up". Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. Finally, fixed-rate execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
- Fixed-delay mode - In this mode, each execution is relative to the actual execution time of the previous event. So, if an execution is delayed for some reason, subsequent event executions are delayed too.
The default delay mode is fixed-delay. If you want to set fixed-rate mode, use the setFixedRate(boolean fixedRate) method of the event generator.
Delay Tolerance
For fixed-delay event generators, you can define the maximum acceptable delay for event execution by specifying delay tolerance. If an event is delayed more than allows the defined delay tolerance, it will not be generated at all. Specifying delay tolerance is useful when the periodical task associated with a generator must be executed in a particular absolute time or not executed at all. By default, the permissible delay interval is equals to the period, i.e. it only ensures that several sequential events are not overlapped.
To define or check the delay tolerance, use the setDelayTolerance(long delayInterval) or getDelayTolerance(long delayInterval) method respectively of the event generator.
Example
Let's clarify the above explanations through a simple example that schedules events using the Event Scheduler Service. We'll create a sample service that notifies us that it's rest time after each 45-minute period of work, and notifies that it's time to go back to work after a 15-minute rest.
The work-rest notification is acquired by creating two event generators, both sending events of type "test.workday". However, the first one sends the "RESTTIME" event each hour (starting 45 minutes after its creation), while the second one sends the "WORKTIME" event each hour (starting 60 minutes after its creation).
After that, it obtains all event generator objects currently available in the Event Scheduler Service, and lists some details about them.
A sample bundle that schedules a number of events through the Event Scheduler:
import java.util.Hashtable;import org.osgi.framework.*;import com.prosyst.mprm.backend.event.*;public class EventsActivator implements BundleActivator { private ServiceReference eventRef; private EventService eventService; private EventThread customizedEventThread; private EventThread generalEventThread; public void start(BundleContext bc) throws Exception { // Getting the Event Service eventRef = bc.getServiceReference(EventService.class.getName()); if (eventRef != null) { eventService = (EventService) bc.getService(eventRef); // Starting generation of general events sendGeneralEvent(); // Starting generation of property-enabled events sendCustomizedEvent(); } else { throw new Exception("The Event Service is unobtainable:-("); } } public void stop(BundleContext bc) throws Exception { // Killing event threads customizedEventThread.stop(); customizedEventThread = null; generalEventThread.stop(); generalEventThread = null; // Ungetting the Event Service if (eventRef != null) { bc.ungetService(eventRef); eventService = null; eventRef = null; } } private void sendGeneralEvent() throws EventListenerException { // Launching the thread generating general events generalEventThread = new EventThread(false); new Thread(generalEventThread, "My General Event Thread").start(); } private void sendCustomizedEvent() { // Launching the thread generating property-enabled events customizedEventThread = new EventThread(true); new Thread(customizedEventThread, "My Customized Event Thread").start(); } // A thread which generates events by using the RM Event Service private class EventThread implements Runnable { private static final String RAC_USER_NAME = "RAC User"; private static final String TEST_EVENT_TYPE = "test"; private static final String MY_APP_EVENT_PROPERTY = "my.app.event.property"; boolean running = false; boolean isFalse = false; private Object monitor; private boolean isCustomized; EventThread(boolean isCustomized) { monitor = new Object(); running = true; this.isCustomized = isCustomized; } public void run() { Hashtable eventTargetProps = new Hashtable(); try { while (running) { if (isCustomized) { // Generating events with properties eventTargetProps.put(MY_APP_EVENT_PROPERTY, Boolean.valueOf(isFalse)); eventService.event(TEST_EVENT_TYPE, "test event", eventTargetProps, RAC_USER_NAME); System.out.println("[EventThread] Customized event sent!"); // Inverting the value of the event property // "my.app.event.property" isFalse = !isFalse; } else { // Generating general events eventService.event(TEST_EVENT_TYPE, "test event"); System.out.println("[EventThread] General event sent!"); } // Waiting for 100 seconds till next event generation synchronized (monitor) { monitor.wait(10 * 1000L); } } } catch (EventListenerException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } // Kills the thread private void stop() { synchronized (monitor) { monitor.notifyAll(); } running = false; } }}The events generated by the above example will be received by all event listeners registered for event type "test.workday".