JBoss.orgCommunity Documentation
Services can be developed by generating initial development artifacts, based on artifacts created in preceding phases (e.g. global model or service contracts/designs).
To ensure that the services continue to conform to the artifacts defined in the previous phases, the tools perform conformance checking between the service implementation and the existing architecture/design artifacts. This is not possible with all implementation languages - they must provide the means to extract the communication structure for comparison.
The following sections explain how the generation and conformance checking can be achieved for the WS-BPEL implementation language.
This tools include a capability to generate a service implementation, for a participant in a choreography, using WS-BPEL. A completed version of the PurchasingGoods example can be found in the samples directory (which can be imported into Eclipse).
However if you wish to generate the example from scratch, the follow the instructions in this section. More information about how to use this feature can be found in the User Guide.
When a choreography description has been created, it is possible to generate a BPEL Process (and associated
WSDL files and deployment descriptor) for each of the participants defined within the choreography.
To try this out, select the Savara->Generate->WS-BPEL menu item from the popup menu
associated with the PurchaseGoods.cdm
.
This will display a dialog listing the possible services that can be generated from this choreography, with a proposed Eclipse project name.
To test out this feature, uncheck the Buyer participant, leave the build system as Ant, select the messaging system appropriate for your target environment and press the 'Ok' button. This will create a single new project for the Store and CreditAgency participants.
Each project will contain a single bpel
folder containing the WS-BPEL process
definition for the participant, a list of relevant WSDL files and a deployment descriptor file
for use with RiftSaw. Howeve the WS-BPEL and WSDL files are standard, so can be deployed to any
WS-BPEL 2.0 compliant engine.
When generated, the deployment descriptor initially has the following content:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<deploy xmlns="http://www.apache.org/ode/schemas/dd/2007/03" xmlns:ns1="http://www.jboss.org/examples/creditAgency">
<process name="ns1:PurchaseGoodsProcess_CreditAgency">
<active>
true
</active>
<provide partnerLink="StoreToCreditAgency">
<service/>
</provide>
</process>
</deploy>
The only change necessary is to add some attributes to the service element:
<service name="ns1:CreditAgencyService" port="CreditAgencyInterfacePort"/>
The generated BPEL process for the CreditAgency participant is as follows:
<process xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:ca="http://www.jboss.org/examples/creditAgency"
xmlns:pur="http://www.jboss.org/examples/purchasing"
xmlns:sto="http://www.jboss.org/examples/store"
xmlns:tns="http://www.jboss.org/savara/examples"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns0="http://www.scribble.org/conversation"
ns0:conversationType="savara.samples.Common@CreditAgency"
name="PurchaseGoodsProcess_CreditAgency"
targetNamespace="http://www.jboss.org/examples/creditAgency"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable">
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="PurchaseGoodsProcess_CreditAgency.wsdl"
namespace="http://www.jboss.org/examples/creditAgency"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="PurchaseGoodsProcess_Store.wsdl"
namespace="http://www.jboss.org/examples/store"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="CreditAgencyPartnerLinkTypes.wsdl"
namespace="http://www.jboss.org/examples/creditAgency"/>
<partnerLinks>
<partnerLink myRole="CreditAgencyService" name="StoreToCreditAgency"
partnerLinkType="ca:StoreToCreditAgencyServiceLT"/>
</partnerLinks>
<variables>
<variable messageType="ca:CreditCheckRequest" name="creditCheckRequestVar"/>
<variable messageType="ca:CreditCheckOk" name="creditCheckOkVar"/>
<variable messageType="ca:CreditCheckInvalid" name="creditCheckInvalidVar"/>
</variables>
<sequence>
<receive createInstance="yes" operation="checkCredit"
partnerLink="StoreToCreditAgency" portType="ca:CreditAgencyInterface"
variable="creditCheckRequestVar"/>
<if>
<sequence>
<reply operation="checkCredit" partnerLink="StoreToCreditAgency"
portType="ca:CreditAgencyInterface" variable="creditCheckOkVar"/>
</sequence>
<else>
<sequence>
<reply faultName="ca:CreditCheckFailed" operation="checkCredit"
partnerLink="StoreToCreditAgency"
portType="ca:CreditAgencyInterface"
variable="creditCheckInvalidVar"/>
</sequence>
</else>
</if>
</sequence>
</process>
There are three changes required, the first being to add a condition following the if element:
<if>
<condition>
$creditCheckRequestVar.CreditCheckRequest/pur:amount <= 500
</condition>
....
The next two changes relate to taking the information provided in the request and constructing an appropriate normal and fault response. In this simple example we only echo back the information received in the request, however more complicated processing could be performed before returning either response.
The following XML code should be added before the normal response (i.e. just inside the sequence element following the condition:
<assign name="CopyPurchaseDetails">
<copy>
<from>$creditCheckRequestVar.CreditCheckRequest</from>
<to>$creditCheckOkVar.CreditCheckOk</to>
</copy>
</assign>
The following XML code should be added before the fault response (i.e. just inside the sequence element that is contained in the else element:
<assign name="CopyPurchaseDetails">
<copy>
<from>$creditCheckRequestVar.CreditCheckRequest</from>
<to>$creditCheckInvalidVar.CreditCheckInvalid</to>
</copy>
</assign>
When generated, the deployment descriptor initially has the following content:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<deploy xmlns="http://www.apache.org/ode/schemas/dd/2007/03" xmlns:ns1="http://www.jboss.org/examples/store">
<process name="ns1:PurchaseGoodsProcess_Store">
<active>
true
</active>
<provide partnerLink="BuyerToStore">
<service/>
</provide>
<invoke partnerLink="StoreToCreditAgency">
<service/>
</invoke>
</process>
</deploy>
The only changes necessary are, (1) to add a namespace prefix definition,
xmlns:ns2="http://www.jboss.org/examples/creditAgency"
and (2) to add some attributes to the service element:
<provide partnerLink="BuyerToStore">
<service name="ns1:StoreService" port="StoreInterfacePort"/>
</provide>
<invoke partnerLink="StoreToCreditAgency">
<service name="ns2:CreditAgencyService" port="CreditAgencyInterfacePort"/>
</invoke>
The generated BPEL process for the Store participant is as follows:
<process xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:ca="http://www.jboss.org/examples/creditAgency"
xmlns:pur="http://www.jboss.org/examples/purchasing"
xmlns:sto="http://www.jboss.org/examples/store"
xmlns:tns="http://www.jboss.org/savara/examples"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns0="http://www.scribble.org/conversation"
ns0:conversationType="savara.samples.Purchasing@Store"
name="PurchaseGoodsProcess_Store"
targetNamespace="http://www.jboss.org/examples/store"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable">
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="PurchaseGoodsProcess_Store.wsdl"
namespace="http://www.jboss.org/examples/store"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="PurchaseGoodsProcess_CreditAgency.wsdl"
namespace="http://www.jboss.org/examples/creditAgency"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="StorePartnerLinkTypes.wsdl"
namespace="http://www.jboss.org/examples/store"/>
<partnerLinks>
<partnerLink myRole="StoreService" name="BuyerToStore"
partnerLinkType="sto:BuyerToStoreServiceLT"/>
<partnerLink name="StoreToCreditAgency"
partnerLinkType="sto:StoreToCreditAgencyLT"
partnerRole="CreditAgencyRequester"/>
</partnerLinks>
<variables>
<variable messageType="sto:BuyRequest" name="buyRequestVar"/>
<variable messageType="ca:CreditCheckRequest" name="creditCheckRequestVar"/>
<variable messageType="ca:CreditCheckOk" name="creditCheckOkVar"/>
<variable messageType="sto:BuyConfirmed" name="buyConfirmedVar"/>
<variable messageType="sto:BuyFailed" name="buyFailedVar"/>
</variables>
<sequence>
<receive createInstance="yes" operation="buy" partnerLink="BuyerToStore"
portType="sto:StoreInterface" variable="buyRequestVar"/>
<scope>
<faultHandlers>
<catch faultMessageType="ca:CreditCheckInvalid"
faultName="ca:CreditCheckFailed" faultVariable="creditCheckInvalidVar">
<sequence>
<reply faultName="sto:BuyFailed" operation="buy"
partnerLink="BuyerToStore" portType="sto:StoreInterface"
variable="buyFailedVar"/>
</sequence>
</catch>
</faultHandlers>
<sequence>
<invoke inputVariable="creditCheckRequestVar" operation="checkCredit"
outputVariable="creditCheckOkVar" partnerLink="StoreToCreditAgency"
portType="ca:CreditAgencyInterface"/>
<reply operation="buy" partnerLink="BuyerToStore" portType="sto:StoreInterface"
variable="buyConfirmedVar"/>
</sequence>
</scope>
</sequence>
</process>
There are three changes required. The first being to add an assignment statement within the catch element's sequence prior to the reply:
<assign name="CopyPurchaseDetails">
<copy>
<from>$creditCheckInvalidVar.CreditCheckInvalid</from>
<to>$buyFailedVar.BuyFailed</to>
</copy>
</assign>
The remaining two changes relate to taking the information received in the initial request, to construct a request to the credit agency, and then extracting the information from the credit agency response, to return it to the Store client. The following snippet shows the two assignment statements either side of the invoke statement:
<assign name="CopyPurchaseDetails">
<copy>
<from>$buyRequestVar.BuyRequest</from>
<to>$creditCheckRequestVar.CreditCheckRequest</to>
</copy>
</assign>
<invoke inputVariable="creditCheckRequestVar" operation="checkCredit"
outputVariable="creditCheckOkVar" partnerLink="StoreToCreditAgency"
portType="ca:CreditAgencyInterface"/>
<assign name="CopyPurchaseDetails">
<copy>
<from>$creditCheckOkVar.CreditCheckOk</from>
<to>$buyConfirmedVar.BuyConfirmed</to>
</copy>
</assign>
This section has provided a brief introduction to the design-time SOA governance features provided within the SAVARA Eclipse Tools distribution.
The aim of these capabilities are to enable verification of an implementation, initially defined just using BPEL process definitions, against a choreography, which in turn has been verified against business requirements defined using scenarios. Therefore this helps to ensure that the implemented system meets the original business requirements.
Being able to statically check that the implementation should send or receive messages in the correct order is important, as it will reduce the amount of testing required to ensure the service behaves correctly. However it does not enable the internal implementation details to be verified, which may result in invalid decisions being made at runtime, resulting in unexpected paths being taken. Therefore, to ensure this situation does not occur, we also need runtime governance, which is discussed in a later section (Runtime Validation).