Book excerpt: Using WSIF for integration

Extend BPEL with WSIF for enterprise application integration

In real-world scenarios, a BPEL (Business Process Execution Language) business process will often have to connect to an existing application or system. Of particular interest here is connectivity to J2EE artifacts, such as Java classes, Enterprise JavaBeans (EJBs), Java Message Service (JMS), enterprise resource planning systems accessible through Java Connector Architecture (JCA), Java Database Connectivity databases, or other Java resources.

It is possible to convert these resources to a Web service, but that approach has several disadvantages:

  • The performance overhead of invoking Web service operations is several orders of magnitude larger than that of invoking native Java classes, and an order of magnitude larger than that of invoking EJBs or other native Java resources.
  • Web services invocations lack the important capability to propagate contexts during transactions. In contrast, when using Java resources directly, transaction context can be propagated automatically if the Java resource provides such support (as EJB and JCA do, for example).

Hence, the better approach is to access these external resources natively. Native connectivity to Java resources is not a standard feature of BPEL, but Oracle BPEL Process Manager offers a solution for this purpose—Web Services Invocation Framework (WSIF)—that does not require modifications or extensions to BPEL code. This capability greatly extends the reach of BPEL and makes it suitable for enterprise application integration (EAI).

(Note: This article is an excerpt from the book, BPEL Cookbook: Best Practices for SOA-Based Integration and Composite Applications Development, Matjaz B. Juric et al. (Packt Publishing, July 2006; ISBN: 1904811337): http://www.packtpub.com/BPEL-SOA/book.)

Understanding WSIF

Consider a business process for buying books. This asynchronous process has three Web services: a book rating Web service, which returns the rating of a specific book ranging from 0 to 5 (best), and one Web service each for two identical book store services, which return the book price. The process selects the lower price and makes the book purchase. In this example, fault handlers are defined and the process is divided into scopes (Check 1_BuyBook\BuyBook.bpel).

Assume that to obtain a book rating you would prefer to use a Java class, EJB (session bean), a service from an enterprise information system that can be accessed through JCA, or a similar Java resource. To incorporate such resources (and possibly any other resources for which bindings exist) into BPEL processes using Oracle BPEL Process Manager, you need only modify the service binding (WSDL), not the BPEL process itself. Thus to replace the book rating Web service with a Java class, you only have to modify the WSDL of the Web service.

WSIF, an Apache technology originally developed by IBM alphaWorks as a part of its Web services toolkit, is the underlying technology that makes this approach possible. It extends the Web services model by allowing you to describe services in WSDL, even if it's not a Web service that communicates through SOAP. WSIF also allows you to map such a service to the actual implementation and protocol.

In other words, you can bind the abstract description of any partner Web service used in the BPEL process to a corresponding resource, which can communicate using one of the supported WSIF bindings. The WSIF used by Oracle BPEL Process Manager 10.1.2 supports Java classes, EJB, JCA, HTTP GET and POST, and sockets; you can also define custom WSIF bindings and use practically any resource from BPEL.

This approach makes BPEL very useful for EAI as well as B2B. Enterprise information systems usually consist of many different software pieces, such as legacy applications accessible though JCA, EJBs, Web services developed on different platforms, and so on. To integrate all these pieces, you have to deal with different protocols. For example, if software migrates to a different server or has been upgraded to use a new technology, you have to upgrade the integration code—unless you use WSIF.

WSIF offers other important benefits:

  • Invoking services through WSIF maintains the performance of native protocols. Thus, when invoking Java resources, native Java classes, EJBs, or any other resources, you do not have to pay the performance penalty of Web services.
  • WSIF enables automatic propagation of transactional contexts between invoked transaction-aware Java resources using Java Transaction API (JTA). That way, Java resources can participate in distributed transactions.

To learn how WSIF works, here you'll modify our BPEL process for buying books and invoke a Java class and then an EJB. Remember that with WSIF, you will only have to modify the WSDL of the service, not the BPEL code. Through the modifications in WSDL, you will bind the call to the Java resource instead of a Web service.

First, we'll focus on using a Java class instead of the book rating Web service. To replace the Web service, you need to have a Java class with exactly the same interface as the Web service; this will require development of a Java class based on the WSDL (Web Services Description Language) contract. The other possibility would be to adapt the WSDL to an existing Java class (or another resource, let's say EJB). The first approach is better, because it is a so-called contract-first approach. This way, the interface of the service is adapted to the needs of the BPEL process and not vice versa.

