Unlike in a synchronous web service invocation, both parties act as client and server during an asynchronous web service invocation. So when sending the request, the BPEL process acts as the client and the external service becomes the server for the particular conversation. Then when the external service sends the response, external service is the client and the BPEL process is the server for that particular conversation.
In contrast with a synchronous web service invocation, those two client-server conversations should be defined separately in an asynchronous web service invocation. Now we will analyze the difference between a synchronous and an asynchronous invocation.
If you consider the implementation of a synchronous process, then you will notice the following facts:
<invoke>
activity is used for the whole conversation. So it encapsulates the input and output parameters required for the synchronous communication. Refer to the sample invoke activity included in the next bullet point.<invoke>
construct, the input variables and output variables are used to store request and response from the external web service. Refer to the following sample invoke activity:<invoke name="InvokeCustomerInfo" partnerLink="CustomerInfoPL" operation="getCustomerSSN" portType="ns1:CustomerInfoPortType" inputVariable="customerInfoInput" outputVariable="customerInfoOutput" />
partnerRole
. This partnerRole
exposes the two-way operation of the external web service, which accepts the request and sends the response back to the BPEL process. Please refer to the following three code snippets:<partnerLinks> <partnerLink name="CustomerInfoPL" partnerLinkType="ns1:CustomerInfo" partnerRole="CustomerInfoPortTypeRole" /> </partnerLinks>
<plnk:partnerLinkType name="CustomerInfo"> <plnk:role name="CustomerInfoPortTypeRole" portType="tns:CustomerInfoPortType"/> </plnk:partnerLinkType>
<invoke>
activity is a request-response-based operation. Refer to the sample WSDL port type, which exposes the getCustomerSSN
operation. This operation is used in the invoke activity that is mentioned in the previous point:<portType name="CustomerInfoPortType"> <operation name="getCustomerSSN"> <input name="input" message="tns:getCustomerSSNRequest" /> <output name="output" message="tns:getCustomerSSNResponse" /> </operation> </portType>
However, if you compare the implementation of an asynchronous web service invocation with synchronous invocation, you'll realize the following facts:
<invoke>
is used to send the outgoing request to the external web service. And <receive>
is used to retrieve the incoming response from the external web service. Refer to the sample BPEL code snippet in the next point.<invoke>
construct, only the input variable is used and the output variable is not used as output is not handled by <invoke>
. The output is captured by <receive>
. So <receive>
defines a variable to handle the output variable:<invoke name="AsynchInvoke" partnerLink="AsynchPartnerLink" portType="ns3:Server" inputVariable="AsynchInvoke_initiate_InputVariable" operation="initiate" bpelx:invokeAsDetail="no"> ... </invoke> <receive name="AsynchronousReceive" createInstance="no" partnerLink="AsynchPartnerLink" portType="ns3:ServerCallback" variable= Receive1_onResult_InputVariable" operation="onResult"> ... </receive>
myRole
and partnerRole
. This partnerRole
role exposes the one-way operation of the external web service which accepts the request from the BPEL process. And myRole
exposes a one-way operation of the service exposed by BPEL service in order to accept the response from the external web service, as shown in the following code:<partnerLinks> <partnerLink name="AsynchPartnerLink" partnerLinkType="ns3:Server" myRole="ServerRequester" partnerRole= ServerProvider" /> </partnerLinks>
<plnk:partnerLinkType name="Server"> <plnk:role name="ServerProvider" portType="tns:Server" /> <plnk:role name="ServerRequester" portType="tns:ServerCallback" /> </plnk:partnerLinkType>
<invoke>
construct. This operation defines the schema of the request message for the external web service invocation. The service exposed by the BPEL process defines another one-way operation, which is invoked by the external service. This operation defines the schema of the response message for the external web service invocation, as shown in the following code:<portType name="Server"> <operation name="initiate"> <input message="tns:ServerRequestMessage" /> </operation> </portType> <portType name="ServerCallback"> <operation name="onResult"> <input message="tns:ServerResponseMessage" wsaw:Action="http://wso2.org/onResult" /> </operation> </portType>
The following are the pre-requisites to initiate an asynchronous web service invocation:
The following are the steps to implement an asynchronous web service invocation in a summary:
myRole
and partnerRole
.inputVariable
that is the outgoing request message from the BPEL process.In the previous section, we talked about basic building blocks required for an asynchronous web service invocation. We explained why and how a partner link should represent the two communication channels, which manage request and response separately. These two channels are named partnerRole
and myRole
in the BPEL world. The myRole
channel is used to represent the requester of the asynchronous communication. During an asynchronous web service invocation, the requester is the BPEL process. So in the WSDL representation of the BPEL process, myRole
is pointed to an operation exposed by the BPEL process to accept the response from the external web service. We name this operation a callback operation.
A callback operation is used to transfer the response message of an asynchronous web service invocation to the client end from the server end. Here, the client end is the BPEL process and the server end is the external web service. Let's see how to set up the callback to the BPEL process.
Setting up a callback happens via the <receive>
activity. You can configure a <receive>
activity in a way to accept messages from the external web service. The partnerLink
and operation
attributes of the receive activity should point to a one-way operation exposed by the BPEL process such that the external web service can send the callback (response) message back to the BPEL process, as shown in the following code:
<invoke name="AsynchInvoke" partnerLink="AsynchPartnerLink" portType="ns3:Server" inputVariable="AsynchInvoke_initiate_InputVariable" operation="initiate" bpelx:invokeAsDetail="no"> … </invoke> <receive name="AsynchronousReceive" createInstance="no" partnerLink="AsynchPartnerLink" portType="ns3:ServerCallback" variable="Receive1_onResult_InputVariable" operation="onResult"> … </receive>
When a message reaches the BPEL server from an asynchronous web service, the BPEL server is responsible to figure out the following details to correlate the <invoke>
activity which sends the request and the <receive>
activity that receives the response message. Once the relevant <receive>
activity is found, the BPEL server routes the particular response message to the correct <receive>
activity.
If the asynchronous web service is implemented using Oracle SOA Suite or according to the WS-Addressing specification, Oracle BPEL Server automatically correlates response messages from asynchronous web services. Hence, users do not need to worry about message correlation when they are modeling asynchronous interactions using Oracle SOA Suite. Next, we will discuss about correlation in detail.
In this section, we will discuss an advanced topic that is targeted on readers who are interested in underlying techniques on mapping asynchronous web service responses to the correct BPEL process instance.
In the preceding section, we raised the question of mapping an incoming message to the BPEL server to a particular web service invocation. In an asynchronous web service invocation, there is no relation between the outgoing request message and the incoming response message, but when a message is being received by the BPEL server, the BPEL server should be able to determine which process instance initiated the outgoing asynchronous request. The response message should be routed to that particular process instance.
Let's have a look at the following graph to get a clear idea on this routing task:
In the preceding figure, you'll realize that there are multiple processes (Process1, Process2, and Process3) and there are multiple instances created from Process1 (that is, Process1-Instance1, Process1-Instance2, and so on). Once an incoming message hits the BPEL server, it can determine the correct process definition by the request URL. Once the process definition is determined, the BPEL server should determine to which instance the message should be routed. This is determined by correlating a specific header element (such as a WS-Addressing header) or a body element (for example, a unique ID included in the message body) of the outgoing and incoming SOAP messages. During an asynchronous invocation, a unique ID is propagated with an outgoing request message and that unique ID is queried in and verified with the incoming response message.
Correlation set is the standard mechanism in WS-BPEL 2.0 that defines the message parts which contain unique IDs that are used to map asynchronous requests and responses. Oracle SOA Suite supports WS-Addressing-based correlation, which doesn't require to specify correlation sets by users. We modeled the asynchronous interactions of the book warehousing process using WS-Addressing. WS-Addressing specification uses a header element in the SOAP message. This WS-Addressing-based header includes a correlation ID (that is a unique ID) and an endpoint location (for example, the URL at which a BPEL process instance is listening for the response message). By processing the WS-Addressing header content, Oracle SOA Suite can automatically route the message to the correct process instance.
In the next sections, we explain how to use correlation sets which are the standard correlation mechanism in WS-BPEL 2.0 for readers who are interested in advanced details.
Setting up a correlation set is a three-step process:
The <correlationSet/>
construct is defined with a unique correlation set name. This name is referred by the <invoke>
and <receive>
constructs to map the outgoing request message with the incoming response message. This correlationSet
construct has a properties
attribute. This attribute's value can contain one or more WSDL message property names.
For example, consider the following code:
<correlationSets> <correlationSet name="AsynchronousServiceInvocationCorrelationSet" properties="ns4:correlationProperty" /> </correlationSets>
WSDL message properties are defined in the WSDLs and they act as mappings to WSDL message parts. We can define a WSDL message property as the intermediate party which maps a correlation set to the exact message parts of the request and response. The schema of the request and response is different and the values which are used to identify the correlation between request and response can be in different places of the message. The WSDL message property should be able to represent both message parts of the request and response messages. This is achieved by message aliases such as <vprop:property name="correlationProperty" type="xsd:string"/>
.
A message alias represents the exact element of the message which is expected to be used to hold the unique ID for a particular asynchronous web service invocation. It consists of a <query/>
element which can locate the elements or attributes of the message, such as:
<vprop:propertyAlias propertyName="cor:correlationProperty" element="ns1:ServerRequest" xmlns:ns1="urn:ode-apache- org:example:async:server"> <vprop:query>/ns1:id</vprop:query> </vprop:propertyAlias> <vprop:propertyAlias propertyName="cor:correlationProperty" element="ns1:ServerResponse" xmlns:ns1="urn:ode-apache- org:example:async:server"> <vprop:query>/ns1:id</vprop:query> </vprop:propertyAlias>
Now, let's see how to use the correlation defined in the previous section. For an asynchronous web service invocation, the correlation value is initiated when executing the <invoke>
activity. Then this correlation value is persisted and used when a message is received to the particular BPEL process for routing operations.
A correlation is used when the request message leaves the BPEL server and when the response message reaches the BPEL server. We'll explain these two phases in the next two subsections.
This is where the correlation is initiated for an asynchronous web service, as shown:
<invoke name="AsynchInvoke" partnerLink="AsynchPartnerLink" portType="ns3:Server" inputVariable="AsynchInvoke_initiate_InputVariable" operation="initiate"> <correlations> <correlation set="AsynchronousServiceInvocationCorrelationSet" initiate="yes" /> </correlations> </invoke>
So you have to set initiate="yes"
within the particular invoke activity.
This is where the previously initialized correlation is referred to realize whether the incoming message is relevant to the particular process instance, as shown in the following code:
<receive name="AsynchronousReceive" createInstance="no" partnerLink="AsynchPartnerLink" portType="ns3:ServerCallback" variable= Receive1_onResult_InputVariable" operation="onResult"> <correlations> <correlation set="AsynchronousServiceInvocationCorrelationSet" initiate="no" /> </correlations> </receive>
So here the only difference is you don't have to initiate the correlation.