Go to page:
Prev 1 2 3 4 5 6 7 8 9 10 11 12 13 Next
Integration with Java
Sometimes we need to integrate our BPEL processes with resources other than web services. In the Java world this could be EJBs (Enterprise Java Beans), JMS (Java Message Service), ERP systems accessible through JCA (Java Connector Architecture), JDBC databases, or even simple Java classes. Accessing these resources from BPEL processes natively is important because many existing systems use these technologies and we often cannot convert all existing resources to web services before using them in BPEL processes.
(continued)Oracle BPEL Process Manager provides native integration with Java. This extends the reach of BPEL and makes it suitable for EAI (Enterprise Application Integration). BPEL Process Manager offers two solutions to integrate Java resources:
- Java embedding: This allows us to embed Java code within a BPEL process.
- Web Services Invocation Framework (WSIF) with Java binding: This is covered in the next section.
Let's look at Java embedding. Oracle provides a custom BPEL activity called <exec>, defined in the http://schemas.oracle.com/bpel/extension namespace. This namespace is usually declared with the bpelx prefix, so we write the activity as <bpelx:exec>.
The <bpelx:exec> activity allows us to embed Java code within BPEL processes. The server will execute the embedded Java code within its JTA (Java Transaction API) transaction context. If the embedded Java code calls EJBs (session or entity beans), the transactional context will be automatically propagated. If an exception occurs during the execution of the embedded Java code, the exception will automatically be converted to a BPEL fault and thrown to the BPEL process.
The <bpelx:exec> activity supports three attributes (in addition to the BPEL standard attributes):
- import: Used to import Java packages.
- language: Denotes the used language. Currently the only supported language is Java, but support for other languages such as C# may be added.
- version: Denotes the version of the language. The supported version of Java is 1.4.
The <bpelx:exec> activity also provides built-in methods we can use in the embedded Java code. They allow us to access and update BPEL variables, get JNDI access, update the audit trail, and set priorities and other parameters. These built-in methods are explained in the following table:
| Method |
Description |
Object getVariableData(String name)
Object getVariableData(String name, String partOrQuery)
Object getVariableData(String name, String part, String query) |
Access BPEL variables |
void setVariableData(String name, Object value)
void setVariableData(String name, String part, Object value)
void setVariableData(String name, String part, String query, Object value) |
Update BPEL variables |
void addAuditTrailEntry(String message, Object detail)
void addAuditTrailEntry(Throwable t) |
Add an entry or an exception to the audit trail |
| Object lookup(String name) |
JNDI lookup |
| Locator getLocator() |
Access to BPEL Process Manager Locator service |
| long getInstanceId() |
Returns the process instance unique ID |
void setTitle(String title)
String getTitle() |
Set/get the title of the process instance |
void setStatus(String status)
String getStatus() |
Set/get the status of the process instance |
void setPriority(int priority)
int getPriority() |
Set/get the priority of the process instance |
void setCreator(String creator)
String getCreator() |
Set/get the creator of the process instance |
void setCustomKey(String customKey)
String getCustomKey() |
Get/set the custom key for the process instance |
void setMetadata(String metadata)
String getMetadata() |
Get/set the metadata of the process instance |
| File getContentFile(String rPath) |
Access to the files stored inthe BPEL suitcase (JAR) |
Invoking a Java Class
In the next example, we will invoke a Java class from our travel BPEL process. Suppose we want to call a Java class (instead of a web service) to determine the employee travel status. As we will see later, we can invoke an EJB, JMS, JCA, or any other Java resource in the same way as we will invoke the Java class.
First let us write a simplified version of the class, called EmployeeStatus. The class implementation is oversimplified and always returns the economy class:
package com.packtpub;
public class EmployeeStatus {
public String getTravelStatus (String firstName, String lastName) {
return "Economy";
}
}
Now let's modify the BPEL code. As mentioned, we will call this class instead of the Employeeweb service. To use the <bpelx:exec> activity, we first have to declare the namespace:
<process name="BusinessTravelProcess"
targetNamespace="http://packtpub.com/bpel/travel/"
xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:trv="http://packtpub.com/bpel/travel/"
xmlns:emp="http://packtpub.com/service/employee/"
xmlns:aln="http://packtpub.com/service/airline/"
xmlns:bpelx="http://schemas.oracle.com/bpel/extension" >
...
Then we make the necessary Java imports. We have to import the DOM Element and our class:
...
<bpelx:exec import="org.w3c.dom.Element"/>
<bpelx:exec import="com.packtpub.EmployeeStatus"/>
...
Note: We can also add the <bpelx:exec> activity using BPEL Designer.
Finally we replace the <invoke> of the Employee web service with the Java embedded code. In Java we first create a new EmployeeStatus object. Then we use the getVariableData() function to retrieve the first and the last name from the BPEL variable EmployeeTravelStatusRequest. We need the name to invoke our Java class. We then add an entry to the trail. Finally we set the EmployeeTravelStatusResponse BPEL variable using the setVariableData() function:
...
<!-- Invoke the EmployeeStatus Java class instead of web service -->
<bpelx:exec name="invokeJavaExec" language="java" version="1.4">
<![CDATA[
EmployeeStatus e = new EmployeeStatus();
String firstName = ((Element)getVariableData(
"EmployeeTravelStatusRequest", "employee",
"/employee/FirstName")).getNodeValue();
String lastName = ((Element)getVariableData(
"EmployeeTravelStatusRequest", "employee",
"/employee/LastName")).getNodeValue();
String empStatus = e.getTravelStatus(firstName, lastName);
addAuditTrailEntry("Employee status is: " + empStatus);
setVariableData("EmployeeTravelStatusResponse", "travelClass",
"/travelClass", empStatus);
]]>
</bpelx:exec>
We have seen that invoking Java resources from BPEL is rather straightforward. For this example to work, we have to pack the Java class file in the BPEL process suitcase JAR archive. We have to store it into the BPEL-INF/classes directory. We could invoke an EJB, JMS, JCA, or other Java resources in the same way.
XML Façades and Schema Compiler
Looking at the embedded Java code, we can see that most lines of code have been used to access the BPEL variables and map individual values to Java variables. With more complex variables this can become time consuming and error prone. Instead of hand coding the access to BPEL variables, we can use XML façades.
XML façades are a set of Java interfaces and classes through which we can access and modify BPEL (and other XML) variables using get/set methods. The concept is known as XML serialization and is also used in JAXB (Java API for XML Bindings). The idea behind XML façades is to generate Java classes from XML Schemas.
Let us demonstrate this with an example. The EmployeeTravelStatusRequest variable is defined by the EmployeeType complex XML type (located in the Employee.wsdl file):
<xs:schema elementFormDefault="qualified"
targetNamespace="http://packtpub.com/service/employee/">
<xs:complexType name="EmployeeType">
<xs:sequence>
<xs:element name="FirstName" type="xs:string" />
<xs:element name="LastName" type="xs:string" />
<xs:element name="Departement" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
An XML façade for this variable consists of an interface (IEmployeeType) and a class (EmployeeType) which provides the following methods:
- getFirstName() and setFirstName()
- getLastName() and setLastName()
- getDepartement() and setDepartement()
There is also a factory class (EmployeeTypeFactory) through which we can create the IEmplyeeType using the createFacade() method.
Oracle BPEL Process Manager provides a schema compiler utility called schemac. Using this we can generate XML façades. To generate the XML façade for Employee.wsdl we can use thefollowing command line:
> schemac -d ./BPEL-INF/classes Employee.wsdl
With the .d option we have defined the directory where the generated façade classes should be stored. To see the façade source code we can use the .trace option:

