by Matjaž B. Jurič

Book excerpt: Using WSIF for integration

news
Dec 22, 200619 mins

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): https://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_BuyBookBuyBook.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:WSIF2_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:WSIF2_JavaBindingClass>

To use these classes from Java resources, you will need to compile them into the C:OraBPELPM_1 integrationorabpelsystemclasses 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.

Defining WSIF bindings in WSDL

To “persuade” the BPEL process to use the Java class instead of the Web service, you have to define the WSIF bindings to the Java class. This is done in the book rating WSDL, where you add the binding section.

Each WSIF binding consists of two parts. First, you have to define the actual binding, where you specify:

  • Type of binding used (Java class, EJB, JCA, and so on).
  • Mapping of types, where you specify the mapping of XML types to the destination types (for Java resources, these are Java types). You have to define the mapping for all complex types; simple types are mapped automatically based on the table presented earlier.
  • Mapping of operations, where you have to specify for each WSDL operation (defined under the <portType> tag) the corresponding operation in the destination resource (for example, the name of the method of a Java class).

Second, you have to specify the service you will be using. Here you specify the exact name of the resource. If it is a Java class, specify its full name (including the package name).

In a real-world scenario, you may have a resource, such as a Java class or an EJB, for which a WSDL will not exist. Then you have to go through the following steps:

  1. Define the Java-to-XML bindings, where you select how to map input parameters and return value to XML. You can use XML façades and simplify the work using the schemac tool with the -R switch, which will generate an XML Schema based on a Java class.
  2. Define the signature for each operation and the corresponding input and output messages.
  3. Add the WSIF binding.
  4. Add the <partnerLinkType> declaration in order to use the WSDL from the BPEL
  5. process.

Particularly in the first two steps you can use a tool or a wizard for automatic conversion of resources to Web services. Such tools are available for most environments. Of course, you do not actually convert the resource to a Web service, but can make use of the generated WSDL (with additional modifications).

WSIF binding for Java class

Let’s now define the WSIF binding for BookRatingJava class. Start by defining the two namespaces used by WSIF providers in the root element of the WSDL document, the <definitions> tag. The format namespace is used to define the type mappings and the java namespace to define the operation mappings and the full name of the Java class:

 <?xml version="1.0" encoding="utf-8" ?> 
<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
             xmlns:tns="http://oracle.com/service/bookrating/" 
             targetNamespace="http://oracle.com/service/bookrating/" 
             xmlns="http://schemas.xmlsoap.org/wsdl/"
             xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" 
             xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"
             xmlns:java="http://schemas.xmlsoap.org/wsdl/java/" >
...

Next, add the binding section. This section is usually located after port type declarations and before partner link types. Here you define a Java binding for the BookRatingPT port type:

  1. Define the type mapping from XML to Java. The input parameter XML type BookDscType is mapped to the com.oracle.service.bookrating.BookDscType Java class. Please note that you do not have to provide the mapping for output XML xs:int type, because it maps automatically to java.lang.Integer.
  2. Also define that the WSDL operation BookRating is mapped to the Java method getBookRating(). Please note that the name of the WSDL operation and the method name of the Java class do not need to be equal, but the types of input and return parameters do:
     ...
          <binding name="JavaBinding" type="tns:BookRatingPT">
        
            <java:binding/>
        
            <format:typeMapping encoding="Java" style="Java">
              <format:typeMap typeName="tns:BookDscType" 
                      formatType="com.oracle.service.bookrating.BookDscType" />
            </format:typeMapping>
        
            <operation name="BookRating">
              <java:operation methodName="getBookRating"/>
              <input/>
              <output/>
            </operation>     
        
          </binding>
        ...
    

Next, specify the service used. Define that the service is provided by the Java class. The book rating service will use the com.oracle.rating.BookRatingJava Java class:

 ...
  <service name="BookRating">

    <port name="JavaPort" binding="tns:JavaBinding">
      <java:address className="com.oracle.rating.BookRatingJava"/>
    </port>

  </service>

The rest of the book rating WSDL (including partner link types) has not changed.

Testing the example

You are almost ready to test the example and verify that the BPEL process will use the Java class instead of the original Web service. Remember, you have modified the WSDL only; you have not made any changes to the BPEL process code.

You will use the original BPEL code and the same partner link and invoke the BookRatingJava Java class with the usual <invoke> activity used for invoking the Web service. Recall the BPEL code for the invocation of the book rating service:

 <!-- Synchronously invoke the Book Rating Web Service -->
          <scope name="BookRatingInvoke">
          
            <faultHandlers>

              <catchAll>
                <!-- If book rating is not available assign 0 -->
                <assign>
                  <copy>
                    <from expression="number(0)"/>
                    <to variable="BookRatingResponse" part="rating"/>
                  </copy>
                </assign>          
              </catchAll>
              
            </faultHandlers>
            
            <invoke partnerLink="BookRating" 
                  portType="bkr:BookRatingPT" 
                  operation="BookRating"
                  inputVariable="BookRatingRequest" 
                  outputVariable="BookRatingResponse" />
          
          </scope>

