Hi
I am looking into helping a xpath header issue on the user forum.
I wanted to know a bit more about it in Camel and how it works.
Camel does have a special notation for finding header values, that you can use
a $ shorthand. See this route:
from("direct:in").choice()
// using $headerName is possible in Camel to get the header
value
.when(xpath("$type = 'Camel'"))
.to("mock:camel")
So if the message contains a header with key type and the value is 'Camel' then
the expression evaluates to true.
However what if we send in an exchange that does *NOT* contain any header with
the key name type?
Currently you get a NPE exception in the SUN Xpath engine that is wrapped as a
XPathExpressionException that Camel catches and rethrows as
InvalidXPathExpression and thus the exchange fails and is caught by the
DeadLetterChannel. See stacktrace below:
But what if the expression should just evaluate to false if the header key does
not exists? There could be an otherwise or another when expression.
See this route:
from("direct:in").choice()
// using $headerName is possible in Camel to get the header
value
.when(xpath("$type = 'Camel'"))
.to("mock:camel")
// here we test for the body name tag
.when(xpath("//name = 'Kong'"))
.to("mock:donkey")
.otherwise()
.to("mock:other")
.end();
The fix seems easy as we could let the MessageVariableResolver#resolveVariable
return an empty string in case it did not find the $type.
// if we can't find an answer return an empty string so the expression
can be evaluated instead
// of throwing a NullPointerException
if (answer == null) {
return "";
} else {
return answer;
}
Here are the two tests that I try against the route above and where the 2nd
fails without the fix above:
public void testChoiceWithHeaderSelectCamel() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:camel");
mock.expectedBodiesReceived("<name>King</name>");
mock.expectedHeaderReceived("type", "Camel");
template.sendBodyAndHeader("direct:in", "<name>King</name>", "type",
"Camel");
mock.assertIsSatisfied();
}
public void testChoiceWithNoHeaderSelectDonkey() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:donkey");
mock.expectedBodiesReceived("<name>Kong</name>");
template.sendBody("direct:in", "<name>Kong</name>");
mock.assertIsSatisfied();
}
2008-07-23 06:58:04,296 [main ] ERROR DeadLetterChannel
- Failed delivery for exchangeId: ID-claus-acer/2228-1216789084015/0-0. On
delivery attempt: 0 caught:
org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath: $type =
'Camel'. Reason: javax.xml.xpath.XPathExpressionException
org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath: $type =
'Camel'. Reason: javax.xml.xpath.XPathExpressionException
at
org.apache.camel.builder.xml.XPathBuilder.evaluateAs(XPathBuilder.java:443)
at
org.apache.camel.builder.xml.XPathBuilder.matches(XPathBuilder.java:98)
at
org.apache.camel.builder.xml.XPathBuilder.matches(XPathBuilder.java:63)
at
org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:47)
at
org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:69)
at
org.apache.camel.processor.DeadLetterChannel.process(DeadLetterChannel.java:155)
at
org.apache.camel.processor.DeadLetterChannel.process(DeadLetterChannel.java:91)
at
org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:57)
at
org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:39)
at
org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:41)
at
org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:66)
at
org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:47)
at
org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:149)
at org.apache.camel.impl.ProducerCache.send(ProducerCache.java:86)
at
org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:84)
at
org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:101)
at
org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:107)
at
org.apache.camel.builder.xml.XPathHeaderTest.testChoiceWithBodyDonkey(XPathHeaderTest.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at junit.framework.TestCase.runTest(TestCase.java:164)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.textui.TestRunner.doRun(TestRunner.java:121)
at
com.intellij.rt.execution.junit.IdeaTestRunner.doRun(IdeaTestRunner.java:65)
at junit.textui.TestRunner.doRun(TestRunner.java:114)
at
com.intellij.rt.execution.junit.IdeaTestRunner.startRunnerWithArgs(IdeaTestRunner.java:24)
at
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:118)
at
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: javax.xml.xpath.XPathExpressionException
at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:183)
at
org.apache.camel.builder.xml.XPathBuilder.evaluateAs(XPathBuilder.java:429)
... 38 more
Caused by: java.lang.NullPointerException
at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.getResultAsType(XPathExpressionImpl.java:347)
at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:98)
at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:178)
... 39 more
Med venlig hilsen
Claus Ibsen
......................................
Silverbullet
Skovsgårdsvænget 21
8362 Hørning
Tlf. +45 2962 7576
Web: www.silverbullet.dk