(Full Size Image)
Let us now implement the Java embedded code. First we have to import the XML façade:
...
<bpelx:exec import="org.w3c.dom.Element"/>
<bpelx:exec import="com.packtpub.EmployeeStatus"/>
<bpelx:exec import="com.packtpub.service.employee.*"/>
...
Then we can modify the code that accesses the BPEL variables. First we have to obtain the DOM element using the getVariableData() function. We then create the XML façade and use it to access the first and the last name. Because the façade can throw an exception we have to introduce a try/catch block:
...
<!-- Invoke the EmployeeStatus Java class instead of a web service -->
<bpelx:exec name="invokeJavaExec" language="java" version="1.4">
<![CDATA[
try {
EmployeeStatus e = new EmployeeStatus();
Element empRequest = (Element)getVariableData(
"EmployeeTravelStatusRequest",
"employee","/employee");
IEmployeeType emp = EmployeeTypeFactory.createFacade(empRequest);
String firstName = emp.getFirstName();
String lastName = emp.getLastName();
String empStatus = e.getTravelStatus(firstName, lastName);
addAuditTrailEntry("Employee status is: " + empStatus);
setVariableData("EmployeeTravelStatusResponse",
"travelClass", "/travelClass", empStatus);
}
catch(Exception e)
{
addAuditTrailEntry(e);
}
]]>
</bpelx:exec>
Go to page:
Prev 1 2 3 4 5 6 7 8 9 10 11 12 13 Next