Tuesday, May 1, 2012

Scheduling a Process in SOA 11g

"Scheduling" is one of the most common tasks that many projects require. We may need to initiate a process on a specific time based on a schedule i.e,  in a particular day of a month or in an hour/min in a day .This feature is not available out-of-box  in SOA 11g. Most common and easy to use approach is to use the Quartz scheduler and its supported java classes that can be used to schedule the process based on a time schedule.

Outline of the Steps to Schedule a BPEL Process using Quartz are as follows:

0. Create and make the wsdl of the BPEL process that needs to be scheduled available.

1. Create a WebService Proxy for the BPEL process that you may want to schedule.
This will create a Client and a Port java classes which can be used to invoke the bpel process operations from java code.

2. Create a Job( class that implements org.quartz.Job) that calls the BPELProcess operation(s)( using its client and port classes that were created as a result of step 1).

3. Create a JobTrigger class trigger that will trigger the above Job in a specific schedule.

In Detail here is  how it works :

Assuming the Process to be scheduled is HelloWorld Process and its wsdl is - http://localhost:8001/soa-infra/services/default/HelloWorldProject/HelloProcess.wsdl

Detailed Steps :

a. Create a Generic Application and name it SoaScheduleApp.

b. Create a Project(say SoaSchedulerProject) and select java,webservices as project technologies.

c. Create a new Web Service Proxy (webservices),selecting JAX-WS client style for the HelloWorld wsdl -
 http://localhost:8001/soa-infra/services/default/HelloWorldProject/HelloProcess.wsdl. You may prefer to copy the wsdl into the project. Select some package name and root package for genric types. Click finish.

d.  This will create the HelloProcess_client_ep.java which is a client Service that contains methods returning Port of the Service.( ex: getHelloProcess_pt()). The Port is of type HelloProcess interface which represents  a Port that defines operations of the Service.

e. Add Quartz Library to the project.
   Click on “Application”-> “Project Properties”,-> " Libraries and Classpath"->“Add JAR/Directory”.
   Select in your JDeveloper home “…\jdeveloper\soa\modules\quartz-all-1.6.5.jar”. Click “Select”.
   Click Ok.

f.    Create a Job component - a Java class which contains the following code.

package sample.oracle.otn.soascheduler.job;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import sample.oracle.otn.soascheduler.proxy.Helloprocess_client_ep;
import sample.oracle.otn.soascheduler.proxy.HelloProcess;
import javax.xml.ws.WebServiceRef;
import org.quartz.Job;
import org.quartz.JobExecutionContext;

import sample.oracle.otn.soascheduler.proxy.Helloprocess_client_ep;

public class DemoJob implements Job{
private static Helloprocess_client_ep helloworldprocess_client;
public DemoJob() {
        helloworldprocess_client = new Helloprocess_client_ep();
public void execute(JobExecutionContext jobExecutionContext) {
        DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.println("HelloWorldJob started");
try {
          helloworldprocess_client = new Helloprocess_client_ep();
HelloProcess helloWorldProcess = helloworldprocess_client.getHelloProcess_pt();
// Add your code to call the desired methods.
System.out.println("HelloWorld Response: " + helloWorldProcess.process("SOAScheduler@" +
        } catch (Exception e) {
          System.out.println("HelloWorld Process failed: " + e.toString());

Observe that it Implements org.quartz.Job and contains the code to call the BPEL process operation in its method execute(..)

g.  Create a Job Scheduler class that triggers the above Job using Cron expressions.
This JobScheduler does 3 things .
i. Creates multiple JobDetails  using org.quartz.JobDetail.
ii. Configure Scheduler time using org.quartz.CronTrigger.setCronExpression(..)
iii. Create the schedule using org.quartz.Scheduler.

Code looks like this :

package sample.oracle.otn.soascheduler.job;

import java.util.Map;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.impl.StdSchedulerFactory;

public class JobTrigger {
  public static void main( String[] args ) throws Exception
        //scheduler task details
        JobDetail job = new JobDetail();
        JobDetail job2 = new JobDetail();

        //configure scheduler time
        CronTrigger trigger = new CronTrigger();
        trigger.setCronExpression("0/30 * * * * ?");

        //configure scheduler time 2
        CronTrigger trigger2 = new CronTrigger();
        trigger2.setCronExpression("0/20 * * * * ? 2013");

        //create the schedule
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.scheduleJob(job, trigger);
        scheduler.scheduleJob(job2, trigger2);


h. Thats it !!. Now its time for execution. Run the  JobTrigger  class's main method and observe that your BPEL process is being triggered for every 30 seconds.

For understanding the cron expression refer - http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger


Now that we are aware of the steps to schedule a bpel service, lets talk about how we can extend and reuse this across projects.
Lets say, in some later point of time, you may need to schedule another process with a different time schedule. example : A Pharma company wants to check its inventory availability every 10 days and make some decisions to reach or not reach to suppliers. For doing so rather than re-inventing the wheel all again we shall do the following.

1. Create WebService Proxy for new Process WSDL.
2. Create another Job component to execute the new process Operation.
3. Reuse the JobTrigger class by making the required additions to create a new JobDetail and schedule the JobDetail using the new cron expression.