The Scheduler Service Engine (SE), powered by OpenSymphony Quartz
, affords scheduling capability to kick off (consume) other JBI component providers, for example a BPEL Service Engine.
Schedules are specified by creating a Scheduler project and subsequently a Schedule XML file containing one or more triggers that determine when to send the user specified message to the appropriate provider endpoint; the latter is configured via the Composite Application Service Assembly (CASA) editor.
When the Scheduler project is built, appropriate Web Service Definition Language (WSDL) files and a Service Unit Descriptor file (jbi.xml) are generated that can be used, for example, to define the respective Partner Links in a BPEL that's to be triggered by the Scheduler.
Lastly, the Scheduler project and other relevant projects (for example, BPEL project) are added into a Composite Application project, where the various Scheduler consumer endpoints can be connected to their respective to-be-triggered provider endpoints.
Current (Release 1.0)
- The Scheduler SE currently only supports statically defined schedules (that is, via Schedule files contained in a Scheduler project).
- Quartz SimpleTrigger
(for example, do something every 30 seconds) is supported.
Planned
- Quartz CronTrigger
(a la Unix crontab) will be supported soon.
- Dynamically defined and persisted schedules. In other words, a consumer endpoint can send a new schedule request to the Scheduler SE provider endpoint and at the appointed time, the respective trigger message will be sent back to same endpoint but of course, now in a provider role.
Architecture
Most of us have used schedulers like Mozilla Lightning or MS Outlook and are familiar with creating appointments whereby we can specify together the time when to perform a certain task as well as the task itself. To provide scheduling service in the JBI world, the definition of a trigger or time to send a message, in other words consume a service provider, is first declared in a Schedule file under a Scheduler project and then the actual connection of the trigger consumer endpoint to the intended task or service provider endpoint is done later in the CASA (Composite Application Service Assembly) editor. When the service assembly is deployed, messages specified during the trigger definitions and at the appointed times will be routed via the NMR (Normalized Message Router) to the waiting provider endpoints that will process the messages and execute the appropriate tasks.
The Scheduler SE is powered by OpenSymphony Quartz API and as such, the latter requires each trigger defined to belong to a unique group. Typically, a NetBeans project name is fairly unique and so the Scheduler project name is used as the Quartz group name. Moreover, this group name appended by the Schedule file name and the suffix Port form the consumer endpoint name for all the triggers contained in the Schedule file. Thus, one Schedule file can only be used to trigger one task or provider endpoint, albeit at multiple times represented by the one or more triggers contained within.
Source Code
Issue Tracker
Steps
These instructions will illustrate how to trigger JBI components (service providers) using a Scheduler project. It is assumed that the reader is familiar with the JBI paradigm and in particular, how to design a BPEL project to implement and invoke specific web services.
- Step 1
- Go to File | New Project... | SOA (category) | Scheduler Module (project)
- Step 2
- Key in Project name. The name forms the first half of the Scheduler consumer endpoint name so choose one that's meaningful yet succinct (no spaces or other unsavory characters for now), for example schedules related to a particular demo, such as SchedulerDemo.
- Step 3
- Right-click the project's Process Files folder and choose New | Schedule File...
- Step 4
- Key in Schedule file name. The name forms the latter half of the Scheduler consumer endpoint name so again, choose one that's meaningful yet succinct (no spaces or other unsavory characters for now), for example what this particular schedule will trigger, such as KickOffBPEL (don't prvoide any extensions in the name for a standard .sched extension is always used).
- Step 5
- In the ensuing Schedule editor, click the Add Simple Trigger toolbar button and a new trigger row will appear in the table below.
- Step 6
- With the respective trigger table row highlighted (note, the Selected checkbox is used for indicating triggers selected for deletion), you can specify the various parameters for that trigger. Changes to a field are registered when either focus is lost or an Enter key is pressed (except for the Message text area since it will accept newlines as part of the data).
- The Starting and Ending Date & Time entries delineate when this trigger will be active. Until a date/time chooser is implemented (very soon; or please donate if you have a good free open-source one), you'll need to enter one manually in the default locale format (Java SimpleDateFormat
is used); the first item in the Job Date Format exemplifies the default locale format. Alternatively, if you want the trigger to be active immediately after the Composite Application has been deployed, choose Now and similarly select Never if the active period has no end.
- A simple trigger basically repeats after a certain time interval so specify the Repeat Count or Indefinite and the various time units that comprise the overall time interval.
- Finally, the Job section pertains to the Message that will be sent when the trigger fires and will contain a metadata part that details the appointed date and time the trigger was configured to fire (note, this may precede the actual time the message is received due to network latency) in the specified Date Format. Moreover, the metadata will also contain the trigger's name and group to which it belongs.
 |
