14 Incorporating Java and Java EE Code in a BPEL Process

This chapter describes how to incorporate sections of Java code into BPEL process service components in SOA composite applications. It describes how to add custom classes and JAR files, use the Java embedding activity, embed service data objects (SDOs) with bpelx:exec, and implement a custom Connection Manager class with a BPEL process.

This chapter includes the following sections:

14.1 Introduction to Java and Java EE Code in BPEL Processes

This chapter explains how to incorporate sections of Java code into a BPEL process. This is particularly useful when there is Enterprise JavaBeans Java code that can perform the necessary function, and you want to use the existing code rather than start over with BPEL.

14.2 Incorporating Java and Java EE Code in BPEL Processes

There are several methods for incorporating Java and Java EE code in BPEL processes:

  • Wrap as a Simple Object Access Protocol (SOAP) service

  • Embed Java code snippets into a BPEL process with the bpelx:exec tag

  • Use an XML facade to simplify DOM manipulation

  • Use bpelx:exec built-in methods

  • Use Java code wrapped in a service interface

14.2.1 How to Wrap Java Code as a SOAP Service

You can wrap the Java code as a SOAP service. This method requires that the Java application have a BPEL-compatible interface. A Java application wrapped as a SOAP service appears as any other web service, which can be used by many different kinds of applications. There are also tools available for writing SOAP wrappers.

14.2.2 What You May Need to Know About Wrapping Java Code as a SOAP Service

A Java application wrapped as a SOAP service has the following drawbacks:

  • There may be reduced performance due to the nature of converting between Java and SOAP, and back and forth.

  • Since SOAP inherently has no support for transactions, this method loses atomic transactionality, that is, the ability to perform several operations in an all-or-none mode (such as debiting one bank account while crediting another, where either both transactions must be completed, or neither of them).

14.2.3 How to Embed Java Code Snippets into a BPEL Process with the bpelx:exec Tag

You can embed Java code snippets directly into the BPEL process using the Java BPEL exec extension bpelx:exec. The benefits of this approach are speed and transactionality. It is recommended that you incorporate only small segments of code. BPEL is about separation of business logic from implementation. If you remove a lot of Java code in your process, you lose that separation. Java embedding is recommended for short utility-like operations, rather than business code. Place the business logic elsewhere and call it from BPEL.

The server executes any snippet of Java code contained within a bpelx:exec activity, within its Java Transaction API (JTA) transaction context.The BPEL tag bpelx:exec converts Java exceptions into BPEL faults and then adds them into the BPEL process.The Java snippet can propagate its JTA transaction to session and entity beans that it calls.

For example, a SessionBeanSample.bpel file uses the bpelx:exec tag shown in Example 14-1 to embed the invokeSessionBean Java bean:

Example 14-1 bpelx:exec Extension

 <bpelx:exec name="invokeSessionBean" language="java" version="1.5">
    <![CDATA[
        try {
            Object homeObj = lookup("ejb/session/CreditRating");
            Class cls = Class.forName(
                "com.otn.samples.sessionbean.CreditRatingServiceHome");
            CreditRatingServiceHome ratingHome = (CreditRatingServiceHome)
                        PortableRemoteObject.narrow(homeObj,cls);
            if (ratingHome == null) {
                addAuditTrailEntry("Failed to lookup 'ejb.session.CreditRating'"
                                   + ". Ensure that the bean has been"
                                   + " successfully deployed");
                return;
            }
            CreditRatingService ratingService = ratingHome.create();
 
            // Retrieve ssn from scope
            Element ssn =
                (Element)getVariableData("input","payload","/ssn");
 
            int rating = ratingService.getRating( ssn.getNodeValue() );
            addAuditTrailEntry("Rating is: " + rating);
 
            setVariableData("output", "payload",
                "/tns:rating", new Integer(rating));
        } catch (NamingException ne) {
            addAuditTrailEntry(ne);
        } catch (ClassNotFoundException cnfe) {
            addAuditTrailEntry(cnfe);
        } catch (CreateException ce) {
            addAuditTrailEntry(ce);
        } catch (RemoteException re) {
            addAuditTrailEntry(re);
        }
    ]]>
    </bpelx:exec>

14.2.4 How to Embed Java Code Snippets in a BPEL 2.0 Process

