Camel: getting EndpointUri of a nested route - java

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());
}
});

Related

Apache camel onException adding error details to the original message

I have added this exception handling to the camel route.
.onException(BeanCreationException.class, ValidationException.class)
.handled(true)
.process(new OnExceptionProcessor())
.to("errorQueue0").id("errorQueue")
.end()
public class OnExceptionProcessor implements Processor {
#Override
public void process(Exchange exchange) throws Exception {
Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
exchange.getIn().setHeader("FailedBecause", cause.getMessage());
}
}
When I read this message back from the error queue, I cannot find this header.
any idea on how to add error details along with the original message to the error queue
This could be a context problem because you are in a processor that is called by the error handler.
As an alternative, you could return the String value to set in the header from your processor method. By the way, this also improves the testability of your Processor.
Then you can use this return value to set the header in the error handler route directly.
.setHeader("FailedBecause", method(new OnExceptionProcessor()))

Camel: how to route data from process method to another pipeline?

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

camel route http response xml parsing

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.

Apache Camel - Unable to propagate JMS Header Properties between Request - Response

I am trying to save a value on the Camel Exchange between a Request - Response invocation against a QPID endpoint.
You can see from my code that I set a Header (and Property) before i invoke the Endpoint. Upon return the same Header and Property Values are null.
I basically want to keep a track of the fileName and filePath so that I can write the results into the same location
Really struggling with this.
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Value;
public class ProcessingRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
//#formatter:off
from("file:/home/molko/in/?recursive=true&include=.*.txt")
.log("File read from disk : ${file:name}")
.doTry()
.setHeader("JMSReplyTo", constant("response-1"; {create:always, node:{type:queue}}"))
.setHeader("JMSCorrelationID", constant(java.util.UUID.randomUUID().toString()))
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
final String fileParent = exchange.getIn().getHeader("CamelFileParent", String.class);
final String endPath = fileParent.substring(fileParent.lastIndexOf('/') + 1);
exchange.getIn().setHeader("endPath", endPath);
exchange.setProperty("endPath", endPath);
}
})
.to(amqp:request-1;{node:{type:queue}}?preserveMessageQos=true?exchangePattern=InOut")
.doCatch(Exception.class)
.log("Failed : ${file:name}")
.log("${exception.stacktrace}")
.stop();
from("amqp:response-1; {create:always, node:{type:queue}}")
.log("Received from qpid broker : ${date:now}")
.doTry()
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
byte[] response = exchange.getIn().getBody(byte[].class);
System.out.println("properties : " + exchange.getProperties());
System.out.println("headers : " + exchange.getIn().getHeaders());
}
})
.to("file:/home/molko/out")
.doCatch(Exception.class)
.log("Failed from qpid brokre : ${date:now}")
.log("${exception.stacktrace}")
.stop();
//#formatter:on
}
}
includeAllJMSXProperties is probably what you are looking for ,
Camel 2.11.2/2.12: Whether to include all JMSXxxx properties when
mapping from JMS to Camel Message. When set to true properties such as
JMSXAppID, and JMSXUserID etc will be included. Note: If you are using
a custom headerFilterStrategy then this option does not apply.
Source : https://camel.apache.org/jms.html

Camel onCompletion has null header

I have a Camel route with an onCompletion() which then hits a Processor. Within this processor it gets a header from the Exchange but this header comes back null.
I know that onCompletion() runs at the end of that particular route but surely the Exchange headers should still be valid and usable. inputLocation below is defined higher up in the class and works for previous routes.
from("file://"+inputLocation+"?initialDelay=5000&delay=2000&recursive=true&delete=true")
.onCompletion()
.process(storedProcProcessor())
.end()
.choice()
.when(appContext.getBean(AppPredicate.class))
.log("Need to check against APP in the database for destination.")
.setHeader(AppConstants.INPUTLOCATION, simple(inputLocation))
.process(databaseProcessor())
.endChoice();
I checked with:
#Override
public void configure() {
from("direct:start")
.onCompletion()
.process(new Processor() {
#Override
public void process(final Exchange exchange) throws Exception {
LOG.info("Hello, {}", exchange.getIn().getHeader("myHeader"));
}
})
.end()
.setHeader("myHeader").constant("World!");
}
}
This prints
Hello, World!
Thus, the header myHeader is still available in onCompletion. So, I guess that your header is never properly set?

Categories

Resources