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>

Monday, August 4, 2008

Creating and using custom xpath functions in BPEL


The motivation..
Recently, while tinkering with the email activity, I stumbled upon a strange but interesting discovery. I had tried to use the ora:fileread xpath function to read a text file (and subsequently send the same as an attachment) and I found that the function returned some strange text. After some more playing around, it dawned on me that the function had actually returned the Base64 encoded equivalent of the original text. So, in order to recover the original text I had to decode the encoded text. Since BPEL does not provide an out of box function to do the same, my first impulse was to write some java snippet and subsequently wrap it as web service. Then I got a better idea - using a custom xpath function that would do the decoding for me. Obviously, this was a better design inasmuch as I would no longer need to use an additional partnerlink in my BPEL process. In fact, this is the subject that I am going to cover in this post.

For ease of writing, I shall use the same code I wrote to decode Base64 encoded text. This is intended to serve as an example. Readers can improvise on it to develop their own functions.

The business logic
The first step is to write the code to decode the message, which is relatively simple.

Here is the snippet
...
private String decodeString(String str)
{
String decoded = null;
try
{
decoded = Base64Decoder.decode(str);
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
return decoded;
}
...

Wrapping the code
In order that this snippet be available as XPath function we need to first implement the IXPathFunction interface. This has a single method that it requires us to implement:

public Object call(IXPathContext iXPathContext, List list) throws XPathFunctionException

Here is the implementation of the above method

private static final int NO_OF_ARGS = 1;
public Object call(IXPathContext context,List args) throws XPathFunctionException {
// test if we have the right argument number

if (args.size() != NO_OF_ARGS)
{
throw new XPathFunctionException("This function requires one argument.");
}
// extract the String of the argument from the BPEL process

Object o = args.get(0);
String str = getValue(o);
// call the business method

return decodeString(str);
}

To get the value of the object, we shall use the getValue method. The implementation of the same is shown below.

private String getValue(Object o) throws XPathFunctionException {
if (o instanceof String)
{
return ((String)o);
}
else if (o instanceof Node)
{
return ((Node)o).getNodeValue();
}
else
{
throw new XPathFunctionException("Unknown argument type.");
}
}

Adding the class to the Server
Now that we are done with the coding, we need to compile it and drop the class into $ORACLE_HOME/bpel/system/classes directory of the BPEL PM server, so that the application server has access to this class.

Registering the xpath funtion with the server
The BPEL PM needs to be aware of this new function so that you can use it. So you need to register it with the server. This is done by adding a new entry in the xpath-functions.xml file located under the $BPEL_HOME/domains/default/config directory.

Namespace prefix for this function<?xml version = '1.0' encoding = 'UTF-8'?>
<bpel-xpath-functions version="2.0.2">
<function id="decode">
<classname>callbpelfromjava.CustomXpathExtension</classname>
<comment><![CDATA[decode the string]]></comment>
<property id="namespace-uri">
<value>http://nebulasky.blogspot.com</value>
<comment>Namespace URI for this function</comment>
</property>
<property id="namespace-prefix"><value>nebulasky</value>
<comment>Namespace prefix for this function</comment>
</property>
</function>
</bpel-xpath-functions>
Setting the BPEL classpath
Edit the shared library of your application server. Navigate to $ORACLE_HOME/j2ee/oc4j_soa/config. Open the server.xml file and locate the shared library called oracle.bpel.common. Add a tag code-source with your classpath as the others code-source tags.
...
<shared-library name="oracle.bpel.common" version="10.1.3">
...
<code-source path="/u01/apps/orasoa/product/10.1.3/bpel/system/classes"/>
...
</shared-library>
...
Now, open the domain.xml and scroll down to property id = "bpelcClasspath". Ensure that the classpath is already present. If not, add it. Once these tasks are done, bounce the server.
...
<property id="bpelcClasspath">
<name>BPEL process compiler classpath</name>
<value>/u01/apps/orasoa/product/10.1.3/bpel/system/classes:/u01/apps/orasoa/product/10.1.3/bpel/lib/j2ee_1.3.01.jar:/u01/apps/orasoa/product/10.1.3/bpel/lib/xmlparserv2.jar
</value>
</property>
...

Testing the Process
Create a BPEL process in JDeveloper. Under the process tag of the bpel file add the namespace that qualifies the function. This is the same as the values of the namespace-uri/namespace-prefix you had specified in the xpath-functions.xml. Here, the namespace is http://nebulasky.blogspot.com and the prefix is nebulasky (see xpath-functions.xml).
Here is how it will look like
xmlns:nebulasky="http://nebulasky.blogspot.com"

Create a copy operation as follows.
...
<copy>
<from expression="nebulasky:decode(bpws:getVariableData('encoded'))"/>
<to variable="outputVariable" part="payload" query="/client:CustomXpathProcessResponse/client:result"/>
</copy>
...
Deploy the project and initiate it. Ideally, your BPEL process should be able to decode the encoded text back to ASCII text.

Monday, July 28, 2008

To the next step....

Not often does one experience something as enigmatic - a moment when time comes to a standstill, when the mind and soul break free and transcend into the vast expanse of eternal bliss; a time when words lose their meaning, a time when you want to say so much and yet words fail you. Today is such an occasion for us (Anil, Lalit, Chatty, Patidar, Neeraj and me). We have been waiting for this day since a time that seems so distant like the start of our lives.

Two years back, on the same day, we embarked on a journey – one that would decide our career, and the course that our lives would eventually take afterwards. We joined the L&T family. With an organization that is undoubtedly at the pinnacle of India’s manufacturing industry, we thought God could not have been more benevolent to us. And we were right. In retrospect, we have reasons to believe that two years of our lives were indeed well spent.

It has been a terrific journey so far – one with so many interesting twists and turns. There were moments of glory as there were instances of regret. But the important thing is we enjoyed every bit of it. The myriad birthday parties with our proprietary “cake-painting” on the birthday boy’s face, the incredibly funny stories we cooked up to cover Lalit’s recurring absences, Patidar’s on-the-spot one-liners that would dumbstruck everyone to the hilt, and our endless discussions about one novel person named “NM” – life was an ice-cream of many flavors. Everything was not rosy though, and one thing that always played spoilt-sport was one lousy “Pipeline” - one that contained all the projects in the world (strangely the pipeline was one of a kind and only L&T had access to it). We used to stare into it with expectant eyes hoping something to come out of it, and more often than not, it disappointed. Thus there was a perennial drought in the river which is more often referred to in corporate terms as “Projects”. Nevertheless, we never cared. Lalit, who is undoubtedly the Einstein in JAVA, got busy creating something that would allow us to access sites which our proxy server would never allow (of course, it was an initiative that he took to get round the problem of not being able to view Vidya Balan’s and Katrina Kaif’s wallpapers - sorry Lalit, I have let your secret out). Chatty on the other hand, hardly gave a damn - he made the telephone his best friend, and whenever he got bored with it he had the gymnasium to fall back to. And Anil, well, he made it a point to ask the office boy for a new notebook - every single day. He scribbled and scribbled untill the notebooks were teeming with motley technical jargons. The days wore on and turned into months and months into years but his collection of notebooks never stopped growing. I was the one entrusted with the most daunting task among all – deal with the one called “NM”.

Like I said, we had our share of joys and sorrows and we have embraced them with dignity, élan and poise. Another milestone, and perhaps the most important one, is that the 2 year bond that we signed prior to joining the organization stands invalid today. This in itself is a culmination of our long cherished desire to be free, to be able to exercise our own will, to know that we matter and more importantly the legitimization of our right to choose what is best for us. The journey will continue, and so will we. May be, we will part ways, each taking a different route. But whatever we do, wherever we go, there will always be something which will symbolize our connection and togetherness - the fact that we all started from the same point.

Time to raise a toast, fellas…



From left: Chatty, Anil, Lalit and me....


Dil Chahta Hai, Kabhi Na Beete Chamkeele Din
Dil Chahta Hai, Hum Na Rahein Kabhi Yaaron Ke Bin
Din Din Bhar Ho Pyaari Baatein
Jhoome Shaame, Gaaye Raatein
Masti Mein Rahe Dooba Dooba Hameshaa Samaa
Humko Raahon Mein Yoonhi Milti Rahein Khushiyaan

Dil Chahta Hai.........

Wednesday, July 23, 2008

AIA Foundation Pack

What is the buzz?
AIA(Application Integration Architecture) Foundation Pack is a set of prebuilt enterprise objects and services coupled with a robust integration management infrastructure intended to expedite the development of integration solutions. Further, by adopting salient and time-tested best practises and industry standards, your entire portfolio of IT services can be integrated within the perview of changes and new requirements therey lending flexibility and adaptability to your business.

Components of the AIA Foundation Pack
The pack comprises of the following:
  • Enterprise Business Objects
  • Enterprise Business Services
  • SOA Governance Tools
  • Reference Architecture

Enterprise Business Objects

A Business object is a data model representing any recognizable business entity like customer, purchase order etc. It containts all the meta data and definitions pertaining to an entity in the form of XSDs.

Enterprise Business Services

Enterprise business services are implementation of a certain business task that have been exposed as web services so that they can be readily consumed over the internet by consumers. Usually your integrated environment will have a pool of enterprise business services with BPEL orchestrating the interaction patteren among them

SOA Governance

To ensure an end to end management of your integration solution, the Foundation Pack comes with a set of tools.

  • Business Service Repository: This is a directory that lists all the services and objects avaialable in your IT ecosystem.
  • Composite Application Validation System: This tool enables you to test your business process independent of the partner process. By providing an environment that simulates the real business scenario, you can do an end to end testing of the services you create
  • Composite Application Error Management and Resolution: It provides an enhanced error management and resolution facility where errors are routed to the intended recepients so that corrective measures can be taken. The result is low downtime.

Reference Architecture

To enable and assist developers there are two guides available that provides a step by step approach to build your custom solutions using AIA.