Before we can test the example, we have to do a few “bookkeeping” activities. First, we have to ensure that the BPEL process will use the modified WSDL. To achieve this, modify the bpel.xml file and specify that the BookRating.wsdl file should be taken from the current directory and not from the Web service itself:

 <?xml version="1.0" encoding="UTF-8"?>
<BPELSuitcase>
  <BPELProcess src="BuyBook.bpel" id="BuyBookJavaBinding">
    <partnerLinkBindings>
      <partnerLinkBinding name="Client">
        <property name="wsdlLocation">
           BuyBook.wsdl
        </property>
      </partnerLinkBinding>
      <partnerLinkBinding name="BookRating">
        <property name="wsdlLocation">
            BookRating.wsdl
        </property>
      </partnerLinkBinding>
      <partnerLinkBinding name="BookStore1">
        <property name="wsdlLocation">
            http://localhost:9700/orabpel/default/BookStore1/BookStore1?wsdl
        </property>
      </partnerLinkBinding>
      <partnerLinkBinding name="BookStore2">
        <property name="wsdlLocation">
            http://localhost:9700/orabpel/default/BookStore2/BookStore2?wsdl
        </property>
      </partnerLinkBinding>
    </partnerLinkBindings>
  </BPELProcess>
</BPELSuitcase>

We then generate the XML façade using the schemac utility and compile the BookRatingJava class. You have to deploy the XML façade and the Java class to the C:OraBPELPM_1integrationbpelpmorabpelsystemclasses directory, where the BPEL server can locate and use them. The easiest way is to modify the build.xml, which should invoke the schemac compiler, the javac compiler, and the bpelc compiler:

 <?xml version="1.0"?>
<project name="BuyBookJavaBinding" default="all" basedir=".">
  <property name="deploy" value="default"/>
  <property name="rev" value="1.0"/>

    <target name="CompileJava">
      <schemac input="${basedir}/BookRating.wsdl"
               out="${home}/system/classes"/>
      <javac srcdir="${basedir}/src" destdir="${home}/system/classes"/>
    </target> 
       
    <target name="main">
      <bpelc home="${home}" rev="${rev}" deploy="${deploy}"/>        
    </target>    

    <target name="all" depends="CompileJava, main"/>

</project>

After starting the obant utility, you should get the following output:

 Z:WSIF2_JavaBindingClass>obant

Z:WSIF2_JavaBindingClass>SETLOCAL
Buildfile: build.xml

CompileJava:
  [schemac] schemac> parsing schema file 'Z:WSIF2_JavaBindingClass/BookRating.
wsdl' ...
  [schemac] schemac> Loaded schemas from wsdl located at Z:WSIF2_JavaBindingCl
ass/BookRating.wsdl
  [schemac] schemac> generating XML business document ...
  [schemac] schemac> compiling XML business documents ...
    [javac] Compiling 1 source file to C:OraBPELPM_1integrationorabpelsystemclasses

main:
    [bpelc] validating "Z:WSIF2_JavaBindingClassBuyBook.bpel" ...
    [bpelc] BPEL suitcase deployed to: C:OraBPELPM_1integrationorabpeldomain
sdefaultdeploy

all:

BUILD SUCCESSFUL
Total time: 17 seconds

Z:WSIF2_JavaBindingClass>ENDLOCAL

Z:WSIF2_JavaBindingClass>

Next, use the BPEL Console to start the process. In the visual flow window, you can observe the execution of the process. Note that the <invoke> activity has been used in BPEL and that the book rating is 4, in contrast to the original book rating Web services, which returned 5, as shown in the figure below.

To be absolutely sure that the BPEL Process Manager has invoked the Java class, the BPEL Process Manager console window will show the following output:

 05/10/19 19:35:36 Book rating for Business Process Execution Language 
(1-904811-18-3): 4.
Click on thumbnail to view full-sized image.
Matjaz B. Juric holds a Ph.D. in computer and information science and is an associate professor at the University of Maribor. In addition to BPEL Cookbook, he has coauthored Professional J2EE EAI, Professional EJB, J2EE Design Patterns Applied, and .Net Serialization Handbook, published by Wrox Press. He has published chapters in More Java Gems (Cambridge University Press) and in Technology Supporting Business Solutions (Nova Science Publishers). Juric has been involved in several large-scale object technology projects. In cooperation with IBM Java Technology Centre, he worked on performance analysis and optimization of RMI-IIOP, an integral part of the Java platform.