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



Reply via email to