Search code examples
javaspring-integrationdsl

How to use enrichHeaders method to pick up xpath of an xml element using java dsl


i am trying to pick up an xpth of an xml element using java dsl in spring integration. I am trying to put the element name in the enrichHeaders method but it doesn't seem to be working. This is the code:

return IntegrationFlows.from(Http.inboundGateway("/person")
                        .requestMapping(m -> m.methods(HttpMethod.POST)
                                .consumes("application/xml")
                                .produces("application/json")
                        )
                        )
                .enrichHeaders( h -> h.header("bsn","/BG:prsLa01/BG:body/BG:object/BG:bsn"))
                .transform(new XmlToJsonTransformer())
                .get();

Solution

  • There is support for xPath:

    https://docs.spring.io/spring-integration/docs/5.2.5.RELEASE/reference/html/xml.html#xpath-spel-function

    xpath SpEL Function

    Spring Integration, since version 3.0, provides the built-in #xpath SpEL function, which invokes the XPathUtils.evaluate(…​) static method. This method delegates to an org.springframework.xml.xpath.XPathExpression. The following listing shows some usage examples:

    <transformer expression="#xpath(payload, '/name')"/>
    
    <filter expression="#xpath(payload, headers.xpath, 'boolean')"/>
    
    <splitter expression="#xpath(payload, '//book', 'document_list')"/>
    
    <router expression="#xpath(payload, '/person/@age', 'number')">
        <mapping channel="output1" value="16"/>
        <mapping channel="output2" value="45"/>
    </router>
    

    The #xpath() also supports a third optional parameter for converting the result of the XPath evaluation. It can be one of the String constants (string, boolean, number, node, node_list and document_list) or an org.springframework.xml.xpath.NodeMapper instance. By default, the #xpath SpEL function returns a String representation of the XPath evaluation.

    To enable the #xpath SpEL function, you can add the spring-integration-xml.jar to the classpath. You need no declare any components from the Spring Integration XML Namespace. For more information, see "`Spring Expression Language (SpEL).

    It could look like this:

    .enrichHeaders(h -> 
                 h.headerExpression("bsn", "#xpath(payload, '/BG:body/BG:object/BG:bsn')"))
    

    Another way could be to XPathExpressionEvaluatingHeaderValueMessageProcessor:

    https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/support/XPathExpressionEvaluatingHeaderValueMessageProcessor.html

    Example of Usage:

            @Bean
            public IntegrationFlow xpathHeaderEnricherFlow() {
                return IntegrationFlows.from("xpathHeaderEnricherInput")
                        .enrichHeaders(
                                s -> s.header("one",
                                        new XPathExpressionEvaluatingHeaderValueMessageProcessor("/root/elementOne"))
                                        .header("two",
                                                new XPathExpressionEvaluatingHeaderValueMessageProcessor("/root/elementTwo"))
                                        .headerChannelsToString("12345")
                                        .messageProcessor(m -> s.header("foo", "bar")),
                                c -> c.autoStartup(false).id("xpathHeaderEnricher")
                        )
                        .get();
            }