Java-to-XML Bindings

To invoke a Java resource from BPEL, you will need to use data from BPEL variables, which are sent as input parameters to Java resources, and to send data from Java back to BPEL. BPEL variables are XML, whereas Java variables are not; therefore, you need a mapping between XML and Java.

To handle XML data from Java you have several options:

  • Handle XML manually through the DOM (Document Object Model) API: This way, the input and output parameters of the corresponding Java methods are of type Element from the World Wide Web Consortium Document Model Object API for Java. Use DOM methods to manipulate XML directly.
  • Use automated Java-to-XML bindings: Java-to-XML binding enables automatic conversion of XML Schema types to Java types. To achieve this, interfaces and a set of Java classes are generated through which you manipulate the XML. This way, XML is hidden, and you can use it through interfaces (such as JavaBeans). Here you have two options:
    • Oracle BPEL Process Manager: Supports default Java-to-XML bindings through the use of XML façades.
    • Use of custom Java serializers: Oracle already provides custom serializers that support JAXB (Java API for XML Bindings), XML beans, and Axis beans. You can also write your own serializers.

Let's have a look at the XML façades first.

XML façades

XML façades are Oracle BPEL Process Manager's original Java-to-XML binding for WSIF and are an integral part of the product. XML façades are a set of Java interfaces and classes through which you can access and modify XML data stored in BPEL variables in a relatively easy way using get/set methods. In this manner, you are not required to manipulate XML directly. Furthermore, the XML is hidden behind the façade, and you can manipulate the data through regular Java interfaces, a concept known as XML serialization. The idea behind XML façades is to provide support for basic data types through mapping to built-in types and to generate Java classes from XML Schemas for complex types.

The automatic mapping for the basic data types between XML Schema and Java types is shown here:

XML Schema Type

Java Types

xs:string

  • java.lang.String

    • char

    • java.lang.Character

xs:int, xs:integer

  • int
  • java.lang.Integer
  • java.math.BigInteger

xs:long

  • long
  • java.lang.Long

xs:short

  • short
  • java.lang.Short

xs:float

  • float
  • java.lang.Float

xs:double

  • double
  • java.lang.Double
  • java.math.BigDecimal

xs:byte

  • byte
  • java.lang.Byte

xs:Boolean

  • boolean
  • java.lang.Boolean

dateTime

java.util.Calendar

date

java.util.Date

As you can see, most of the simple types can be mapped to either primitive or object types. This is useful as you can adapt the mapping to the actual types used in your Java code. In addition to simple types, you also need a way to map complex types, whether those defined in the <types> section of the WSDL or in the external XML Schema (XSD) files. For example, in your book rating Web service WSDL, you'll notice an operation that takes as input the BookRatingRequestMessage, which is of type BookDscType. The BookDscType complex XML type is used for the BookRatingRequestMessage and for the corresponding BookRatingRequest BPEL variable:

 <xs:schema elementFormDefault="qualified" 
            targetNamespace="http://oracle.com/service/bookrating/">

   <xs:complexType name="BookDscType">
     <xs:sequence>
       <xs:element name="Title" type="xs:string" /> 
       <xs:element name="ISSN" type="xs:string" /> 
       <xs:element name="Publisher" type="xs:string" /> 
       <xs:element name="Authors" type="xs:string" /> 
     </xs:sequence>
   </xs:complexType>

