January 22 2015

A very common use case for using an SLA (Service Level Agreement) is when there is a start date-time (not necessarily the current date-time) and an end date-time and you want to use the time difference between those two dates as your SLA in your BPM process. In the good old BPM 10g days you could do that easily. You could take the two dates and subtract one from the other and the result could be used as a SLA value. Unfortunately, the same cannot be done in BPM 11g as easily but we do have a solution.

The following will demonstrate how the above scenario can be achieved in BPM 11g. Since the SLA calculation itself is just a few lines of Java code, we will use a BPEL component called 'Java Embedding' for it. It does exactly what the name suggests; it embeds Java code into a BPEL process. In this blog, we will kill two birds with one stone and will look at the Java code to calculate the SLA value and also look at how to embed that into a reusable BPEL process. The BPEL process can then be referenced or invoked from any client, including a BPM process.

  1. Create a very simple reusable synchronous BPEL process. This BPEL process will be the SLA calculation utility. The input payload will have the two date-times (start date-time and end date-time) as strings. The output payload will have the calculated SLA value as string.
     
  2. We will set the output variable in the ‘Java Embedding’ component later, but for it to work the output variable has to have already been initialized. Therefore, let’s initialize the output variable. Drag the ‘Assign’ component and give it an appropriate name and assign a default value to the output variable. I have assigned it ‘PT60M’, which translates to 60 minutes Duration. Here are some examples of Duration code:

    PT5M - five minutes
    P1D - a day
    P1M - a month
    P1Y1DT1H1S - one year, one day, one hour, and one second


     
  3. Now we will write the Java code to calculate the SLA value. Drag the ‘Java Embedding’ component under the ‘Oracle Extensions’ onto your BPEL process and give it an appropriate name.


  4. This component works like a plain text editor. It does not offer any coding functionality like code completion, typo warnings, etc. so you have to be very careful of what you type. Fortunately for you, we have the code you need, so just copy/paste it.
    The input1 and input2 variables will be assigned with your start date-time and end date-time input variables respectively. The output1 variable will be assigned with your SLA output variable. Those are the only changes you will have to make.
    
    try {   
        addAuditTrailEntry("Executing DateDiff.JavaEmbeddingSLACalculation.");   
        SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        String diffDatePeriod = "P";
    
        XMLElement input1 = 
        (XMLElement) getVariableData("inputVariable", "payload", "/ns1:purchaseOrderUS/ns1:orderDateStart");
        XMLElement input2 = 
        (XMLElement) getVariableData("inputVariable", "payload", "/ns1:purchaseOrderUS/ns1:orderDateEnd");  
    
        Date d1 = format.parse(input1.getTextContent());
        Date d2 = format.parse(input2.getTextContent());
        addAuditTrailEntry(d1 + " " + d2);
    
        long diff = d2.getTime() - d1.getTime();
        long diffSeconds = diff / 1000 % 60;
        long diffMinutes = diff / (60 * 1000) % 60;
        long diffHours = diff / (60 * 60 * 1000) % 24;
        long diffDays = diff / (24 * 60 * 60 * 1000);
    
        diffDatePeriod = diffDatePeriod + diffDays + "DT";
        diffDatePeriod = diffDatePeriod + diffHours + "H";
        diffDatePeriod = diffDatePeriod + diffMinutes + "M";
        diffDatePeriod = diffDatePeriod + diffSeconds + "S";
    
        setVariableData("outputVariable", "payload", "/ns2:OrderAudit/ns2:ActivitySLA", diffDatePeriod);
        XMLElement output1 = 
        (XMLElement) getVariableData("outputVariable", "payload", "/ns2:OrderAudit/ns2:ActivitySLA");
        addAuditTrailEntry("ActivitySLA: " + output1.getTextContent());
    
        addAuditTrailEntry("Finished DateDiff.JavaEmbeddingSLACalculation.");
    
    } catch (Exception e) {   
        System.out.println("exception "+e.getMessage());   
        addAuditTrailEntry(e);   
    }


    Big thanks to Oracle Ace Dan Atwood for providing some of this code to me. You can check out his amazing training material here.
     
  5. Since we are writing Java code, we need to import a few classes for the Java code to work. Click on the ‘Source’ tab of your BPEL process and add the following import statements after the <process> tag. These import statements work with BPEL 2.0 Specification. The import syntax is different for BPEL 1.1 Specification.
     
    <import location="oracle.xml.parser.v2.XMLElement" importType="http://schemas.oracle.com/bpel/extension/java"/>
    <import location="java.text.SimpleDateFormat" importType="http://schemas.oracle.com/bpel/extension/java"/>
    <import location="java.util.Date" importType="http://schemas.oracle.com/bpel/extension/java"/>
  6. You are now done creating your utility. Your completed reusable synchronous BPEL process should look similar to this and will be available (as a SOAP service) to be used from anywhere.


  7. Create a client (a BPM process in this example) to use this utility. Below, the ‘Call DateDiff’ makes a service call to the BPEL process with the two dates as input variables and gets back a SLA value to be used in the BPM process. The Catch Timer Event ‘CatchEvent1’ uses this SLA value.


  8. Deploy your composite(s) and test it out from your client.

    In the example below we provided the input dates, as shown below.



    Based on the two input dates, the SLA calculated is 1 minute, as shown below.



    The SLA is set and then fired after 1 minute, as shown below.

The above example used the Catch Timer Event, but this SLA can be used and set on other BPM components like Start Timer Event, Human Task Boundary Event, and Human Task Deadlines. Please feel free to leave me your questions and comments.

Join the Conversation

June 4, 2015

Can't we use xsl transformation 

June 19, 2015

Hi,

Thats an interesting approach and very informative. We had a similar requirement on a recent 11g BPM project and noted there was no out of the box functions to achieve this.

The way in which we tackled the issue was to implement a custom xpath function that could be instantiated from either XSLT / Assign (BPEL) / Data Association (BPM). This function can then be invoked as and when you require to calculate the duration between dates.

Thanks Again
David

June 21, 2015

Hi Suyesh,

Awesome article.
In 10g we have opportunity to calculate SLA by using calendar which can help in determining the non working days.

Where in 11g we don't have that opportunity.
Your inputs can help us solving the problem
Thank you
Prabha

shashi Kanth
March 30, 2016

Hi ,

Kindly let us know to how to add sla based on Calender.

if there is holidays, SLA duration should be based on working days.

 

thanks in advance,

shashi Kanth

Raj
April 5, 2016

Hi Suyash,

I have a quick question; if I like to terminate task (STALE state) will SLA timer will be terminated??

As of now its not happening. Is there any API to kill it explicitly.

Thanks

Enter your first name. It will only be used to display with your comment.
Enter your email. This will be used to validate you as a real user but will NOT be displayed with the comment.
By submitting this form, you accept the Mollom privacy policy.