1

What is the best way to make a small modification to some data in a Camel route?

I'm pulling in a BSON document from Mongo. I need to use a timestamp from it in an http call, but I need to convert it from milliseconds to seconds.

I tried setting a header.

.setHeader("test").jsonpath("$.startTime")

Which lets me add the timestamp to the URL with a Simple expression.

.toD("https://test.com/api/markets?resolution=60&start_time=${headers.test}")

But I can't find a way to modify the value of the header.

I also tried using a process

.process(new Processor() {
    public void process(Exchange exchange) throws Exception {
        DocumentContext message = JsonPath.parse(exchange.getMessage().getBody());
        String time = message.read("$.startTime").toString();
        time = "111100000";  
        // do something with the payload and/or exchange here
       //exchange.getIn().setBody("Changed body");
   }
})

But here the exchange isn't passed back out. I based this on how I used an enrich EIP, with an aggregation strategy that returned an Exchange with the changes I made. This Process doesn't seem to work that way.

BenW
  • 737
  • 10
  • 41

2 Answers2

1

You can modify body, header or property using Lambda, processor or a bean. With processor you need to use Message.setHeader method to modify the value of the header at least for value types and strings. Bean methods receive body value by default so if you want to pass in header you'll need to specify it using simple language.

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

public class SetHeaderTest extends CamelTestSupport {

    @Test
    public void testGreeting() throws Exception {

        MockEndpoint resultMockEndpoint = getMockEndpoint("mock:result");
        resultMockEndpoint.expectedMessageCount(3);

        template.sendBodyAndHeader("direct:modifyGreetingLambda", 
            null, "greeting", "Hello");

        template.sendBodyAndHeader("direct:modifyGreetingProcessor", 
            null, "greeting", "Hello");

        template.sendBodyAndHeader("direct:modifyGreetingBean", 
            null, "greeting", "Hello");
    
        resultMockEndpoint.assertIsSatisfied();
    }

    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder(){

            @Override
            public void configure() throws Exception {
                
                from("direct:modifyGreetingLambda")
                    .routeId("modifyGreetingLambda")
                    .setHeader("greeting").exchange(exchange -> {   
                        String modifiedGreeting = (String)exchange.getMessage().getHeader("greeting");
                        modifiedGreeting += " world!";
                        return modifiedGreeting;
                    })
                    .log("${headers.greeting}")
                    .to("mock:result");

                from("direct:modifyGreetingProcessor")
                    .routeId("modifyGreetingProcessor")
                    .process(new Processor(){

                        @Override
                        public void process(Exchange exchange) throws Exception {
                            String modifiedGreeting = (String)exchange.getMessage().getHeader("greeting");
                            modifiedGreeting += " world!";
                            exchange.getMessage().setHeader("greeting", modifiedGreeting);
                        }
                    })
                    .log("${headers.greeting}")
                    .to("mock:result");

                from("direct:modifyGreetingBean")
                    .routeId("modifyGreetingBean")
                    .setHeader("greeting").method(new ModifyGreetingBean(), 
                        "modifyGreeting('${headers.greeting}')")
                    .log("${headers.greeting}")
                    .to("mock:result");
            }
        };
    }

    public class ModifyGreetingBean {
        public String modifyGreeting(String greeting) {
            return greeting + " world!";
        }
    }
}

Aside from these you can also use expression languages like simple or groovy.

Pasi Österman
  • 2,002
  • 1
  • 6
  • 13
1

In the route you can set the header with the milliseconds value .setHeader("test").jsonpath("$.startTime").

Then in a processor you can retrieve this value:

String milliSecondsValue = (String) exchange.getIn().getHeader("test");

Then you transform the milliSecondsValue to the value you want and you set it back on the exchange:

exchange.getIn().setHeader("test", secondsValue);

After that call .toD("https://test.com/api/markets?resolution=60&start_time=${header.test}") and it will use the seconds value

lbma
  • 132
  • 8