The examples in this chapter focus primarily on how to embed Java code snippets with the bpelx:exec extension. For BPEL projects that support version 2.0 of the BPEL specification, the syntax is slightly different. The bpelx:exec extension and Java code are wrapped in an <extensionActivity> element. Example 14-2 provides details.

Example 14-2 bpelx:exec Extension in BPEL 2.0

<extensionActivity>
  <bpelx:exec language="java">
  <![CDATA[
    java code
  ]]>
  </bpelx:exec>
</extensionActivity>

When you drag a Java Embedding activity into a BPEL process in Oracle BPEL Designer, the <extensionActivity> element and bpelx:exec tag are automatically added.

Example 14-3 shows the import syntax for BPEL 2.0:

Example 14-3 Import Syntax in BPEL 2.0

<import location="class/package name"
 importType="http://schemas.oracle.com/bpel/extension/java"/>

Note:

The BPEL 2.0 import syntax differs from BPEL 1.1, which uses the following syntax:

<bpelx:exec import="class/package name"

Example 14-4 shows a BPEL file with two Java embedding activities for a project that supports BPEL version 2.0.

Example 14-4 Java Embedding Activities in a BPEL File for Version 2.0

<process name="Test" targetNamespace="http://samples.otn.com/bpel2.0/ch10.9"
     . . .
     . . .
 <import location="oracle.xml.parser.v2.XMLElement"
     importType="http://schemas.oracle.com/bpel/extension/java"/>
. . . 
 <sequence>   
 . . .
<extensionActivity>
     <bpelx:exec language="java">
         XMLElement elem = (XMLElement) getVariableData("output", "payload");
         elem.setTextContent("set by java exec");
     </bpelx:exec>
   </extensionActivity>

   <extensionActivity>
     <bpelx:exec language="java">
         <![CDATA[XMLElement elem = (XMLElement) getVariableData("output",
          "payload");
         String t = elem.getTextContent();
         elem.setTextContent(t + ", set by java exec 2");]]>
     </bpelx:exec>
   </extensionActivity>
  . . .
 </sequence>
</process>

For information on using this activity, see Section 14.4, "Using Java Embedding in a BPEL Process in Oracle JDeveloper."

14.2.5 How to Use an XML Facade to Simplify DOM Manipulation

You can use an XML facade to simplify DOM manipulation. Oracle BPEL Process Manager provides a lightweight Java Architecture for XML Binding (JAXB)-like Java object model on top of XML (called a facade). An XML facade provides a Java bean-like front end for an XML document or element that has a schema. Facade classes can provide easy manipulation of the XML document and element in Java programs.

You add the XML facade by using a createFacade method within the bpelx:exec statement in the .bpel file. Example 14-5 provides an example:

