I have code like this:
.from("file://" + FTP_FILES + "?idempotent=true")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
list = parseDataFromExchange(ecxhange);
}
I want to send this data to another pipeline vm:myEndpoint
I believe that Camel can this but google didn't help me.
How can I achieve this ?
Just use a ProducerTemplate from inside your Processor, then you can send any message to any Camel endpoint. You can find more information on the Camel website such as: http://camel.apache.org/producertemplate.html
Related
In my Springboot Camel application I'm using the Kafka integration to produce message on a topic.
I compared message produced by Camel Kafka integration with message produced by Kafka Spring integration and I noticed one little difference:
in OffsetExplorer, messages produced by Spring Kafka uses an Header "spring_json_header_types" with the class of all other headers, and header Long or Integer are correctly showed and serialized.
With Camel instead, if I set an header not String, in OffsetExplorer it is represented with the square char.
I did my research and found that Spring Kafka uses the DefaultKafkaHeaderMapper to create this header, and this help the inbound process to know how to deserialize the other header.
How can I use it in my Camel Kafka Producer?
Here my code:
#Component
public class KafkaProducerRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer:myTimer?period=10000")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Map<String, Object> headers = new HashMap<>();
headers.put("TIMER_COUNTER_1", exchange.getProperty(Exchange.TIMER_COUNTER, Long.class));
headers.put("TIMER_COUNTER_2", String.valueOf(exchange.getProperty(Exchange.TIMER_COUNTER, Long.class)));
exchange.getIn().setHeaders(headers);
}
})
.to("kafka:topic1?brokers=localhost:9092");
}
}
I am trying to use the Apache Camel aws2 DyanamoDB component. In that there is a operation DescribeTable. I was trying that out.I have a camel rest API like so ->
.post("dynamodb-describe-table")
.route()
.process(new Processor(){
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setHeader("CamelAwsDdbTableName", "user");
}
})
.toD("aws2-ddb://user?accessKey=insert&secretKey=insert®ion=us-east-1&operation=DescribeTable")
.endRest();
This operation is run successfully but the response is null. Why is this happening?
Operation DescribeTable does not return body. All attributes are returned in form of Message headers.
All headers returned by this operation are listed in AWS DynamoDB documentation.
You have many options to create body, eg. with MVEL:
.transform().mvel("{" +
"'tableSize': exchange.in.headers.CamelAwsDdbTableSize," +
"'status': 'exchange.in.headers.CamelAwsDdbTableStatus'" +
"}")
Or Processor:
.process( exchange ->
exchange.getIn().setBody(
new HashMap<String, Object>(){{
put("tableSize", exchange.getMessage().getHeader("CamelAwsDdbTableSize"));
put("status", exchange.getMessage().getHeader("CamelAwsDdbTableStatus"));
// ...
}}
)
)
Between your toD() and endRest().
BTW I don't see any dynamic part in your URI, you should be able to use just to(), which i generally faster.
I am new to Apache camel. I am trying to create routes to call multiple rest APIs and aggregate the response into one.
But for some reason, the JSON request that I am creating does not reach the rest endpoint.
During debug, I see that Exchange objects do have the values that I have set and get converted into byte array and on the other side, rest API recieves empty objects.
I am working on a Spring boot project and I have tried different ways of marshalling the request to JSON including Gson and Jackson. None of which seem to work.
Please assist.
from("direct:oneResponse")
.multicast(new MyAggregationStrategy()).parallelProcessing()
.to("direct:rest1call", "direct:rest2call")
.end();
from("direct:rest1call")
.routeId("rest1call")
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
.setHeader("Content-Type", constant("application/json"))
.setHeader("Accept", constant("application/json"))
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody(<<valid json>>); //json values as required for the rest call.
}
})
.to("http4://localhost:5555/mock/rest1call")
.setProperty("route", simple("routeId"))
.unmarshal(new JacksonDataFormat(Rest1Response.class));
from("direct:rest2call")
.routeId("rest2call")
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
.setHeader("Content-Type", constant("application/json"))
.setHeader("Accept", constant("application/json"))
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody(<<valid json>>); //json values as required for the rest call.
}
})
.to("http4://localhost:5555/mock/rest2call")
.setProperty("route", simple("routeId"))
.unmarshal(new JacksonDataFormat(Rest2Response.class));
Can you try to create a processor and specify all the headers and body in it?
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getOut().setHeader(Exchange.HTTP_METHOD, HttpMethod.POST);
exchange.getOut().setHeader(Exchange.CONTENT_TYPE, "application/json");
exchange.getOut().setHeader("Accept", "application/json");
/* this is one way, string representation of json, but maybe you can try to build Model and fill that model with data */
exchange.getIn().setBody(<<valid json>>); //json values as required for the rest call.
}
})
if you decide to go with models, use marshaling after processor just to be sure your data is converted to JSON.
.marshal(yourDataFormat)
Try GsonDataFormat it works pretty good for me.
I am new to using camel and I need to build a route in JAVA to process some xml returned by http request. I tried to parse the body of the response by setting up a route with a processor and log it to a file setting the consumer as http url but it didn't work. Then I tried to set up a jms queue to grab and process it from the queue with similar result.
I think I am getting the 200 response but the producer text file I set it to write to is not working and the log4j in DEBUG is not too informative on isolating the issue. Does anyone have any insight on this issue to point me in the right camel direction? thanks in advance!
public static void main(String[] args) throws Exception {
CamelContext camelContext = new DefaultCamelContext();
// connect to embedded ActiveMQ JMS broker
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("vm://localhost");
camelContext.addComponent("jms",
JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
try {
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:start")
.to("http://tomcatappurl:8080/format=xml?bridgeEndpoint=true")
.process(new OrderProcessor())
.to("log:DEBUG?showBody=true&showHeaders=true")
.log("file:C:/Desktop/camellog1.txt")
.to("log:DEBUG?showBody=true&showHeaders=true")
.log("${headers}")
.convertBodyTo(String.class)
.to("file:C:/Desktop/camellog1.txt")
.log("${in.headers}")
.to("stream:out")
.to("jms");
from("jms:incomingOrders")
.process(new Processor() {
public void process (Exchange exchange) throws Exception {
//HttpServletRequest request = exchange.getIn().getBody(HttpServletRequest.class);
System.out.println("Response received from Google, is streamCaching = " + exchange.getContext().isStreamCaching());
System.out.println("----------------------------------------------IN MESSAGE--------------------------------------------------------------");
System.out.println(exchange.getIn().getBody(String.class));
System.out.println("----------------------------------------------OUT MESSAGE--------------------------------------------------------------");
//System.out.println(exchange.getOut().getBody(String.class)); //Activating this line causes empty response on browser
}
})
.to("file:C:/Users/Desktop/camellog1.txt?fileExist=Append");
}
});
camelContext.start();
} finally {
camelContext.stop();
}
}
I think your routes are not running.
You need something (like a timer) to trigger your routes, for example:
from("timer:myTimer?period=30s")
.to("direct:start");
Camel documentation for Direct component says:
The direct: component provides direct, synchronous invocation of any consumers when a producer sends a message exchange.
So you need something else to start the invocation of the route.
Mind that your first route must finish to the correct JMS queue:
// ... cut
.to("file:C:/Desktop/camellog1.txt")
.log("${in.headers}")
.to("stream:out")
.to("jms:incomingOrders");
without the queue name it will not work.
I have route A that calls route B:
from("direct:a")
.to("direct:b");
from("direct:b")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception
{
System.out.println("Route B URI: " + exchange.getUnitOfWork().getRouteContext().getFrom().getEndpointUri()); //oops, prints direct:a
}
});
I would like the nested route B to print out its own URI, not the URI of the encapsulating route A. How could I do it?
Afaik, I don't think it's possible as is.
The UnitOfWorks keep a Stack of RouteContext, but this stack is not publicly accessible. However, you can access a history of the processor in which the exchange has been routed. This collection of MessageHistory is located in an header Exchange.MESSAGE_HISTORY. It contains the id of the processor and (sanitized) uri of the endpoints.
A more simple/robust approach can be to add explicitly a header on each route invoking the route B.
Personally, I don't think it's a good idea to depend on such information // internal details of the route!
Add a routeId() instruction to your route and use that to access your route definition:
from("direct:b")
.routeId("routeB")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
System.out.println("Route B URI: " + exchange.getContext().getRoute("routeb").getFrom().getEndpointUri());
}
});