Original URL: http://www.theregister.co.uk/2007/07/16/bpelj_compensation/

Programming constructs in BPEL

Part 3: BPELJ and Compensation

By John Hunt

Posted in Developer, 16th July 2007 14:07 GMT

In this column in our series examining BPEL and its use within Service Oriented Architecture (SOA) systems, I'll will be looking at BPELJ and Compensation.

BPELJ is an extension to the core BPEL (Business Process Execution Language), which allows the direct inclusion of Java code within a BPEL script. Compensation is actually a core element of BPEL that provides an undo-like facility for situations where part of a BPEL script fails and other parts require their effects to be undone.

BPELJ

The aim of BPELJ is to let you embed Java and J2EE processes in a BPEL process. The intention is to allow portable integration of Java and J2EE applications into BPEL across application servers. In practice, most BPEL engines have allowed integration with programming languages such as Java in one form or another for some time, but via their own proprietary extensions. Thus, there have been BPEL extensions without portability, which I personally find extremely frustrating - because I need to support multiple application server environments.

BPELJ offers a glimmer of hope, in that it aims to provide a standard extension to BPEL for inline Java. The aim of BPELJ is to combine the power of a general purpose programming language such as Java with the orchestration and integration facilities of BPEL. By doing this, developers are free to select the appropriate "programming" language for the level of task they are implementing.

The Design of BPELJ

The design of BPELJ allows Java code to be embedded directly within a BPEL script in similar way to the embedding of Java within a JSP page. That is, BPELJ allows sections of Java code, called Java snippets, to be included in BPEL process definitions. Snippets are expressions or small blocks of Java code used for such things as loop conditions, branching conditions, variable initialisation, calling methods on Java objects etc.

Within BPEL standard extension points are used to support BPELJ. For example, a new partner link type is defined that references Java code; variables can now be typed as being of a specific Java class; and BPELJ code snippets can contain valid Java code statements, with the ability to invoke methods on Java classes from within BPEL statements.

BPELJ Examples

The following BPEL script illustrates the concepts presented in the above section. I've omitted much of this example for clarity, however, the core BPELJ elements remain:


<process name="BookCheck" 

expressionLanguage="http://jcp.org/java"

bpelj:package="com.regdev.example"

xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"

targetNamespace="http://regdev.com/bp/BookCheck"

xmlns:bpelj="http://schemas.xmlsoap.org/ws/2003/03/business-process/java"

xmlns:pq="http://regdev.com/ws/external/BookCheck">

<partnerLinks>

      ...

      <partnerLink name="lookup"  

              partnerLinkType="bpelj:com.regdev.BookLookup"/>

<variables>

   ....

   <variable name="message" type="bpelj:com.regdev.TextMessage"/>

</variables>

<sequence>

...

<flow>

...

</flow>

<bpelj:snippet name="Calculate Total">

   <bpelj:code>

      ...

      subtotal = subtotal * (1 – discount.getRate());

      response.setSubtotal(subtotal);

      float taxes = subtotal * taxRate;

      float total = subtotal + taxes;

      response.setTax(taxes);

      response.setTotal(total);

      ...

   </bpelj:code>

</bpelj:snippet>

...

<invoke partnerLink="BookLookup" operation="checkRegistration">

    <input part="Title" variable="title"/>

    <input part="ISBN" variable="isbn"/>

</invoke>

...

</sequence>

</process>

The first thing to note in this script is the two attributes for the whole process at the start. These are used to define the default expression language (which in this case is Java) and the default package (bpelj:package="com.regdev.example") that should be used with any emebedded Java code within the script. That is, all Java code should be considered to be part of the com.regdev.example package.

Next, note that the <partnerLinks> section includes a partner link to a "lookup" resource. This is actually a Java class, such as an EJB, that will be used elsewhere within the script.

In the variables section, a new variable message is defined as a type defined by a class TextMessage within a package com:.regdev.

Later in the script, a Java snippet can be seen. A Java snippet contains valid Java expressions or statement blocks. These blocks are embedded in a BPEL process definition and have access to certain variables defined within the execution space of the script (in a similar manner to the way in which JSPs can contain embedded Java code that can access certain variables within a JSP).

Finally, an invoke section illustrates how a method is invoked on a Java class. In this case the method checkRegistration on the class indicates by the partner link referenced by BookLookup (i.e. com.regdev.BookLookup). The method checkRegistration takes two parameters a (book) title and an isbn.