Example 14-5 Addition of XML facade

 <bpelx:exec name= ...
    <![CDATA
     ...
    Element element = ...
         (Element)getVariableData("input","payload","/loanApplication/"):
    //Create an XMLFacade for the Loan Application Document
    LoanApplication xmlLoanApp=
         LoanApplicationFactory.createFacade(element);
 ...

14.2.6 How to Use bpelx:exec Built-in Methods

Table 14-1 lists a set of bpelx:exec built-in methods that you can use to read and update scope variables, instance metadata, and audit trails.

Table 14-1 Built in Methods for bpelx:exec

Method Name Description

Object lookup( String name )

JNDI access

long getInstanceId( )

Unique ID associated with each instance

String setTitle( String title ) / String getTitle()

Title of this instance

String setStatus( String status ) / String getStatus()

Status of this instance

void setCompositeInstanceTitle(String title)

Set the composite instance title

void setIndex( int i, String value ) / String getIndex( int i )

Six indexes can be used for a search

void setCreator( String creator ) / String getCreator()

Who initiated this instance

void setCustomKey( String customKey ) / String getCustomKey()

Second primary key

void setMetadata( String metadata ) / String getMetadata ()

Metadata for generating lists

String getPreference( String key )

Access preference

void addAuditTrailEntry(String message, Object detail)

Add an entry to the audit trail

void addAuditTrailEntry(Throwable t)

Access file stored in the suitcase

Object getVariableData(String name) throws BPELFault

Access and update variables stored in the scope

Object getVariableData(String name, String partOrQuery) throws BPELFault

Access and update variables

Object getVariableData(String name, String part, String query)

Access and update variables

void setVariableData(String name, Object value)

Set variable data

void setVariableData(String name, String part, Object value)

Set variable data

void setVariableData(String name, String part, String query, Object value)

Set variable data


14.2.7 How to Use Java Code Wrapped in a Service Interface

Not all applications expose a service interface. You may have a scenario in which a business process must use custom Java code. For this scenario, you can:

  • Write custom Java code.

  • Create a service interface in which to embed the code.

  • Invoke the Java code as a web service over SOAP.

For example, assume you create a BPEL process service component in a SOA composite application that invokes a service interface through a SOAP reference binding component. For this example, the service interface used is an Oracle Application Development Framework (ADF) Business Component.

The high-level instructions for this scenario are as follows.

To use Java code wrapped in a service interface:

  1. Create an Oracle ADF Business Component service in Oracle JDeveloper.

    This action generates a WSDL file and XSD file for the service.

  2. Create a SOA application that includes a BPEL process service component. Ensure that the BPEL process service component is exposed as a composite service. This automatically connects the BPEL process to an inbound SOAP service binding component.

  3. Import the Oracle ADF Business Component service WSDL into the SOA composite application.

  4. Create a web service binding to the Oracle ADF Business Component service interface.

  5. Design a BPEL process in which you perform the following tasks:

    1. Create a partner link for the Oracle ADF Business Component service portType.

    2. Create an assign activity. For this example, this step copies data (for example, a static XML fragment) into a variable that is passed to the Oracle ADF Business Component service.

    3. Create an invoke activity and connect to the partner link you created in Step 5a.

  6. Connect (wire) the partner link reference to the composite reference binding component. This reference uses a web service binding to enable the Oracle ADF Business Component service to be remotely deployed.

  7. Deploy the SOA application.

  8. Invoke the SOA application from the Test Web Service page in Oracle Enterprise Manager Fusion Middleware Control.

For more information on creating Oracle ADF Business Components, see Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

For more information on invoking a SOA composite application, see Oracle Fusion Middleware Administrator's Guide for Oracle SOA Suite and Oracle Business Process Management Suite.

14.3 Adding Custom Classes and JAR Files

You can add custom classes and JAR files to a SOA composite application. A SOA extension library for adding extension classes and JARs to a SOA composite application is available in the $ORACLE_HOME/soa/modules/oracle.soa.ext_11.1.1 directory. For Oracle JDeveloper, custom classes and JARs are added to the application_name/project/sca-inf/lib directory.

14.3.1 How to Add Custom Classes and JAR Files

If the classes are used in bpelx:exec, you must also add the JARs with the BpelcClasspath property in the System MBean Browser of Oracle Enterprise Manager Fusion Middleware Control.

To add JARs to BpelcClasspath:

  1. From the SOA Infrastructure menu, select SOA Administration > BPEL Properties.

  2. At the bottom of the BPEL Service Engine Properties page, click More BPEL Configuration Properties.

  3. Click BpelcClasspath.

  4. In the Value field, specify the class path.

  5. Click Apply.

  6. Click Return.

In addition, ensure that the JARs are loaded by the SOA composite application.

To add custom classes:

  1. Copy the classes to the classes directory.

  2. Restart Oracle WebLogic Server.

To add custom JARs:

  1. Copy the JAR files to this directory or its subdirectory.

  2. Run ant.

  3. Restart Oracle WebLogic Server.

14.4 Using Java Embedding in a BPEL Process in Oracle JDeveloper

In Oracle JDeveloper, you can add the bpelx:exec activity and copy the code snippet into a dialog.

Note:

For custom classes, you must include any JAR files required for embedded Java code in the BpelcClasspath property in the System MBean Browser of Oracle Enterprise Manager Fusion Middleware Control. See Section 14.3.1, "How to Add Custom Classes and JAR Files" for instructions. The JAR files are then added to the class path of the BPEL loader. If multiple JAR files are included, they must be separated by a colon (:) on UNIX and a semicolon (;) on Windows.

14.4.1 How To Use Java Embedding in a BPEL Process in Oracle JDeveloper

To use Java embedding in a BPEL process in Oracle JDeveloper:

  1. From the Component Palette, expand Oracle Extensions.

  2. Drag the Java Embedding activity into the designer.

  3. Double-click the Java Embedding activity to display the Java Embedding dialog.

  4. In the Name field, enter a name.

  5. In the Code Snippet field, enter (or cut and paste) the Java code. Figure 14-1 provides details.

    Figure 14-1 bpel:exec Code Example

    Description of Figure 14-1 follows
    Description of "Figure 14-1 bpel:exec Code Example"

Note:

As an alternative to writing Java code in the Java Embedding activity, you can place your Java code in a JAR file, put it in the class path, and call your methods from within the Java Embedding activity.

14.4.2 What You May Need to Know About Using thread.sleep() in a Java Embedding Activity

If you create and deploy a BPEL process that uses thread.sleep() in a Java Embedding activity, the executing thread is blocked and the transaction associated with that thread is prevented from committing. This causes BPEL instances to appear only after the wait is over, which is the expected behavior.

Instead, use a wait activity, which releases the resource upon entering the activity and enables the ongoing transaction to commit and the BPEL instance data to hydrate into the data store.

14.5 Embedding Service Data Objects with bpelx:exec

You can embed SDO code in the .bpel file with the bpelx:exec tag. In the syntax provided in Example 14-6, mytest.apps.SDOHelper is a Java class that modifies SDOs.

Example 14-6 Embedding SDO Objects with the bpelx:exec tag

</bpelx:exec>
<bpelx:exec name="ModifyInternalSDO" version="1.5" language="java">
     <![CDATA[try{
     Object o = getVariableData("VarSDO");
     Object out = getVariableData("ExtSDO");
      System.out.println("BPEL:Modify VarSDO... " + o + " ExtSDO: " + out);
     mytest.apps.SDOHelper.print(o);
     mytest.apps.SDOHelper.print(out);
     mytest.apps.SDOHelper.modifySDO(o);
      System.out.println("BPEL:After Modify VarSDO... " + o + " ExtSDO: " + out);
     mytest.apps.SDOHelper.print(o);
     mytest.apps.SDOHelper.print(out);
  }catch(Exception e)
  {
  e.printStackTrace();
}]]>
   </bpelx:exec> 

Example 14-7 provides an example of the Java classes modifySDO(o) and print(o) that are embedded in the BPEL file.

Example 14-7 Java Classes

public static  void modifySDO(Object o){
       if(o instanceof commonj.sdo.DataObject)
       {
           ((DataObject)o).getChangeSummary().beginLogging();
          SDOType type = (SDOType)((DataObject)o).getType();
          HelperContext hCtx = type.getHelperContext();
           List<DataObject>  lines =
            (List<DataObject>)((DataObject)o).get("line");
           for (DataObject  line: lines) {
               line.set("eligibilityStatus", "Y");
           }
       } else {
           System.out.println("SDOHelper.modifySDO(): " + o + " is not a
           DataObject!");
       }
   }
. . .
. . .
   public static  void print(Object o)    {
       try{
         if(o instanceof commonj.sdo.DataObject)
        {
           DataObject sdo = (commonj.sdo.DataObject)o;
            SDOType type = (SDOType) sdo.getType();
            HelperContext hCtx = type.getHelperContext();
            System.out.println(hCtx.getXMLHelper().save(sdo, type.getURI(),
             type.getName()));
         } else {
             System.out.println("SDOHelper.print(): Not a sdo " + o);
         }
       }catch(Exception e)
       {
       e.printStackTrace();
       }          } 

14.6 Sharing a Custom Implementation of a Class with Oracle BPEL Process Manager

When you implement a custom Connection Manager class with the same name as a class used by Oracle BPEL Process Manager, you must ensure that the custom class does not override the class used by Oracle BPEL Process Manager.

For example, assume the following is occurring:

  • You are using embedded Java in a BPEL project.

  • The Connection Manager custom class is overriding the BPEL Connection Manager class.

  • A java.lang.NoClassDefFoundError is occurring at runtime.

14.6.1 How to Configure the BPEL Connection Manager Class to Take Precedence

To configure the BPEL Connection Manager class to take precedence:

  1. Start Oracle JDeveloper.

  2. Highlight the BPEL project.

  3. From the Edit main menu, select Properties.

  4. Select Libraries and Classpath.

  5. Click Add JAR/Directory.

  6. Navigate to the location of the custom JAR file and click Select.

    This adds the custom Connection Manager JAR file to the classpath.

  7. Click OK.

  8. Redeploy the BPEL project and retest.