- Step 7
- Save your work and build the Scheduler project.
- Step 8
- Use the generated WSDL files as appropriate to set up the provider endpoints to be triggered.
- Step 9
- Create a JBI project that provisions the desired endpoints to be triggered, for example in the following BPEL project.
- Step 10
- Add this Scheduler project and other required ones into a Composite Application project.
- Step 11
- Connect the various Scheduler consumer endpoints with their respective provider endpoints to be triggered.
- Step 12
- Save Composite Application project, build, and deploy into running instance of GlassFish Application Server.
Schedule XML File Syntax
Here's what a typical one looks like:
<?xml version="1.0" encoding="UTF-8"?>
<schedule name="kickOffBPEL" group="SchedulerDemo"
xmlns="http://schemas.sun.com/jbi/engines/scheduler"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.sun.com/jbi/engines/scheduler schedule.xsd">
<trigger name="everyMinute" enabled="true" description="Triggering the BPEL usecase every minute">
<simpleTrigger>
<starting>
<date value="now"/>
</starting>
<ending>
<date value="9/30/08 11:59 PM"/>
</ending>
<repeat count="indefinite">
<interval minutes="1"/>
</repeat>
</simpleTrigger>
<message date-format="M/d/yy h:mm a">Send status to loan applicant!</message>
</trigger>
</schedule>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.sun.com/jbi/engines/scheduler"
xmlns:sched="http://schemas.sun.com/jbi/engines/scheduler"
elementFormDefault="qualified">
<xsd:complexType name="scheduleType">
<xsd:sequence>
<xsd:element ref="sched:trigger" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>Defines a Quartz trigger belonging to the group specified in the schedule element.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>Name for the set of triggers in this schedule. Note, this name forms the latter half of the prefix for the resultant Scheduler SE Consumer Endpoint name.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="group" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>Group name for the set of triggers in this schedule. Note, this name forms the first half of the prefix for the resultant Scheduler SE Consumer Endpoint name.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="description" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>Optional description for this schedule.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="triggerType">
<xsd:sequence>
<xsd:choice>
<xsd:element ref="sched:simpleTrigger" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines a Quartz Simple Trigger that is interval-based (http://www.opensymphony.com/quartz/api/org/quartz/SimpleTrigger.html).</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:choice>
<xsd:element ref="sched:message" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines the message that will be sent to the respective service provider endpoint that is to be triggered.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>Name of the Quartz trigger and must be unique within the group.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="enabled" type="xsd:boolean" default="true" use="optional">
<xsd:annotation>
<xsd:documentation>If enabled, the Quartz trigger will be activated at runtime.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="description" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>Optional description for this trigger.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="simpleTriggerType">
<xsd:sequence>
<xsd:element ref="sched:starting" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines the date when this trigger will start operating.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="sched:ending" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines the date when this trigger will end operating.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="sched:repeat" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines how often the trigger will be repeated.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="startingType">
<xsd:sequence>
<xsd:element ref="sched:date" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines the starting date.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="dateType">
<xsd:sequence/>
<xsd:attribute name="format" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>Format of date value being specified (per http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html) If not specified, format defaults to locale's default pattern.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="value" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>value can be "now" or "never" (case-insensitive and of course, format is ignored accordingly) or value corresponding to specified format.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="endingType">
<xsd:sequence>
<xsd:element ref="sched:date" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines the ending date.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="repeatType">
<xsd:sequence>
<xsd:element ref="sched:interval" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>Defines the time interval between repeats of this trigger.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="count" type="xsd:string" use="optional" default="indefinite">
<xsd:annotation>
<xsd:documentation>count can either be "indefinite" or ant int value.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="intervalType">
<xsd:sequence/>
<xsd:attribute name="weeks" type="xsd:long" default="0" use="optional">
<xsd:annotation>
<xsd:documentation>Week (7 days) component in the interval.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="days" type="xsd:long" default="0" use="optional">
<xsd:annotation>
<xsd:documentation>Day (24 hours) component in the interval.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="hours" type="xsd:long" default="0" use="optional">
<xsd:annotation>
<xsd:documentation>Hour (60 minutes) component in the interval.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="minutes" type="xsd:long" default="0" use="optional">
<xsd:annotation>
<xsd:documentation>Minute (60 seconds) component in the interval.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="seconds" type="xsd:long" default="0" use="optional">
<xsd:annotation>
<xsd:documentation>Second (1000 milli-seconds) component in the interval.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="millisecs" type="xsd:long" default="0" use="optional">
<xsd:annotation>
<xsd:documentation>Milli-second component in the interval.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="messageType" mixed="true">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:any processContents="skip"/>
</xsd:choice>
<xsd:attribute name="date-format" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>format of date appearing in the meta-data portion of the message sent when this trigger occurs, per http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:element name="schedule" type="sched:scheduleType">
<xsd:annotation>
<xsd:documentation>Defines one or more trigger(s) for this schedule.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="trigger" type="sched:triggerType"/>
<xsd:element name="simpleTrigger" type="sched:simpleTriggerType"/>
<xsd:element name="starting" type="sched:startingType"/>
<xsd:element name="date" type="sched:dateType"/>
<xsd:element name="ending" type="sched:endingType"/>
<xsd:element name="interval" type="sched:intervalType"/>
<xsd:element name="repeat" type="sched:repeatType"/>
<xsd:element name="message" type="sched:messageType"/>
</xsd:schema>
System Requirements
- NetBeans 6.1 with Patch 3 (available via NetBeans Update Center after installing standard NetBeans 6.1, or simply use the OpenESB Installer)
- JDK 1.5 or greater
Binaries
- Complete OpenESB Installer available here