How can I get the body of MockEndpoint?
#EndpointInject(uri = "mock:direct:end")
protected MockEndpoint endEndpoint;
endEndpoint.setExpectedMessageCount(1);
String test = (String)endEndpoint.getExchanges().get(0).getIn().getBody();
endEndpoint.getExchanges() returns empty list and throws ArrayIndexOutOfBoundsException. However, endEndpoint does get 1 message.
You should get it after you send the message to that endpoint and not before. So, after template.send..
Related
Issue:
I have multiple route sending messages to an ActiveMQ queue which later gets processed by a processor to save status information
The same message sending from ProducerTemplate to ActiveMQ queue somehow breakes the same code by not triggering logs on console, and saving status information to a randomly generated file name.
Desired Behavior:
Both sending method gets the messages processed the same way
Code Explanation:
On below codes the Save processor is the one producing the weird behavior where logs dont show up on console and writes to some random file, file name is basically the clientID from ActiveMQ
StartRoute calling the activemq:save works correctly
Code:
public class Save implements Processor {
public void process(Exchange exchange) throws Exception {
try {
Map<String, Object> map = new HashMap<String, Object>() {};
map.put(".....", ".....");
map.put(".....", ".....");
map.put(".....", ".....");
map.put(".....", ".....");
ProducerTemplate template = exchange.getContext().createProducerTemplate();
String response = template.requestBodyAndHeaders("activemq:save", "Batch Job Started", map, String.class);
FluentProducerTemplate FluentTemplate = exchange.getContext().createFluentProducerTemplate();
String result = FluentTemplate
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.withHeader(".....", ".....")
.to("activemq:save")
.request(String.class);
} catch (Exception e) {
.....
}
}
}
public class StartRoute extends RouteBuilder {
restConfiguration()
.component("servlet")
.enableCORS(true);
rest("/start").id("start")
.post("/{filename}")
.route()
.....
.process(new Save())
.wireTap(startBackgroundProcessRoute)
.to("activemq:save")
.endRest();
}
public class SaveRoute extends RouteBuilder {
from("activemq:save")
.log("started saving")
.process(new FormatText())
.to("file:///status");
}
This question came from my original problem described here:
Camel Multicast Route call order
Solution can be found also there:
Camel Multicast Route call order
However to satisfy this question:
It seems Camel have few bugs regarding producer templates and maybe ActiveMQ, this is my initial conclusion.
The Only way i was able to use ProducerTemplate without issue is to use the send function with Exchanges, send() sends the messages correctly to the ActiveMQ same way as the to() however for whatever reason the content was still not written to the file.
After I dropped the ActiveMQ between the routes, everything started to work consistently. So possible miss configuration on ActiveMQ component or possible another camel framework bug.
If anyone knows the exact answer i would be happy to hear / see the reason for this behavior.
Code example:
public class SaveProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
ProducerTemplate template = exchange.getContext().createProducerTemplate();
template.send(Utilities.trackBatchJobStatus, exchange);
/** NOTE
* DO NOT USE any other functions which are not working with EXCHANGES.
* Functions that uses body, header values and such are bugged
*/
}
}
I created a class by extending HystrixCommand and configured timeout for the request using below code
HystrixCommandProperties.Setter().withExecutionIsolationThreadTimeoutInMilliseconds(int milliSec);
Also overriden fallBack method when request not returns response within timeout specified
#Override
protected JSONObject run() throws Exception
{
// performed some http call
final HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.GET, httpEntity, JSONObject.class)
.getBody();
System.out.println(response);
return response;
}
#Override
protected JSONObject getFallback()
{
final JSONObject json = new JSONObject();
json.put("status", "900");
json.put("message", "Request Failed");
return json;
}
Am getting fallBack method response whenever request takes more time than timeout specified which is expected.
But, what I observed is, when timeout occurs fallBack response is getting returned, and the response of the request which is executed in run method is coming later and am not able to hold or return as we returned the fallback response as soon as timeout.
Is there any way I can return that response ?
Thanks in advance.
I am using rabbitmq component in camel. I have a following route:
public void configure() throws Exception {
from("rabbitmq://localhost:5672/test_op?queue=out_queue&routingKey=test_out&username=guest&password=guest" +
"&autoAck=false&durable=true&exchangeType=direct&autoDelete=false&exchangePattern=InOut")
.aggregate(constant(true), new ArrayListAggregationStrategy())
.completionSize(2000).completionTimeout(60000).eagerCheckCompletion()
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
Message m = exchange.getIn();
org.apache.camel.TypeConverter tc = exchange.getContext().getTypeConverter();
String strValue = tc.convertTo(String.class, m.getBody());
System.out.println("[[out_queue]]: " + strValue);
}
});
}
Problem is that the use of aggregate is acknowledging the message to rabbitmq even before process() is called. I want to acknowledge message only when process() execution is successful, and not when aggregate is invoked. How can I achieve this?
FYI: Without aggregate this route works as expected. That means it acknowledges message only when process() is executed successfully.
I am getting a strange situation at the code below which simply routes request to Google and returns response.
It works well but when I activate the line commented out as "//Activating this line causes empty response on browser" to print out returned response from http endpoint (Google), response is disappear, nothing is displayed on browser. I thought it might be related with input stream of http response which can be consumed only once and I activated Stream Caching on context but nothing changed.
Apache Camel version is 2.11.0
Any suggestions are greatly appreciated, thanks in advance.
public class GoogleCaller {
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() {
from("jetty:http://0.0.0.0:8081/myapp/")
.to("jetty://http://www.google.com?bridgeEndpoint=true&throwExceptionOnFailure=false")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
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
}
});
}
});
context.setTracing(true);
context.setStreamCaching(true);
context.start();
}
}
As you use a custom processor to process the message, you should keep it in mind the in message of the exchange has response message from the google, if you are using exchange.getOut(), camel will create a new empty out message for you and treat it as response message.
Because you don't set the out message body in the processor, it makes sense that you get the empty response in the browser.
I have an InInterceptor that gets some information from the HTTPHeaders and creates a custom object
public void handleMessage(Message message) throws Fault {
final HttpServletRequest request = (HttpServletRequest) message
.get(AbstractHTTPDestination.HTTP_REQUEST);
String a= request.getHeader("A");
String b= request.getHeader("B");
message.put("CustomObject", new CustomObject(a,b));
}
Then in service methods I use below code to get the custom object
final Message message = PhaseInterceptorChain.getCurrentMessage();
final CustomObject customObject=(CustomObject)message.getContextualProperty("CustomObject");
I was wondering if its possible to get this through #Context ..
#GET
#Path("/custom")
#Produces("application/json")
public List<Node> getA(#Context("CustomObject") String user) throws XYZException;
Thanks