7 Replies Latest reply on Jan 30, 2015 7:54 AM by andrefrancisco

    Camel Binding - Header manipulation

    andrefrancisco

      Hello,

       

      We are using the camel exchange header and we are not being able to manipulate the header once it's set. We are setting an xml in the header and we would like to set some values to those xml nodes.

       

      So far we are receiving the exchange to be manipulated by JMS and we are trying to manipulate the header to add values to the nodes.

      Our main route is something like this:

       

          <route streamCache="true" id="Main">

              <from uri="switchyard://endpoint" />

              /** Here we would like to manipulate the header ${headers.header} **/

             <wireTap uri="direct:routeMessage" copy="true">

                  <body>

      <simple>${headers.header}</simple>

                  </body>

             </wireTap>

              <to uri="switchyard://newEndPoint"/>

              /** Here we would like to manipulate the header ${headers.header} again **/

              <wireTap uri="direct: routeMessage " copy="true">

                  <body>

      <simple>${headers.header}</simple>

                  </body>

             </wireTap>

          </route>

        

      And our header is something as this fields, among others:

      <Header>

      <Info>

      <InternalID></ InternalID >

      </Info>

      <StartTime></StartTime>

      <EndTime></EndTime>

      </Header>

       

       

      We would like to be able to manipulate the header where we mention above so we could set values on the nodes. We have a xslt file to do some transformations and it would be great if we could manipulate the header directly with the xslt, but any other way to do it would be much appreciated.

       

       

      Thank you in advance

        • 1. Re: Camel Binding - Header manipulation
          slayercode2

          Hello, In Switchyard, headers are not automatically copied, you have to add to messageComposer which headers you want to include (.*: all), see: http://unpoucode.blogspot.com/2014/10/message-composers-in-switchyard.html

          1 of 1 people found this helpful
          • 2. Re: Camel Binding - Header manipulation
            andrefrancisco

            Hi Akram, thank you for your help.

             

            We already did that, and we are receiving the headers just fine from the JMS. The thing is that we are not being able to find a way to directly edit the header we are receiving from the JMS message.

            We don't want to mess the content of the body while editing the header. Besides that, we would like to not use JAVA while editing.

             

            Is this possible?

            • 3. Re: Camel Binding - Header manipulation
              slayercode2

              Hello,

               

              You can try this solution:
              <route>

                   <setHeader headerName="InternalID">

                        <constant>myId1</constant>

                   </setHeader>

              </route>

               

              You can also set a header by using a xpath expression or by calling a method:

              <xpath>/order/@customer</xpath>
              <method beanType="MyBean"  method="myMethod"/>

              • 4. Re: Camel Binding - Header manipulation
                andrefrancisco

                Hi Akram,

                 

                Thank you for the suggestion. Actually, we already have the header set. What we would like to do is to edit it (kind of). Maybe an example would be easier to explain.

                Right now we have a header named "internalHeader" set:

                 

                <Header>

                <Info>

                <InternalID></ InternalID >

                </Info>

                <StartTime></StartTime>

                <EndTime></EndTime>

                </Header>

                 

                Witch means that we have a header with a XML format (it's a string and not a DTMNodeList) and we would like to populate the nodes of that XML. So, we have already tried something like this:

                 

                <setHeader headerName="internalHeader">

                     <xpath>/Header/Info/InternalID = 12345 </xpath>

                </setHeader>

                 

                But from what we understood we can not set a value with xpath, just get the values and compare them.

                 

                Any suggestion of how we could achieve this?

                • 5. Re: Camel Binding - Header manipulation
                  jorgemoralespou_2

                  Hi,

                  setHeader sets the whole header, and since you want to modify it's contents, you should get the header, modify and then set it back.

                  You should probably do it better in a processor.

                  For this use case I would probably not use XML values as headers, and use plain headers, and then compose the final header before sending to the reference.

                   

                  Anyway, you should ask better in the camel forums, as this is more a Camel related question than FSW itself.

                   

                  Here are some links:

                  http://camel.465427.n5.nabble.com/setHeader-using-xpath-returns-Object-td4726154.html

                  http://stackoverflow.com/questions/23644836/camel-how-to-manipulate-output-message-set-header-based-on-xpath-expression

                   

                  XpathBuilder will be your friend ;-)

                   

                  Cheers,

                  1 of 1 people found this helpful
                  • 6. Re: Camel Binding - Header manipulation
                    slayercode2

                    Hi André,

                    If I have understood correctly your problem, then I think you should use a processor in your use case. Here an example:

                     

                    @Named("MyProcessor")

                    public class MyProcessor implements Processor {

                        public CustomProcessor() {

                        }

                        public void process(Exchange exchange) throws Exception {

                            String h1 = (String) exchange.getIn().getHeader("h1");

                            String h2 = (String) exchange.getIn().getHeader("h2");

                            String h3 = (String) exchange.getIn().getHeader("h3");

                            exchange.getOut().setBody(

                                            "<Header>"

                                                + "<Info>"

                                                    + "<InternalID>" + h1 +"</InternalID>"

                                                + "</Info>"

                                                + "<StartTime>" + h2 +"</StartTime>"

                                                + "<EndTime>" + h3 +"</EndTime>"

                                            + "</Header>"

                                            + exchange.getIn().getBody());

                        }

                    }

                     

                    I hope this would help you.

                    • 7. Re: Camel Binding - Header manipulation
                      andrefrancisco

                      Thank you for your input. Both suggestions were good.

                       

                      As I was trying to avoid the use of JAVA, I end up with the following concept:

                       

                      I use multicast so I can work the header as being my body and in the end I use a CustomAggregationStrategy to build it back together.

                       

                      I ended with something like this:

                       

                      <route streamCache="true" id="Main">

                              <from uri="jms:endpoint" />

                         <to uri="direct:manipulateHeader" />

                             <wireTap uri="direct:routeMessage" copy="true">

                                  <body>

                             <simple>${headers.header}</simple>

                                  </body>

                             </wireTap>

                              <to uri="switchyard://newEndPoint"/>

                         <to uri="direct:manipulateHeader" />

                              <wireTap uri="direct: routeMessage " copy="true">

                                  <body>

                             <simple>${headers.header}</simple>

                                  </body>

                             </wireTap>

                          </route>


                      <route>

                              <from uri="direct:manipulateHeader" />

                            <multicast parallelProcessing="true" strategyRef="headerProcessor" >

                                  <pipeline id="Header">

                                      <setBody id="[HeaderAsBody]">

                                          <simple>${headers.header}</simple>

                                      </setBody>

                                      <recipientList strategyRef="headerProcessor">

                                         <simple>xslt:${property.myProperty}_Transformer.xsl</simple>

                                      </recipientList>

                                  </pipeline>

                                  <pipeline id="Body">

                                      <setBody id="[BodyAsBody]">

                                          <simple>${body}</simple>

                                      </setBody>

                                  </pipeline>

                              </multicast>

                      </route>



                      And my AggregationStrategy is


                      public class HeaderProcessor implements AggregationStrategy{

                        @Override

                        public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {

                             if (oldExchange == null)

                             {

                                 // the first time we have the header in our body

                                 return newExchange;

                              }

                             else {

                                  // the second time we will have the header in the old exchange

                                  String oldEx = oldExchange.getIn().getBody(String.class);

                        

                                  // so we set the old body in the header of the new exchange

                                  newExchange.getIn().setHeader("header", oldEx);

                        

                                  // return the new exchange with our JMS exchange edited

                                  return newExchange;

                             }

                         }

                      }