</xs:schema>

The XML façade for this complex XML type provides an interface and a class through which you can access the elements (title, ISSN, publisher, authors) using Java getter methods. The XML façade also allows you to modify the element data using setter methods.

An XML façade for this variable consists of an interface (IBookDscType), and a class (BookDscType) that provides the following methods:

  • getTitle() and setTitle()
  • getISSN() and setISSN()
  • getPublisher() and setPublisher()
  • getAuthors() and setAuthors()

There is also a factory class (BookDscTypeFactory) through which you can create the IBookDscType using the createFacade() method. XML façade makes the code simpler and easier to maintain; this is particularly true for larger variables with many member fields.

Oracle BPEL Process Manager provides a schema compiler utility called schemac. Using this utility you can generate XML façades. To generate the XML façade for BookRating.wsdl, use the following command line:

Z:\WSIF\2_JavaBindingClass>schemac BookRating.wsdl
----------------------------------------------------
Oracle XML Schema Processor Version 10.1.2.0.0
http://otn.oracle.com/bpel
Copyright (c) 2002-2004 - Oracle
(type schemac -help for help)
----------------------------------------------------

schemac> parsing schema file 'BookRating.wsdl' ...
schemac> Loaded schemas from wsdl located at BookRating.wsdl
schemac> generating XML business document ...
schemac> compiling XML business documents ...
Schemac completed successfully.

Z:\WSIF\2_JavaBindingClass>

To use these classes from Java resources, you will need to compile them into the C:\OraBPELPM_1\ integration\orabpel\system\classes directory where the BPEL server can access them.

The schemac utility has several options. You can use the -d switch to define the directory where the generated façade classes should be stored. To see the façade source code, use the -trace option. The schemac utility can also be used to generate XML Schemas out of Java classes. This is useful if you would like to adapt the service interface to an existing Java resource. You have to use the -R switch and provide the Java class name without the extension.

Developing the Java class

To replace the book rating Web service with a Java class without modifying BPEL, you need a Java class that has the same interface (contract) as the original book rating Web services. This means that the Java class has to provide the operations with the identical functionality, and that operations have to accept the same parameters and return the same result type—but the operation name needn't be identical.

Looking at the original WSDL, you'll see that the book rating Web service provides an operation called BookRating, which takes an input and an output message and is thus synchronous:

 <portType name="BookRatingPT">
  <operation name="BookRating">
    <input message="tns:BookRatingRequestMessage" /> 
    <output message="tns:BookRatingResponseMessage" /> 
  </operation>
</portType>

The signatures of both messages are as follows:

 <message name="BookRatingRequestMessage">
  <part name="book" type="tns:BookDscType" /> 
</message>

<message name="BookRatingResponseMessage">
  <part name="rating" type="xs:int" />
</message>

The input parameter to the operation is of type BookDscType. To map the BookDscType to Java, use the corresponding XML façade, which you generated earlier using the schemac tool. The return type of the operation is the BookRatingResponseMessage message, which is of type xs:int. xs:int type maps to java.lang.Integer. (It could also map to int or java.math.BigInteger, but you are using java.lang.Integer here.)

You are now ready to write the Java equivalent class for the book rating Web service. Call the new Java class BookRatingJava, which will have a single method called getBookRating. The method body will be oversimplified—you will print a notification to the server console and return the rating of 4. (In a real-world example, you could calculate the rating based on data in the database, for example.) The code is as follows (note how you can access the book title and ISSN using getTitle() and getISSN() methods respectively):

 package com.oracle.rating; 
import com.oracle.service.bookrating.*;

public class BookRatingJava {

 public Integer getBookRating (BookDscType book) {
  System.out.println("Book rating for "+book.getTitle()+" ("+book.getISSN()+"): 4.");
  return new Integer(4);
 }

}

The console output is added here to verify that the process really calls the Java class and not the Web service.

1 2 Page 1
Page 1 of 2