| Oracle® BPEL Process Manager Developer's Guide 10g (10.1.3.1.0) Part Number B28981-03 |
|
|
View PDF |
You can embed sections of Java code into a BPEL process.
This chapter contains the following topics:
This chapter explains how you can embed sections of Java code into a BPEL process. This is particularly useful when there is already Java code that can perform the desired function, and you want to use the existing code rather than start over with BPEL.
You can incorporate Java code using any of the following methods:
If the Java application has a BPEL-compatible interface, you either use Web Services Inspection Language (WSIF) binding or wrap the Java code as a SOAP service to use it in a BPEL process.
WSIF binding is the most common way of using Java code in a BPEL process. This method enables a BPEL process to invoke an Enterprise Java Bean through native J2EE protocol (local or remote method invocation (RMI)). With WSIF binding, a section of the WSDL file defines the protocol for communicating between Java and XML. This approach maintains Java's transactionality and does not sacrifice performance. It is also quicker for you to add WSIF binding to an existing Java application rather than starting over in Oracle BPEL Process Manager. However, WSIF binding has the following drawbacks:
Less tool support than SOAP services
Less interoperability, because each application server needs a specific binding
Currently, you must write the binding manually.
Oracle BPEL Process Manager's Java binding implementation is based on the Apache WSIF package's Java binding. Java binding enables a BPEL process to invoke user-defined Java classes.
All data used internally in a BPEL process is of a W3C DOM element. Therefore, data marshalling must be performed between a BPEL process and the user-defined Java classes. Oracle BPEL Process Manager's Java binding implementation currently supports Java classes that use the following data types:
XML simple type
XML complex type using Oracle BPEL Process Manager facade data type
DOM element
Most XML simple types can be mapped to Java types, and vice versa. The data mapping can be defined in the WSDL file using the format extension. For example, a Java method is defined as follows:
public float getQuote (String symbol) throws Exception;
The format:typeMap definitions are defined as follows:
<binding name="JavaBinding" type="tns:StockquotePT"> <java:binding/> <format:typeMapping encoding="Java" style="Java"> <format:typeMap typeName="xsd:string" formatType="java.lang.String" /> <format:typeMap typeName="xsd:float" formatType="java.lang.float" /> </format:typeMapping> <operation name="getQuote"> <java:operation methodName="getQuote"/> <input/> <output/> </operation> </binding>
See Also:
SOA_Oracle_Home\samples\demos\IBMSamples\simple for a sample of using XML simple typesAn XML facade is an Oracle BPEL Process Manager technology that provides a Java bean-like interface on top of an XML DOM element. Given the XML schemas, facade classes can be generated using the Oracle BPEL Process Manager schemac tool. In the following example, the classes use XML facade classes in the method:
public CommentsType addComment(CommentsType payload, CommentType comment)
throws JavaBindingException;
The WSDL Java binding is defined as follows:
<binding name="JavaBinding" type="tns:HelperService">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="tns:commentType"
formatType="com.otn.services.CommentType" />
<format:typeMap typeName="tns:commentsType"
formatType="com.otn.services.CommentsType" />
</format:typeMapping>
<operation name="addComment">
<java:operation methodName="addComment"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
<operation name="testFault">
<java:operation methodName="testFault"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
</binding>
The Java types CommentType and CommentsType are XML facade classes.
See Also:
"schemac" for details about the schemac tool and XML facades
Oracle BPEL Process Manager internally uses an XML DOM element. If a Java binding class uses XML DOM elements, data marshalling is not needed. For example, in the following example, the addComment() method is defined:
public Element addComment(Element payload, Element comment)
throws JavaBindingException;
The Java binding of the WSDL file is defined as follows:
<binding name="JavaBinding2" type="tns:HelperService2">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
format:typeMap typeName="tns:commentType"
formatType="org.w3c.dom.Element"/>
<format:typeMap typeName="tns:commentsType"
formatType="org.w3c.dom.Element"/>
</format:typeMapping>
<operation name="addComment">
<java:operation methodName="addComment"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
<operation name="testFault">
<java:operation methodName="testFault"/>
<input/>
<output/>
<fault name="CommentException"/>
</operation>
</binding>
With the Java class using a DOM element type, Java binding can support any XML data type.
As a Web service, a Java binding can throw a fault. The fault can be defined in the WSDL file as a Web service.
<message name="CommentFaultMessage"> <part name="payload" type="tns:commentType"/> </message> <portType name="HelperService2"> <operation name="testFault"> <input message="tns:TestFaultRequestMessage"/> <output message="tns:TestFaultResponseMessage"/> <fault name="CommentException" message="tns:CommentFaultMessage" /> </operation> </portType> <binding name="JavaBinding2" type="tns:HelperService2"> ... <operation name="testFault"> <java:operation methodName="testFault"/> <input/> <output/> <fault name="CommentException"/> </operation> </binding>
To throw a Web service fault, the Java class must declare to throw a predefined fault type com.collaxa.cube.ws.wsif.providers.java.JavaBindingException or its subclass.
In the following example, the Java file has a function that throws this exception:
public CommentType testFault(CommentType payload)
throws JavaBindingException
{
System.out.println("testFault : " + payload);
if (payload != null) {
JavaBindingException ex = new JavaBindingException();
ex.setFaultName("CommentException");
ex.setPart("payload", payload);
System.out.println(" throwing exception " + ex);
throw ex; } else {
return payload;
}
}
In a different Java file, there is a similar function:
public Element testFault(Element payload)
throws JavaBindingException
{
System.out.println("testFault2: " + payload);
if (payload != null) {
JavaBindingException ex = new JavaBindingException();
ex.setFaultName("CommentException");
ex.setPart("payload", payload);
System.out.println(" throwing exception " + ex);
throw ex;
} else {
return payload;
}
}
If such an exception is thrown from the Java binding class, the BPEL WSIF layer converts it into a Web service exception that can be caught by the BPEL source as follows:
<variables>
......
<variable name="fault" messageType="services:CommentFaultMessage"/>
</variables>
......
<faultHandlers>
<catch faultName="services:CommentException" faultVariable="fault">
<assign>
<copy>
<from expression="string('CommentException')"/>
<to variable="output" part="payload"
query="/types:comments/types:item[1]/types:message"/>
</copy>
</assign>
</catch>
<catchAll>
<empty/>
</catchAll>
</faultHandlers>
See Also:
Chapter 8, "Fault Handling" for additional details about faults
SOA_Oracle_Home\bpel\samples\tutorials\702.Bindings for examples of WSIF bindings for EJB, HTTP, and Java. Bindings must be written to match the application server.
SOA_Oracle_Home\bpel\samples\demos\BankTransferDemo\BankTransferFlow
As an alternative to WSIF binding, you can wrap the Java code as a SOAP service. As with WSIF binding, 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.
However, a Java application wrapped as a SOAP service has the following drawbacks:
It loses performance, because interactions are constantly being mapped back and forth between the Java code and the SOAP wrapper.
It loses interoperability, 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).
Another way to use Java in a BPEL process is to embed the code directly into the BPEL process using the Java BPEL exec extension bpelx:exec. The benefits of this approach are speed and transactionality. However, you can incorporate only fairly small segments of code. If you want to incorporate larger segments of code, or if the project requires the Java code to have the same look and feel throughout all the BPEL processes being created, consider using WSIF binding or wrapping it as a SOAP service.
The BPEL tag bpelx:exec enables you to embed a snippet of Java code within a BPEL process. 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 following bpelx:exec tag to embed the invokeSessionBean Java bean:
<bpelx:exec name="invokeSessionBean" language="java" version="1.4">
<![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'"
+ ". Please make sure 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>
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. For example:
<bpelx:exec name= ...
<
See Also:
"Java Embedding Activity" for additional details about this activity, including adding JAR files to classpathsThis chapter demonstrates how you can embed sections of Java code into a BPEL process using one of the following techniques:
If the Java application has a BPEL-compatible interface, you can use WSIF binding or wrap the Java code in a SOAP service.
You can directly embed the Java code by including an inline code snippet using bpelx:exec. This snippet is executed within the transaction context of Oracle BPEL Server. This method allows you to propagate that transaction to your own session and entity beans. You can use a set of built-in methods to enable the bpelx:exec snippet to read and update variables, change instance meta data, and throw faults. To simplify DOM manipulation, use an XML facade.