Different standard bodies deal differently in respect to verifying compliance to their published specifications.
Sun’s JCP (Java Community Process version 2.1) is very stringent on implementors of its specifications. The specification lead must provide a technology compatibility kit (TCK). The TCK includes tests, tools, and documentation that a implementor must use to verify and prove conformance to the specification. These TCKs usually consist of huge test-beds, containing hundreds of test-cases. The implementor can only promote conformance to a specification after all test-cases have passed with a positive result.
In contrast, OASIS defines a Adoption Service program. Adoption services are a group of services whose aim is to drive adoption of OASIS standards (and OASIS committee drafts) by means of providing conformance, interoperability, or training/personal skill certification programs. Organizations can work together with OASIS to create a referral relationship, which is then used to advertise the certification programs that the organizations provide. Conformance certification programs usually consist of test assertion summary documents, and a testing process.
I did a quick search in the Web and I could not find any single OASIS referred adoption service program for BPEL, version 1.1 or otherwise.
What this means is that currently there is no way of asserting implementation conformance to the OASIS BPEL4WS 1.1 committee draft.
In another words, even if the implementors wanted to guarantee that their implementation is portable and fully compliant, there is no obvious way of doing so.
In spite of this, there are several vendors that do offer BPEL engine implementations. Wikipedia alone lists over 20 providers. How many of these are really full-fledged BPEL engines? Actually, how many of these even provide a minimum level of portability and QoS? It is very hard to tell.
Even worse, currently the onus of ascertaining conformance is on the client. And vendors are not facilitating it. Vendors do not provide a compatibility issue list, or even document the features that they support.
To confirm this, I wrote two scenarios that test significant but hidden BPEL features and executed these scenarios in a couple of commercial and open-source implementations. The BPEL processes for these scenarios are included for reference.
The first one has to do with isolated scopes. When a scope is marked as isolated (variableAccessSerialized), access to its variables must follow a serialization schedule, so that data consistency is preserved. To force the engine into yielding while running within a isolated scope, I used a receive activity and delayed the dispatch of its message.
The second scenario has to do with dead-path-elimination. Paths that will not (ever) be executed, e.g. the unselected case of a switch statement, must be considered as having a negative link status and this negative status must be propagated to all of its target links. Otherwise the flow may just block indefinitely, or until the transaction, if present, times-out.
None of the implementations I tried were able to cope with either of these scenarios. I was not particularly surprised about this. Granted, the BPEL 1.1 specification is not very clear in respect to these particular features, but they are very important nonetheless. So it seems there is a urgent need for a BPEL TCK!
- Isolated scope test-case:
- DPE test-case:
<process name=”isolatedscope” targetNamespace=”http://bea.com/bpeltck/isolatedscope”
xmlns=”http://schemas.xmlsoap.org/ws/2003/03/business-process/”
xmlns:bpws=”http://schemas.xmlsoap.org/ws/2003/03/business-process/”
xmlns:ns1=”http://www.w3.org/2001/XMLSchema”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:client=”http://bea.com/bpeltck/isolatedscope”>
<partnerLinks>
<partnerLink name=”client”
partnerLinkType=”client:plt” myRole=”Provider”/>
</partnerLinks>
<variables>
<variable name=”inputVariable” messageType=”client:RequestMessage”/>
<variable name=”outputVariable” messageType=”client:ResponseMessage”/>
<variable name=”totalVar” type=”ns1:string”/>
</variables>
<sequence>
<receive partnerLink=”client” portType=”client:pt” operation=”process” variable=”inputVariable” createInstance=”yes”/>
<assign >
<copy>
<from variable=”inputVariable” part=”payload” query=”/client:ProcessRequest/client:input”/>
<to variable=”totalVar”/>
</copy>
</assign>
<flow suppressJoinFailure=”yes”>
<links>
<link name=”AtoB”/>
</links>
<sequence >
<scope name=”debit” variableAccessSerializable=”yes”>
<target linkName=”AtoB”/>
<variables>
<variable name=”tempVar” type=”ns1:string”/>
</variables>
<sequence>
<assig >
<copy>
<from variable=”totalVar”/>
<to variable=”tempVar”/>
</copy>
</assign>
<assign>
<copy>
<from expression=”bpws:getVariableData ( ‘tempVar’ ) – 10″/>
<to variable=”totalVar”/>
</copy>
</assign>
</sequence>
</scope>
</sequence>
<sequence>
<scope name=”credit” variableAccessSerializable=”yes”>
<variables>
<variable name=”tempVar” type=”ns1:string”/>
</variables>
<sequence>
<assign>
<source linkName=”AtoB”/>
<copy>
<from variable=”totalVar”/>
<to variable=”tempVar”/>
</copy>
</assign>
<receive createInstance=”no” partnerLink=”client” portType=”client:pt” operation=”wake” variable=”inputVariable”/>
<assign>
<copy>
<from expression=”bpws:getVariableData ( ‘tempVar’ ) + 10″/>
<to variable=”totalVar”/>
</copy>
</assign>
</sequence>
</scope>
</sequence>
</flow>
<assign>
<copy>
<from variable=”totalVar”/>
<to variable=”outputVariable” part=”payload” query=”/client:ProcessResponse/client:result”/>
</copy>
</assign>
<reply name=”replyOutput” partnerLink=”client” portType=”client:pt” operation=”process” variable=”outputVariable”/>
</sequence>
</process>
<process name=”dpe” targetNamespace=”http://bea.com/bpeltck/dpe”
xmlns=”http://schemas.xmlsoap.org/ws/2003/03/business-process/”
xmlns:bpws=”http://schemas.xmlsoap.org/ws/2003/03/business-process/”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:client=”http://bea.com/bpeltck/dpe” >
<partnerLinks>
<partnerLink name=”client” partnerLinkType=”client:plt” myRole=”Provider” partnerRole=”Requester”/>
</partnerLinks>
<variables>
<variable name=”inputVariable” messageType=”client:RequestMessage”/>
<variable name=”outputVariable” messageType=”client:ResponseMessage”/>
</variables>
<sequence>
<receive partnerLink=”client” portType=”client:pt” operation=”initiate” variable=”inputVariable” createInstance=”yes”/>
<flow suppressJoinFailure=”yes”>
<links>
<link name=”AtoB”/>
</links>
<sequence>
<target linkName=”AtoB”/>
<assign>
<copy>
<from variable=”inputVariable” part=”payload” query=”/client:ProcessRequest/client:input”/>
<to variable=”outputVariable” part=”payload” query=”/client:ProcessResponse/client:result”/>
</copy>
</assign>
</sequence>
<sequence>
<switch>
<case condition=”bpws:getVariableData ( ‘inputVariable’, ‘payload’, ‘/client:ProcessRequest/client:input’ ) = ‘donotmatch'”>
<empty>
<source linkName=”AtoB”/>
</empty>
</case>
<otherwise> <!– selected case –>
<sequence >
<assign>
<copy>
<from expression=”‘otherwise'”/>
<to variable=”outputVariable” part=”payload” query=”/client:ProcessResponse/client:result”/>
</copy>
</assign>
</sequence>
</otherwise>
</switch>
</sequence>
</flow>
<invoke partnerLink=”client” portType=”client:cb” operation=”onCallback” inputVariable=”outputVariable”/>
</sequence>
</process>