BPELJ - is this the right answer?

In an earlier column, I indicated that BPEL represented Programming in the Large, whereas programming languages such as Java represent Programming in the small. I am left wondering whether there's a fundamental dichotomy between the two approaches. Is it really appropriate to define business functions in Java within a BPEL definition? Does this promote the flexibility claimed for BPM and the use of BPEL?

If we look at the implementation of BPELJ, I'm again left wondering about the success of the final result. The intention, as mentioned earlier, was to use the strengths of both to provide something that is more than the sum of its parts. However, we end up with a syntax that is less than "clean", in my opinion, as a programming language (notably, a criticism I've also been levelling at JSPs for years). Embedding Java within BPEL Java snippets might work well if there was a development tool hiding the details, but in its raw form it's hamstrung by embedding it in an XML-based pseudo-programming language.

Compensation

The idea behind compensation is that in any long running business process, situations may occur in which it's necessary for the whole business process to be terminated tidily. However, within such business processes, the systems being integrated tend to be asynchronous in nature. They may represent both new and legacy applications, may or may not have the ability to rollback any side affects of any services executed etc.

In such situations, when a business process must be terminated, it may be necessary to communicate with one or more systems that have previously completed their activities, in order to tell them to undo what they've done. The goal of compensation is to support the reversal of the effects of previous activities that have been carried out as part of the process now being terminated.

Compensation overview

Having read the introduction, perhaps you are thinking, so what exactly is compensation? I find it useful to think of compensation being used in the following scenario for a holiday booking business process:

To book a holiday we might create a business process that defined three specific steps:

  1. Booking a hotel
  2. Booking a hire car
  3. Booking a flight

In such a scenario compensation behaviour might be defined for each of these steps such that if the hotel and the hire car are booked but a flight cannot be found then the hire car and the hotel booking can be undone - this undoing process is compensation.

In practice, compensation has two parts a compensation handler and a compensate activity. A compensation handler is associated with a "scope". A scope is a container and context for other activities (you might considered it to be analogous to a {}block in Java). For example, the "Booking a Hotel" step above could be a scope. Indeed, the above example could be considered to have three scopes, one for each booking. Thus, each scope would have its own compensation process defined for it. The compensation process is referred to as the "compensation handler" and defines how the compensation is implemented (i.e. how the undo behaviour should be performed).

The compensation handler can also be invoked indirectly by a compensate activity. When this happens the compensation handler is invoked on an inner scope activity that has already successfully completed, and it can be invoked only from within a fault handler or another compensation handler.

What compensation is not

So having indicated that compensation is essentially like an undo facility for BPEL, let us now consider what it is not. It is not an exception handling or fault handling mechanism. It is also not an exception handling mechanism (this is worth saying, as a scope looks a bit like a try block within Java - at least conceptually). A suitable analogy might be that if you are using an editor and undo some operations; this is because you have decided to take a different course of action - not because the editor has generated an error.

Indeed, you'll find that BPEL also includes the ability to catch and handle errors at different levels of activity nesting. A fault handler can be defined on any scope and either bound to a particular kind of fault (defined by the fault's qualified name - a bit like an exception, or its message type) or to any faults not caught by a more specific handler. A handler simply contains an activity that will run in case an error occurs. For example, it might contain a reply activity that notifies a partner that an error has occurred.

This makes it clear that Compensation is not error handling - it is what should happen when I want to roll back some activities within the overall business process. I use the term roll-back here - but also do not want to imply that this is some form of distributed transaction rollback - instead, you have to decide what happens to undo any effects of what has gone before. There is nothing automatic in this, there is no DBMS handling the rollback.

Compensation example

In the overview of compensation, I introduced the idea of a holiday booking BPEL script that allowed hotel, hire car and flight bookings to be made. The following BPEL extracts illustrate how these scopes might be defined with compensation being provided to facilitate undoing some element of the booking process if one element fails. For example, the following scope defines a sequence for booking a hotel room and a compensation handler that can be invoked if required:

