About Mule, content-based routing and namespaces

Some of our Mule ESB applications make use of content-based routing when processing a message. To implement this in Mule we use a filtering-router with a jaxen-filter. The most simple example looks like this:

...
<outbound>
  <filtering-router>
    <vm:outbound-endpoint ref="out-queue" />
     <xm:jaxen-filter pattern="//firstname" expectedValue="Pascal"/>
  </filtering-router>
</outbound>
...

You can also use a XPath function in your jaxen-filter like this (if you want to check a certain element is in an XML message regardless the value of the element):

...
<outbound>
  <filtering-router>
    <vm:outbound-endpoint ref="out-queue" />
    <xm:jaxen-filter pattern="local-name(//Relations)" expectedValue="Relations"/>
  </filtering-router>
</outbound>
...


The problem starts if you have to declare namespaces in your XPath expression. You can use namespaces in your XPath expression by declaring a namespace-manager in your mule-config, like this:

...
 <xm:namespace-manager includeConfigNamespaces="false">
   <xm:namespace prefix="ns1" uri="http://www.redstream.nl/relations/v1_1"/>
 </xm:namespace-manager>
...
   <outbound>
     <filtering-router>
       <vm:outbound-endpoint ref="out-queue" />
       <xm:jaxen-filter pattern="local-name(//ns1:Relations)" expectedValue="Relations"/>
     </filtering-router>
   </outbound>
...

But if you run this example you will get the following exception:

org.jaxen.UnresolvableException: No Such Function {http://www.mulesource.org/schema/mule/core/2.2}:local-name
at org.jaxen.SimpleFunctionContext.getFunction(SimpleFunctionContext.java:127)
at org.jaxen.ContextSupport.getFunction(ContextSupport.java:242)
at org.jaxen.Context.getFunction(Context.java:216)
at org.jaxen.expr.DefaultFunctionCallExpr.evaluate(DefaultFunctionCallExpr.java:172)
at org.jaxen.expr.DefaultXPathExpr.asList(DefaultXPathExpr.java:102)
at org.jaxen.BaseXPath.selectNodesForContext(BaseXPath.java:674)
at org.jaxen.BaseXPath.selectSingleNodeForContext(BaseXPath.java:698)
at org.jaxen.BaseXPath.stringValueOf(BaseXPath.java:279)
at org.jaxen.BaseXPath.valueOf(BaseXPath.java:254)
at org.mule.module.xml.filters.JaxenFilter.accept(JaxenFilter.java:184)
at org.mule.module.xml.filters.JaxenFilter.accept(JaxenFilter.java:118)
at org.mule.routing.outbound.FilteringOutboundRouter.isMatch(FilteringOutboundRouter.java:119)
at org.mule.routing.outbound.DefaultOutboundRouterCollection. route(DefaultOutboundRouterCollection.java:72)
at org.mule.service.AbstractService.dispatchToOutboundRouter(AbstractService.java:867)
at org.mule.model.seda.SedaService.dispatchToOutboundRouter(SedaService.java:561)
at org.mule.model.seda.SedaService$ComponentStageWorker.doRun(SedaService.java:583)
at org.mule.work.AbstractMuleEventWork.run(AbstractMuleEventWork.java:41)
at org.mule.work.WorkerContext.run(WorkerContext.java:310)
at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor. runWorker(ThreadPoolExecutor.java:1061)
at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker. run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Thread.java:637)

Although it is logged as warning it makes the filter to return no matching values and the XML message is discarded (although I use the jaxen-filter here this also goes for the jxpath-filter and the xpath-filter).

The solution for this is quite simple: just give the XPath function a unique prefix (one that is not mapped to a namespace). So if you modify the last example and make the jaxen-filter like:
<xm:jaxen-filter pattern="fn:local-name(//ns1:Relations)" expectedValue="Relations"/>
or
<xm:jaxen-filter pattern="abc:local-name(//ns1:Relations)" expectedValue="Relations"/>
it will work.
You just have to make sure the prefix you use isn’t used in the declared namespace-manager because then the function is looked up (and not found) in the supplied XML document.

About Pascal Alma

Pascal is a senior IT consultant and has been working in IT since 1997. He is monitoring the latest development in new technologies (Mobile, Cloud, Big Data) closely and particularly interested in Java open source tool stacks, cloud related technologies like AWS and mobile development like building iOS apps with Swift. Specialties: Java/JEE/Spring Amazon AWS API/REST Big Data Continuous Delivery Swift/iOS
This entry was posted in Mule2, XML/ XSD/ XSLT and tagged , . Bookmark the permalink.