Today I am going to discuss about a extension point of WSO2 ESB, implementing custom XPath function which can be used in ESB sequence. If you didn't understand what I meant by custom XPath functions, let me take an example from WSO2 ESB.
Most of the users use get-property('propertyName') in sequences to retrieve properties, which is not a XPath function provided by jaxen (ESB uses jaxen library underneath) but we used it as a XPath function. So that is a good example of custom XPath function.
Now you know what is custom XPath function is. So lets start creating a new XPath function.
Here say we are going to add a XPath function to retrieve a upper case string of a given string. Lets say the function signature to-uppercase('string') which returns STRING.
In order to implement this we need to implement two interfaces.
- org.jaxen.Function
- org.apache.synapse.util.xpath.ext.SynapseXpathFunctionContextProvider
First let me show how I implement the Function interface.
package org.wso2.carbon.samples.xpath; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jaxen.Context; import org.jaxen.Function; import org.jaxen.FunctionCallException; import org.jaxen.function.StringFunction; import org.apache.synapse.MessageContext; import java.util.List; public class UpperCaseFunction implements Function { private Log log = LogFactory.getLog(UpperCaseFunction.class); private MessageContext synCtx; private String NULL_STRING = ""; public UpperCaseFunction(MessageContext synCtx) { this.synCtx = synCtx; } @Override public Object call(Context context, List list) throws FunctionCallException { if (list == null || list.size() == 0) { if (log.isDebugEnabled()) { log.debug("String not specified"); } return NULL_STRING; } String str = StringFunction.evaluate(list.get(0), context.getNavigator()); return str.toUpperCase(); } }
Here you can see I have parse the MessageContext in construct but I didn't use. Here I tried to show you how to access MessageContext inside the function implementation.
Now let me show how I implement SynapseXpathFunctionContextProvider.
package org.wso2.carbon.samples.xpath; import org.apache.synapse.MessageContext; import org.apache.synapse.util.xpath.ext.SynapseXpathFunctionContextProvider; import javax.xml.namespace.QName; import org.jaxen.Function; public class UppercaseXPathFunctionProvider implements SynapseXpathFunctionContextProvider { private static final String NAME_SPACE_PREFIX = "wso2"; private static final String CACHE_LOOKUP = "to-uppercase"; public Function getInitializedExtFunction(MessageContext messageContext) { UpperCaseFunction toUppercaseFunction = new UpperCaseFunction(messageContext); return toUppercaseFunction; } public QName getResolvingQName() { return new QName(null, CACHE_LOOKUP, NAME_SPACE_PREFIX); } }
That's all coding. Now make a OSGi bundle out of this and drop it into $ESB_HOME/repository/component/dropins or make a jar out of this and drop it into $ESB_HOME/repository/component/lib.
Now we need to register this and that can be done by adding the following entry to $ESB_HOME/repository/conf/synapse.properties file.
synapse.xpath.func.extensions=org.wso2.carbon.samples.xpath.UppercaseXPathFunctionProvider
You can try this out by creating a custom log as follows which will print the upper case of "wso2", "WSO2"
Hope this helps.