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.

5 comments:

Lalit Jolania said...

Its an easy way of adding reusable functionality for BPEL...

Nice POST

Abhishek Saurabh said...

Wow...A great idea.
This post will be helpful for everyone working on BPEL.

Thanks for sharing your thoughts.

Custom Paper Writing said...

Many institutions limit access to their online information. Making this information available will be an asset to all.

Anonymous said...

Good day

We do not agree with this year BRIT awards 2010 decision.

Please visit our little poll

http://micropoll.com/t/KDqOnZBCWt

Lady Gaga can not be better than Madonna

Poll supported by BRIT awards 2010 sponsor femmestyle
[url=http://www.femmestyle.li/brustvergroesserung/preis.html]brustvergrößerung preis[/url]

PRINCE HARRY WISHES HAPPY BIRTHDAY TO THE BRIT AWARDS
With a special birthday message from Prince Harry for the 30th Anniversary of the BRIT Awards

first time handjob stories said...

Promise me you wont go there anymore. The echo of Gingers heels marked her departure.
xxx incest stories
asian incest sex stories
free porn picsincest stories
stories lesbian
xxx sex stories post
Promise me you wont go there anymore. The echo of Gingers heels marked her departure.