This section describes the coding needed for implementing a simple J2EE client which makes use of the Web service API delivered with the WebSphere® Business Process Choreographer. The sample is structured in two parts, a Basic sample and an Advanced sample.
In the Basic sample, the focus is on setting up the infrastructure, getting the Web Services Description Language file (WSDL file) and setting up security, as this interface is designed as a secured Web service interface. The actual Web service call in the Basic sample is then a very simple query without parameters: a query for all active process templates on the server.
In the Advanced sample, the focus is on the Java code needed to perform some more advanced Web service calls, like assembling a nested business object, constructing an input message, starting a process, accessing the input message and the output message of a process, and querying the execution state of a particular process. As prerequisite for running the advanced sample, the application containing the BPEL process advertiseProcess must be deployed on the server.
The following five source files are shipped with the sample:
- Basic sample: index.html
This HTML file is the entry page of the small Web application. It contains only plain HTML code.
The file contains one HTML form with one push button; this push button issues an HTTP GET request to the invoke.jsp file, which then performs one Web service call.
In addition, this file contains a shortcut to the start page of the Advanced sample.
- Basic sample: setEndpoint.jsp
This JSP file contains the code to display, test, and manipulate the service endpoint that is used by the Java Web Service proxy.
Because the session bean representing the proxy is shared between all JSP pages of this project, any change of the service endpoint will as well
affect the service endpoint used by other JSP during the same browser session.
- Basic sample: invoke.jsp
This JSP file contains one single call to the Web service API, as well as the necessary object definitions for passing parameters to the call and for processing the response. This code is explained in more detail in the following sections.
In addition, the invoke.jsp file contains some code to render the response data as an HTML table, containing dynamic strings.
Those pieces are usual JSP coding techniques that are not explained in more detail here.
- Advanced sample: startprocess.html
This HTML file is the start page of the Advanced sample. It allows the user to enter input data that will be used as input for a long-running BPEL process. This file contains only plain HTML code and consists of one HTML form with four text input fields. The submit button of the form passes the actual content of these input fields as a parameterized HTTP GET request to the startprocess.jsp file, which will perform the
appropriate Web service calls for starting the process.
- Advanced sample: startprocess.jsp
This JSP file contains the code to assemble an input message object and to fill this object with the supplied parameter values. Using this input message object, a request to start a long running process is submitted to the Web service API. This is an asynchronous call, which by definition does not immediately return the result of the business process. It does, however, immediately return a handle to this business process, the so-called Process Instance ID (PIID). This PIID can be used later to query the process status and to access the result of the business process once it has been completed. Therefore, after a successful process start, the rendering code of this JSP displays a parameterized link to viewprocess.jsp, which can be used in the next step to view status and result of the business process.
In addition to the Web service calls, the startprocess.jsp file contains some code to convert HTTP parameter values into Java String values (in the beginning) and
some dynamic HTML code for rendering the response displayed to the user.
These pieces are usual JSP coding techniques that are not explained in more detail here.
- Advanced sample: viewprocess.jsp
This JSP file contains the code to query certain attributes of a particular process instance with a given PIID. Using the Web service API, it is demonstrated how to access the input data, query the execution state, and evaluate the output once the process instance has finished. In one particular case, namely when the execution state of the process instance is found to be STATE_RUNNING, this JSP file will add HTML code which will cause an automatic refresh to be performed after a few seconds; this mechanism will periodically poll the process execution state as long as the process is found in running state.
In addition, the viewprocess.jsp contains some code to read the PIID parameter into a Java String variable (in the beginning) and
some conditional HTML, depending on Java variable values. These pieces are usual JSP coding techniques that are not explained in more detail here.
In the following, we will take a look at the most interesting code pieces inside the JSP files.
setEndpoint.jsp
Allow to use the generated Java proxy in the browser session, shared between all JSPs:
<jsp:useBean id="MyBFMAccess" class="com.ibm.www.BFMIFProxy" scope="session"></jsp:useBean>
If the Update button of the HTML form was used, then the content of the text field myEndpoint is
passed in the HTTP request; this is then set in the proxy and stored in the local variable endPoint
and rendered later in this JSP.
Otherwise, the default service endpoint of the proxy is stored in the local variable; this
default is derived from the WebSphere Process Server wsdl that was used to generate the proxy:
String endPoint;
if (null != request.getParameter("myEndpoint")) {
endPoint = request.getParameter("myEndpoint");
MyBFMAccess.setEndpoint(endPoint);
} else {
endPoint = MyBFMAccess.getEndpoint();
}
The remainder of the setEndpoint.jsp file contains the code to render the service endpoint URL, a hyperlink to test the service endpoint URL, and a
HTML form to submit a new value for the service endpoint URL. This submit is done by using a push button with label Update that calls this JSP again.
invoke.jsp
Allow to use the generated Java proxy in the browser session, shared between all JSPs:
<jsp:useBean id="MyBFMAccess" class="com.ibm.www.BFMIFProxy" scope="session"></jsp:useBean>
Create an empty parameter object for the queryProcessTemplates
operation, then use the Java proxy to launch the query operation:
com.ibm.www.QueryProcessTemplates parameters = new com.ibm.www.QueryProcessTemplates();
com.ibm.www.QueryProcessTemplatesResponse bfmResponse = MyBFMAccess.queryProcessTemplates(parameters);
The response data are in the bfmResponse object now. Use the getter method to extract the list of process templates into an appropriate array:
com.ibm.www.ProcessTemplateType[] templates = bfmResponse.getProcessTemplate();
The remainder of the invoke.jsp file contains the code to iterate over the array and render the template data as HTML table.
startprocess.jsp
Allow to use shorthands instead of the fully qualified class names (for example, SOAPElement
instead of javax.xml.soap.SOAPElement
) in the remainder of the JSP file:
import="javax.xml.soap.SOAPFactory"
import="javax.xml.soap.SOAPElement"
import="javax.xml.soap.SOAPException"
Allow to use the generated Java proxy in the browser session, shared between all JSPs:
<jsp:useBean id="MyBFMAccess" class="com.ibm.www.BFMIFProxy" scope="session"></jsp:useBean>
Get access to the mechanism for creating SOAP elements:
SOAPFactory mySoapFactoryInstance = SOAPFactory.newInstance();
Create a new SOAP message with no elements inside yet. This will become our input message later on:
// define elements and link them together as defined in objects BO_Customer and BO_Address
mySoapMessage = mySoapFactoryInstance.createElement(myOperation, myNamespacePrefix, myInterfaceURI);
Now create the business object that will be part of the input message.
The details have to be in sync with the business object definition of the business process template. First, the business object itself is created.
In the next step, the attributes ("firstName", "lastName",...) are created, and subsequently the values (myFName, myLName,...), which were extracted from the HTTP request, are attached to them using the addTextNode()
method.
Finally, the attributes are linked to the business object using
the addChildElement()
method. Note that the indentation used here does reflect the nesting of the elements rather than the nesting of the Java programming logic:
// define the BO_Customer object
SOAPElement myInputElement = mySoapFactoryInstance.createElement("customer");
SOAPElement myInputElement1 = mySoapFactoryInstance.createElement("firstName");
myInputElement1.addTextNode(myFName);
myInputElement.addChildElement(myInputElement1);
SOAPElement myInputElement2 = mySoapFactoryInstance.createElement("lastName");
myInputElement2.addTextNode(myLName);
myInputElement.addChildElement(myInputElement2);
...
The third attribute of the "customer" business object is a business object itself, it has the name "address".
This child business object is created the same way as the parent business object and then linked to the parent:
// define the BO_Customer object
SOAPElement myInputElement3 = mySoapFactoryInstance.createElement("address");
SOAPElement myAddressElement1 = mySoapFactoryInstance.createElement("street");
myAddressElement1.addTextNode(mySName);
myInputElement3.addChildElement(myAddressElement1);
SOAPElement myAddressElement2 = mySoapFactoryInstance.createElement("city");
myAddressElement2.addTextNode(myCName);
myInputElement3.addChildElement(myAddressElement2);
myInputElement.addChildElement(myInputElement3);
Now attach the business object to the SOAP message created earlier:
mySoapMessage.addChildElement(myInputElement);
Create the set of parameters needed for calling the sendMessage
operation, which is used for starting a long-running BPEL process. The parameters are process template, porttype, operation, and the input message:
// prepare parameters for starting the process
com.ibm.www.SendMessage myCallParameters = new com.ibm.www.SendMessage();
myCallParameters.set_any(mySoapMessage);
myCallParameters.setProcessTemplateName(myProcessTemplateName);
myCallParameters.setOperation(myOperation);
javax.xml.namespace.QName myPortTypeQName = new javax.xml.namespace.QName(myInterfaceURI, myPortTypeName);
myCallParameters.setPortType(myPortTypeQName);
Create an object for storing the result of the sendMessage
operation, then call the sendMessage
operation with the help of the Java proxy:
com.ibm.www.SendMessageResponse mySendMessageResponse = null;
try {
mySendMessageResponse = MyBFMAccess.sendMessage(myCallParameters);
} catch (Exception e) {
...
}
Extract the Process Instance ID (PIID) from the response that was returned by the sendMessage
operation.
This PIID can be used as handle to the process instance details later:
String myPIID = mySendMessageResponse.getPIID();
The remainder of the startprocess.jsp file contains the code to render the parameterized URL for calling the viewprocess.jsp page and some basic exception handling.
viewprocess.jsp
Allow to use shorthands instead of the fully qualified class names (for example, SOAPElement
instead
of javax.xml.soap.SOAPElement
) in the remainder of the JSP file. Here, we do not create new SOAP elements, so
we do not need the shorthand for the SOAPFactory.
import="javax.xml.soap.SOAPElement"
import="javax.xml.soap.SOAPException"
Allow to use the generated Java proxy in the browser session, shared between all JSPs:
<jsp:useBean id="MyBFMAccess" class="com.ibm.www.BFMIFProxy" scope="session"></jsp:useBean>
Note: In this JSP file, we want to add the refresh directive to the HTTP header conditionally, thus the relevant Java code has to be
merged into the HTTP header rather into the HTTP body.
Create the objects for the request and for the response of the getProcessInstance
operation:
// get the process instance
com.ibm.www.GetProcessInstance myGetProcessInstanceParms = new com.ibm.www.GetProcessInstance();
com.ibm.www.GetProcessInstanceResponse myGetProcessInstanceResponse = null;
Provide the PIID which was extracted from the HTTP request, then launch the getProcessInstance
operation:
myGetProcessInstanceParms.setPiid(myPIID);
myGetProcessInstanceResponse = MyBFMAccess.getProcessInstance(myGetProcessInstanceParms);
Note: When starting a long running process with the BPC Explorer, the user is allowed to specify an arbitrary process instance name (the only constraint is that it has to be unique). For the getProcessInstance
operation, that unique name is accepted as valid PIID value. However, in other operations that take a PIID as input (for example, getInputMessageForProcessInstance
) the internal PIID is required.
That is why the PIID is queried again from the system and stored in the variable myInternalPIID
and used in other operations that rely on a PIID:
com.ibm.www.ProcessInstanceType
myProcessInstance = myGetProcessInstanceResponse.getProcessInstance();
// get internal PIID which is required for retrieving the messages
myInternalPIID = myProcessInstance.getPiid();
...
myGetInputMessageForPIParms.setPiid(myInternalPIID);
After running the operation getInputMessageForProcessInstance
, extract the content from the response:
SOAPElement myInputMessage = myGetInputMessageForPIResponse.get_any();
Look for an element with XML tag "firstName"; to allow checking for null pointers, store the result of the item(0) method in a variable.
If all checks for null pointers are passed successfully, concatenate the actual value to the Java variable which will be used for rendering later:
org.w3c.dom.Node tmpNode;
tmpNode = myInputMessage.getElementsByTagName("firstName").item(0);
if (tmpNode!=null && tmpNode.getFirstChild()!=null)
myInput = tmpNode.getFirstChild().getNodeValue();
Extract the ExecutionState from the process instance object into a Java String. In case the process is still running, set a boolean variable which conditionally includes an auto-refresh directive to the HTML header:
// get the execution state
myExecutionState = myProcessInstance.getExecutionState();
if (myExecutionState.equals("STATE_RUNNING")) {
// still in running state,
// try again in a moment
doRefresh = true;
} else ...
...
<% if (doRefresh) { %>
<META http-equiv="refresh" content="4">
<% } // end if %>
When the value "STATE_FINISHED" is found as ExecutionState, the output message is extracted
in the same way as the input message has been extracted earlier. In addition to the value, the
name of the output variable is retrieved by the getNodeName()
method.
This way, the viewprocess.jsp can be used for monitoring arbitrary long-running process instances and display
the first element of the output message.
Keep in mind though that for running process instances frequent polling will happen, which may add some extra load to your system.
The remainder of the viewprocess.jsp file contains the code to render the process instance data as an HTML table.