camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Willem Jiang <willem.ji...@gmail.com>
Subject Re: Custom XPath Annotation
Date Mon, 11 May 2009 06:52:51 GMT
Yes, we could define the namespace when using the @XPath annotation.
Here is an example:

 public void checkLuggage(Exchange exchange, @Body String body,
@XPath(value = "/ns1:order/@custId", namespaces =
{@NamespacePrefix(prefix = "ns1", uri = "http://example.org/ns1")})
String custId) {
...
}

Since the namespaces is too long, I don't like this solution :(.

Willem


Claus Ibsen wrote:
> On Mon, May 11, 2009 at 2:46 AM, Willem Jiang <willem.jiang@gmail.com> wrote:
>> Hi
>>
>> After checking the Camel code, I think the MyXPath need to be extended
>> from XPath.
>>
>> That is because the XPathAnnotationExpressionFactory will check if the
>> annotation is the instance of XPath, before it adds the namespace into
>> the XPathBuilder.
> Well spotted.
> 
> I was wondering if we can do some check whether it has the @LanguageAnnotion
> and that the language attribute is = xpath.
> @LanguageAnnotation(language = "xpath", factory =
> XPathAnnotationExpressionFactory.class)
> 
> 
> But yet again this might be crossing the river to get water.
> People should just extend the existing XPath annotation class and add
> their own namespaces.
> 
> BTW: We could also add some convention so you could register some bean
> in the registry that holds the custom namespaces
> so you can leverage the existing @XPath annotation. As a kind of
> global additional namespaces. Might be easier than creating your own
> annotations that is not something developers do every day.
> 
> 
>> public class XPathAnnotationExpressionFactory extends
>> DefaultAnnotationExpressionFactory {
>>
>>    @Override
>>    public Expression createExpression(CamelContext camelContext,
>> Annotation annotation, LanguageAnnotation languageAnnotation, Class
>> expressionReturnType) {
>>        String xpath = getExpressionFromAnnotation(annotation);
>>        XPathBuilder builder = XPathBuilder.xpath(xpath);
>>        if (annotation instanceof XPath) {
>>            XPath xpathAnnotation = (XPath) annotation;
>>            NamespacePrefix[] namespaces = xpathAnnotation.namespaces();
>>            if (namespaces != null) {
>>                for (NamespacePrefix namespacePrefix : namespaces) {
>>                    builder =
>> builder.namespace(namespacePrefix.prefix(), namespacePrefix.uri());
>>                }
>>            }
>>        }
>>        return builder;
>>    }
>> }
>>
>> Willem
>>
>>
>> millej wrote:
>>> The bottom of this page talks about how to use my namespaces in an XPath
>>> injection as a parameter.   http://camel.apache.org/xpath.html
>>> http://camel.apache.org/xpath.html
>>>
>>> I've tried doing this, but for some reason I still get an exception saying
>>> it can't resolve my namespace.
>>>
>>> Here is my custom XPath annotation (edits to remove company info):
>>>
>>> @Retention(RetentionPolicy.RUNTIME)
>>> @Documented
>>> @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
>>> @LanguageAnnotation(language = "xpath", factory =
>>> XPathAnnotationExpressionFactory.class)
>>> public @interface MyXPath {
>>>       String value();
>>>       NamespacePrefix[] namespaces() default {
>>>               @NamespacePrefix(prefix = "soap", uri =
>>> "http://www.w3.org/2003/05/soap-envelope"),
>>>               @NamespacePrefix(prefix = "xsd", uri =
>>> "http://www.w3.org/2001/XMLSchema"),
>>>               @NamespacePrefix(prefix = "bg", uri =
>>> "http://mycompany.com/mynamespace")};
>>> }
>>>
>>> And my function that uses the custom annotation:
>>>
>>> @Consume(uri = "activemq:com.mycompany.myqueue")
>>> public String myFunction(
>>>       @Body String inXml,
>>>       @MyXPath("//bg:elem/@id") String id) {
>>>
>>>     log.info("Id: " + id);
>>>     log.info("Body: " + inXml);
>>>
>>>     return "<Success/>";
>>> }
>>>
>>> I couldn't find any examples for custom XPath annotations and the link above
>>> is all I could find about it in the documentation.  Any help as to what I
>>> need to do, or what needs to be done differently, is greatly appreciated.
>>>
>>> Also, I don't know if it is relevant, but I am using camel inside Fuse
>>> Servicemix with these versions:
>>>    ServiceMix: 3.4.0.0-fuse
>>>    Camel:  1.5.4.0-fuse
>>>    Activemq:  5.2.0.2-fuse
>>>
>>> And the exception:
>>>
>>> org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath:
>>> //bg:elem/@id. Reason: javax.xml.xpath.XPathExpressionException
>>>       at
>>> org.apache.camel.builder.xml.XPathBuilder.evaluateAs(XPathBuilder.java:443)
>>>       at
>>> org.apache.camel.builder.xml.XPathBuilder.evaluate(XPathBuilder.java:110)
>>>       at
>>> org.apache.camel.component.bean.MethodInfo$2.evaluate(MethodInfo.java:186)
>>>       at
>>> org.apache.camel.component.bean.MethodInfo.createMethodInvocation(MethodInfo.java:78)
>>>       at
>>> org.apache.camel.component.bean.BeanInfo.createInvocation(BeanInfo.java:100)
>>>       at
>>> org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:103)
>>>       at
>>> org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:72)
>>>       at
>>> org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:543)
>>>       at
>>> org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:482)
>>>       at
>>> org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:451)
>>>       at
>>> org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:323)
>>>       at
>>> org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:261)
>>>       at
>>> org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:982)
>>>       at
>>> org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:881)
>>>       at java.lang.Thread.run(Thread.java:619)
>>> Caused by: javax.xml.xpath.XPathExpressionException
>>>       at
>>> com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(XPathImpl.java:402)
>>>       at
>>> org.apache.camel.builder.xml.XPathBuilder.createXPathExpression(XPathBuilder.java:465)
>>>       at
>>> org.apache.camel.builder.xml.XPathBuilder.getExpression(XPathBuilder.java:301)
>>>       at
>>> org.apache.camel.builder.xml.XPathBuilder.evaluateAs(XPathBuilder.java:429)
>>>       ... 14 more
>>> Caused by:
>>> com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception:
>>> Prefix must resolve to a namespace: bg
>>>       at
>>> com.sun.org.apache.xpath.internal.compiler.XPathParser.errorForDOM3(XPathParser.java:653)
>>>       at
>>> com.sun.org.apache.xpath.internal.compiler.Lexer.mapNSTokens(Lexer.java:638)
>>>       at
>>> com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Lexer.java:265)
>>>       at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Lexer.java:96)
>>>       at
>>> com.sun.org.apache.xpath.internal.compiler.XPathParser.initXPath(XPathParser.java:110)
>>>       at com.sun.org.apache.xpath.internal.XPath.<init>(XPath.java:176)
>>>       at com.sun.org.apache.xpath.internal.XPath.<init>(XPath.java:264)
>>>       at
>>> com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(XPathImpl.java:394)
>>>
>>
> 
> 
> 


Mime
View raw message