I totally agree - we should try not to fail if a variable is not set. I guess the only decision is what is the value of an undefined variable; its a shame it can't be null :). I guess an empty string is a pretty good default - though I wonder what if someone actually wanted to test for a header being an empty string? I guess we could always support some xpath function like header-exists() if folks really wanted to differentiate missing headers from blank headers.
I wonder if returning some other Java object might work? e.g. returning Boolean.FALSE or Void.class or something. Though maybe we'd get some strange ClassCastExceptions if folks then did comparisions with strings or whatever. Another option could be some string constant that means an undefined header? e.g. something like "__CamelUndefinedHeader" which its pretty unlikely anyone would ever want to test for? 2008/7/23 Claus Ibsen <[EMAIL PROTECTED]>: > 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 > > > > -- James ------- http://macstrac.blogspot.com/ Open Source Integration http://open.iona.com