Some 'more, in-depth' information on Oracle BPEL PM, ESB and other SOA, day2day things

Monday, March 27, 2006

BPEL: the miracle of xsd:choice with pre-populated elements

Last week's thursday I was working with Marty, a fellow from our global support organisation, on a problem a customer in Canada has reported.

The problem was having an xsd:choice element within the payload, and BPEL PM 'pre-creating' all the possible elements, instead of just the one, that was filled with data. At first I thought a surrounding xsd:sequence was missing, but even with that, all elements where created .. Strange, at least kind of...

After playing with some ideas, here is the workaround that I have found.

Here is the schema that defines the choice, in this case pretty simple, just to show the problem


<schema attributeFormDefault="qualified"
elementFormDefault="qualified"
targetNamespace="http://xmlns.oracle.com/UsingChoices"
xmlns="http://www.w3.org/2001/XMLSchema">

<element name="UsingChoicesProcessResponse">
<complexType>
<sequence>
<element name="choiceTest" type="client:second"/>
</sequence>
</complexType>
</element>
<complexType name="second">
<choice>
<element name="name" type="string"/>
<element name="address" type="string"/>
<element name="telephone" type="string"/>
</choice>
</complexType>
</schema>


Usually someone tends to do a "normal" <assign> as shown below, to get the value into the element ..

<assign name="Assign_ToSeeWrongVariable">
<copy>
<from expression="string('testname')"/>
<to variable="outputVariable" part="payload"
query="/client:UsingChoicesProcessResponse/
client:choiceTest/client:name"/>
</copy>
</assign>

a look into the flow diagram shows the mysterious element creation we do..


<outputVariable>
<part name="payload">
<UsingChoicesProcessResponse>
<choiceTest>
<name>testname</name>
<address/>
<telephone/>
</choiceTest>
</UsingChoicesProcessResponse>
</part>
</outputVariable>


The big question is, why are we doing this? Pretty simple, because we want to make it as easy as possible for the developer to assign values, and no need of taking care about creation of xml elements. The drawback here is clear. Having an xsd:choice element, and we create all possible elements for you, and don't remove them after the developer assigned the target value. (a choice must only contain one element!)

What's the fix? - Overwriting this behaviour by using another <assign> rule, just before you assign a value into the chosen element. The following code piece demonstrates, what needs to be done. It's creating the target element by hand, and assigning it directly.

<assign name="Assign_WithWorkaround">
<copy>
<from expression="ora:parseEscapedXML('
<choiceTest xmlns="http://xmlns.oracle.com/UsingChoices">
<name xmlns="http://xmlns.oracle.com/UsingChoices"/>
</choiceTest>')"
/>
<to variable="outputVariable" part="payload"
query="/client:UsingChoicesProcessResponse/
client:choiceTest"/>
</copy>
<copy>
<from expression="string('testname')"/>
<to variable="outputVariable" part="payload"
query="/client:UsingChoicesProcessResponse/
client:choiceTest/client:name"/>
</copy>
</assign>


After applying appying this workaround, you should see the expected element in the flow diagram of your process instance

<outputVariable>
<part name="payload">
<UsingChoicesProcessResponse>
<choiceTest>
<name>testname</name>
</choiceTest>
</UsingChoicesProcessResponse>
</part>
</outputVariable>


Having questions? send your feedback on The miracle of precreated elements here

0 Comments:

Post a Comment

<< Home