Tuesday, August 5, 2008

Accessing BPEL variables from within XSLT

What's new?
XSLT is a remarkable technology, and I almost always prefer using it over other alternatives, most notably JAVA(of course there are times when nothing else will work and JAVA enticingly fits the bill). However, very often one is tempted to write JAVA snippets, and expose them as webservices to accomplish a task, when the same could be achived using XSLT with minimal or no coding.

Most of us are aware that BPEL PM provides an out of box function ora:processXSLT to execute an XSL template. The signature of the function is pretty well known.

ora:processXSLT('template','input','properties'?)
template : The XSL File Name
input : The variable to be transformed

Very often we use only the first two parameters without giving much of a thought about the third. This post is intended unravel the mystery sorrounding this parameter.

The third parameter
Interestingly, the third parameter comes in handy when you need access to BPEL variables from within an XSL file. Withing the XSLT engine this parameter translates to XSL parameters that can be accessed within the XSL Map using the construct
<xsl:param name="<paramName>"/>

All that remains is retrieving data from this parameter within XSLT. This is relatively straight forward and is done as follows
<Name><xsl:value-of select="$param1"/></Name>

More about "properties"
For the "properties" argument to be available to the XSLT engine, it must be of type "message" that conforms to the following schema.
...
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.oracle.com/service/bpel/common" targetNamespace="http://schemas.oracle.com/service/bpel/common" elementFormDefault="qualified">
<xsd:element name="parameters">
<xsd:annotation>
<xsd:documentation> A sample element </xsd:documentation> </xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="item" maxOccurs="unbounded"> <xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="value" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
...

Create and initialize the variable
Your first step is to import this schema into the project wsdl file. Once this is done your wsdl file should look like this
...
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.oracle.com/service/bpel/common" schemaLocation="Props.xsd" />
</schema>
</types>
...

Add the namespace under the definitions tag of the wsdl file like this

xmlns:ns1="http://schemas.oracle.com/service/bpel/common"

Now, go ahead and create the appropriate message types. For the sake of convinience, I have modelled my request message on top of this schema(since my intention is just to drive home the concept; readers are welcome to improvise) so that I don't need to create another variable and populate it with the contents of input variable again within the BPEL process. Instead, I shall directly use the input variable as the third argument. If you are using JDeveloper, there isn't any need to do all these manually. All you need to do is specify this schema for the input/request message when defining the process at the beginning. The designer automatically generates these fragments for you without you even knowing it. Anyways, here is my message type
...
<message name="ReadConfig1RequestMessage">
<part name="payload" element="ns1:parameters" />
</message>
...

NS:If you are not directly using the input variable, you must first create a variable that conforms to this message and populate the same with the contents of that bpel variable whose values you wish to make avaiable within the XSLT.

Anyways, here is how the third argument will look like after it has been initialized
...
<parameters xmlns:ns2="http://schemas.oracle.com/service/bpel/common" xmlns="http://schemas.oracle.com/service/bpel/common"/>
<ns2:item>
<ns2:name>Name</ns2:name>
<ns2:value>Sankash</ns2:value>
</ns2:item>
<ns2:item>
<ns2:name>Occupation</ns2:name>
<ns2:value>Software Engineer</ns2:value>
</ns2:item>
</parameters>
...

Call ora:processXSLT with the third argument
Unfortunately, the JDeveloper GUI does not support using this parameter. So, you have to do it after clicking the source tab in the designer. Just add this snippet within the tranformation
...
<copy>
<from expression="ora:processXSLT('Transformation_1.xsl',bpws:getVariableData('Invoke_1_SynchRead_OutputVariable','Configurations'),bpws:getVariableData('inputVariable','payload'))"/>
<to variable="outputVariable" part="payload"/>
</copy>
...

The XSLT snippet
Here is the xsl file. It will concat the values of the parameters which are essentially the contents of the BPEL variable (the input variable in this case). ...
<xsl:stylesheet version="1.0" ....>
<xsl:param name="Name"/>

<xsl:param name="Occupation"/>
<xsl:template match="/">
<ns1:ReadConfig1ResponseMessage>
<ns1:result>
<xsl:value-of select="concat('Name : ', $Name, ' Occupation : ',$Occupation)"/> </ns1:result>
</ns1:ReadConfig1ResponseMessage>
</xsl:template>
</xsl:stylesheet>
...

Testing the process
Save the project and deploy. Ideally the response message should containt the concatenated value of the parameters. In this case it shoudl look like this

<ns1:result>Name : Sankash Occupation : Software Engineer</ns1:result>

6 comments:

Lalit Jolania said...

This is a very creative way of making xsl mapper dynamic....

So that it can behave accordingly at runtime...

Anonymous said...

Amiable brief and this mail helped me alot in my college assignement. Thank you on your information.

Anonymous said...

Brim over I acquiesce in but I contemplate the brief should acquire more info then it has.

Anonymous said...

Amiable dispatch and this post helped me alot in my college assignement. Thank you as your information.

Anonymous said...

i without a doubt adore your writing choice, very remarkable,
don't give up as well as keep writing mainly because it just simply well worth to follow it.
looking forward to browse a whole lot more of your own stories, have a good day :)

Anonymous said...

Good point, though sometimes it's hard to arrive to definite conclusions