<scope name="BookHotel">

    <!-- define a compensation handler -->

    <compensationHandler>

      <!-- call cancel ticked -->

        <invoke name="Invoke_CancelBooking" 

                partnerLink="HotelBookingService"

                portType="hotel:hotelBooking"

                operation="cancelRoom"/>

    </compensationHandler>

    <sequence name="Sequence_1">

        <invoke name="Invoke_BookRoom" 

                partnerLink="HotelBookingService"

                portType="hotel:hotelBooking"

                operation="reserveRoom"/>

    </sequence>

  </scope>

The compensation handler in the above cancels a hotel room that has previously been booked by the service called by this step in the BPEL script.

The following scope defines what happens when we try to book seats on a flight to go along with the hotel room bookings. In this case, a sequence is defined to book the seats, but associated with it is a fault handler that is invoked when no seats are available for the selected dates.

  <scope name="BookFLight">

    <faultHandlers>

      <catch faultName="flight:NoSeatsAvailfault"

        <throw name="cancelBooking" 

               faultName="client:cancelBooking"/>

      </catch>

    </faultHandlers>

    <sequence name="Sequence_2"

      <invoke name="Invoke_BookFLight" 

              partnerLink="airline" 

              portType="ReservationSystem" 

              operation="bookSeats"/>

    </sequence>

  </scope>

In the above code, a catch block is defined to catch the specific fault and throws itself a cancelBooking fault to the parent scope. That will trigger the compensation we have defined earlier.

The last part is to define a catch block on the parent scope, that triggers in case of a cancelBooking fault and fires the compensation defined on the BookHotel scope.

<faultHandlers>

    <!-- catch the rollback fault and call -->

    <catch faultName="client:cancelBooking">

      <compensate name="CompensateBoookings" 

                  scope="BookHotel"/>

    </catch>

  </faultHandlers>

Compensation - what does it really mean?

So, where does this leave us with Compensation - it is not exception handling and it is not fault handling. However, it is closely related to both concepts, as the above example illustrates. It is an explicit way of representing how we recover from a problem or failure situation; but it is not automated state rollback; nor is it error recovery.

It should also be noted that compensation is not ACID compliant. ACID (or Atomicity, Consistency, Isolation, Durability) is a set of properties that guarantee that a single logical operation is processed reliably to completion or not at all. The term itself is most often used in the contact of database systems. So what do I mean when I say Compensation is not ACID compliant? Well, I mean that compensation does not guarantee any of the core concepts of ACID. Indeed, you can do anything you want within a compensation handler and that "anything" might intentionally not undo the effect of running the associated service.

As an example, consider how you might compensate in a business process for an activity that cannot be easily undone. For example, in a telecommunications environment part of the business process might have been to send an engineer out to install some new hardware. Undoing this may not be cost effective or indeed useful. Thus, the newly installed device may be left where it is.

As another example, if a payment has been made to a third party as part of the business process, you cannot just undo that payment - rather some alternative course of action may be required, such as requesting a credit note or a refund etc.

Of course, compensation was never intended to be based around ACID concepts - as that is not what compensation is about - however, it means that compensation could be very dangerous from a software engineering point of view. Remember, compensation itself does not guarantee anything about the state of the system before or after the compensation activities have executed, it does not guarantee consistency of the resulting data etc.

As an example of the complexities facing a developer working with compensation, consider the how difficult it to test all possible failure modes and paths through the compensation handlers in a large complex system, in order to ensure the resulting overall system state is coherent? I suspect this could be a very difficult task. Taking this further, how difficult is it to actually implement the compensation correctly in the first place? The above example made it look conveniently simple, but in reality it could be much more complex.

My biggest worry is that compensation may provide a nice warm feeling to system designers: that they can use compensation to solve all their problems. Then, not enough thought might go into the actual compensation process, the testing of these processes and their interactions.

Summary

In this final column on BPEL, we've looked at two of the more controversial (in my opinion) areas of BPEL and attempted to consider what they can do and why they may or may not be the right answer to the problem they are trying to address. How they develop in future version of BPEL will, I think, reflect the industry's experience with using them. Currently, both compensation and BPELJ have ardent supporters and vociferous detractors – personally, I'm sceptical of both. ®

Online References

BPELJ White Paper: ftp://www6.software.ibm.com/software/developer/library/ws-bpelj.pdf.

IBM BPELJ: BPEL for Java technology: http://www.ibm.com/developerworks/library/specification/ws-bpelj/.

BEA BPEL and BPELJ Page: http://oreilly-test.bea.com/webservices/bpel/.