How many times have you developed error handling logic in a BPEL process and want to collect error information to pass to an error handler service? There are many xpath functions that are currently available and can be utilized individually to collect all the necessary data, however this can become a time consuming task when you have several catch blocks and many processes. This is a case where re-use is a must. Simplifying the collection of the error data will ensure that the error handling is completed and performed in a consistent manner across processes.
Re-using the logic doesn’t imply copying the logic to another process, this leads to maintenance problems since we will inherently forget every place it was copied. You could create small utility BPEL processes that manage the logic but that can be a bit heavy weight and probably overkill.
Custom XPath functions come to the rescue and solve this problem by providing a framework to generate a custom java class that can perform the collection of all the error data and return a XML document in the structure of the specific error handler.
Now we know we want to create a custom XPath function to populate the following CommonErrorHandler.xsd, so here are the steps required.
<?xml version=”1.0″ encoding=”UTF-8″ ?> <xsd:schema xmlns:xsd=”http://www.w3.org/2001/XMLSchema” targetNamespace=”http://mycompany.com/Common/CommonErrorHandler” elementFormDefault=”qualified”> <xsd:element name=”CommonErrorHandler”> <xsd:complexType> <xsd:sequence> <xsd:element name=”interfaceName” type=”xsd:string”/> <xsd:element name=”instanceId” type=”xsd:string”/> <xsd:element name=”messageId” type=”xsd:string”/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
- Create a java project in JDeveloper called BlogXpathFunctions.
- Open up Project Properties the newly created project
- Default package name: mycompany
- Click on Libraries and Classpath
- Click on Add Library, add BPEL Runtime and SOA Runtime to the project
- Create a java class
- Name: Helpers
- Package name: mycompany.foundation.helpers
- Add the following methods to this class, these methods will help in creating the return document.
public static Element createElementWithValue(Document document, String nodeName, String namespaceURI, String value){ Element elem = document.createElementNS(namespaceURI, nodeName); Text text = document.createTextNode(value); elem.appendChild(text); return elem; } public static Document prepareDocument() throws ParserConfigurationException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); return builder.newDocument(); } catch (Exception e) { throw new ParserConfigurationException(e.getMessage()); } }
- Create a java class
- Name: BlogFunctions
- Package: mycompany.foundation.xpath
- Add below method to class. BPEL and XSLT require very specific signatures and implementation to work properly.
public static class PopulateErrorDataFunction implements IXPathFunction { public Object call(IXPathContext iXPathContext, List list) throws XPathFunctionException { try { return BlogFunctionsImpl.populateErrorData(iXPathContext); } catch (Exception e) { throw new XPathFunctionException(e.getMessage()); } } }
- Create a java class
- Name: BlogFunctionsImpl
- Package: mycompany.foundation.xpath
- Add below method to class. Make sure that the namespace in this class matches your xsd namespace.
public static final String sERROR_DATA_NAME_SPACE = “http://mycompany.com/Common/CommonErrorHandler”; public BlogFunctionsImpl() { super(); } public static Object populateErrorData(IXPathContext pIXPathContext) throws XPathFunctionException, ParserConfigurationException { Node rootNode = null; try { Map props = (Map)pIXPathContext.getVariableValue(null, null, “xpath-function-data”); ICubeContext cubeContext = (ICubeContext)props.get(“ICubeContext”); ICubeInstanceImpl cubeInstance = CubeContextHelper.getCubeInstance(cubeContext); Document document = Helpers.prepareDocument(); rootNode = document.createElementNS(sERROR_DATA_NAME_SPACE, “CommonErrorHandler”); rootNode.appendChild(Helpers.createElementWithValue(document, “interfaceName”, sERROR_DATA_NAME_SPACE, cubeInstance.getCompositeName())); rootNode.appendChild(Helpers.createElementWithValue(document, “instanceId”, sERROR_DATA_NAME_SPACE, cubeInstance.getCompositeInstanceId())); rootNode.appendChild(Helpers.createElementWithValue(document, “messageId”, sERROR_DATA_NAME_SPACE, cubeInstance.getECID())); } catch (Exception e) { e.printStackTrace(); throw new XPathFunctionException(e.getMessage()); } return rootNode; }
Need to create a descriptor file to let SOA know about the new XPath function that was created, so it can be utilized. It needs to be saved in a META-INF folder in the src directory. The file name is ext-soa-xpath-functions-config.xml. The contents must match below:
- Important to make sure the package name from the BlogFunctions class is added as shown.
- This is the name that will show up in the expression builders.
- This is the class name from the BlogFunctions class.
<?xml version=”1.0″ encoding=”UTF-8″?> <soa-xpath-functions xmlns=”http://xmlns.oracle.com/soa/config/xpath” xmlns:blog=”http://www.oracle.com/XSL/Transform/java/mycompany.foundation.xpath.BlogFunctions”> <function name=”blog:populateErrorData”> <className>mycompany.foundation.xpath.BlogFunctions$PopulateErrorDataFunction</className> <return type=”node-set”/> <desc>Returns a error handler object</desc> </function> </soa-xpath-functions>
- Deploy the project to a jar
- Click on Deploy
- Click on New Deployment Profile
- Click on Jar File
- Name the deployment profile the same as the project
- Add xpath functions to JDeveloper
- Click on Tools
- Click on Preferences
- Click on SOA
- Click on Add and search for the newly created jar file
- Recycle jdev to take effect
- Add xpath functions to Server
- Copy newly created jar file to $OracleHome/Oracle_SOA/soa/modules/oracle.soa.ext_11.1.1/classes
- Run build.xml from the oracle.soa.ext_11.1.1 directory, this will register your new class with the server
$OracleHome/modules/org.apache.ant_1.7.1/bin/ant –buildfile build.xml
- Recycle the server to take effect
You can now utilize your new custom xpath functions.
In my next blog, we will enhance the xpath functions to include parameters.
what are the dependent Jar files and import statements for the below Classes
Hi Kumar,
fabric-runtime.jar
import oracle.fabric.common.xml.xpath.IXPathContext;
import oracle.fabric.common.xml.xpath.IXPathFunction;
import oracle.fabric.common.xml.xpath.XPathFunctionException
depending in what you want to do, add the following jars:
soa-infra-mgmt.jar
orabpel.jar
xmlparserv2.jar
xml.jar
the paths depend upon your installation, so I just provided the jar names.
Let me know if you need something else.
Dan