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:
Section 14.1, "Introduction to Java and Java EE Code in BPEL Processes"
Section 14.2, "Incorporating Java and Java EE Code in BPEL Processes"
Section 14.4, "Using Java Embedding in a BPEL Process in Oracle JDeveloper"
Section 14.5, "Embedding Service Data Objects with bpelx:exec"
Section 14.6, "Sharing a Custom Implementation of a Class with Oracle BPEL Process Manager"
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.
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
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.
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).
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>
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."
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:
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 |
---|---|
|
JNDI access |
|
Unique ID associated with each instance |
|
Title of this instance |
|
Status of this instance |
|
Set the composite instance title |
|
Six indexes can be used for a search |
|
Who initiated this instance |
|
Second primary key |
|
Metadata for generating lists |
|
Access preference |
|
Add an entry to the audit trail |
|
Access file stored in the suitcase |
|
Access and update variables stored in the scope |
|
Access and update variables |
|
Access and update variables |
|
Set variable data |
|
Set variable data |
|
Set variable data |
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:
Create an Oracle ADF Business Component service in Oracle JDeveloper.
This action generates a WSDL file and XSD file for the service.
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.
Import the Oracle ADF Business Component service WSDL into the SOA composite application.
Create a web service binding to the Oracle ADF Business Component service interface.
Design a BPEL process in which you perform the following tasks:
Create a partner link for the Oracle ADF Business Component service portType
.
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.
Create an invoke activity and connect to the partner link you created in Step 5a.
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.
Deploy the SOA application.
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.
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.
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:
From the SOA Infrastructure menu, select SOA Administration > BPEL Properties.
At the bottom of the BPEL Service Engine Properties page, click More BPEL Configuration Properties.
Click BpelcClasspath.
In the Value field, specify the class path.
Click Apply.
Click Return.
In addition, ensure that the JARs are loaded by the SOA composite application.
Copy the classes to the classes
directory.
Restart Oracle WebLogic Server.
Copy the JAR files to this directory or its subdirectory.
Run ant
.
Restart Oracle WebLogic Server.
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.
To use Java embedding in a BPEL process in Oracle JDeveloper:
From the Component Palette, expand Oracle Extensions.
Drag the Java Embedding activity into the designer.
Double-click the Java Embedding activity to display the Java Embedding dialog.
In the Name field, enter a name.
In the Code Snippet field, enter (or cut and paste) the Java code. Figure 14-1 provides details.
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.
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.
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.
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(); } }
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.
To configure the BPEL Connection Manager class to take precedence:
Start Oracle JDeveloper.
Highlight the BPEL project.
From the Edit main menu, select Properties.
Select Libraries and Classpath.
Click Add JAR/Directory.
Navigate to the location of the custom JAR file and click Select.
This adds the custom Connection Manager JAR file to the classpath.
Click OK.
Redeploy the BPEL project and retest.