Apache Camel message exchange does not wait for the response - apache-camel

I have following code for publishing message to activeMQ and reading response via exchange. But code seem to be returning instantaneously and not waiting for the response. Could you please point what is wrong with the following Scala code.
def sendAndReceiveExtractionDetails(request:String, header: String) : String = {
val exchange: DefaultExchange = new DefaultExchange(camel, ExchangePattern.InOut)
exchange.getIn.setBody(request)
exchange.getIn.setHeader("meshId", header)
producer.send("activemq:queue:extractor-jobs?requestTimeout=1400000", exchange)
val out: apache.camel.Message = exchange.getOut()
out.getBody().toString
}

It seems to ignore the ExchangePattern you set. Have you tried to set it on your JMS URI as activemq:queue:...&exchangePattern=InOut?
I am not sure if you also need to define the JMSReplyTo header on the message or if this is done automatically when the exchangePattern is InOut.

Use the request method on the producer as that is for InOut

Following code works for me:
def sendAndReceiveExtractionDetails(request:String, header: String) : String = {
camel.createProducerTemplate()
.sendBody("activemq:queue:extractor-jobs?requestTimeout=1400000", ExchangePattern.InOut, request).toString
}

Related

Camel ActiveMQ replyTo Issues

Getting a exception when trying to use replyTo. Requirement is to receive reply from external queue . Not sure why I am getting timeout error, do I have to make any configuration changes or any code changes . Tried different ways, but it’s not working . Any help will be appreciated
I am reading file from folder, split the file and sending results to req queue and expecting a reply on req2
from("file://C:/pkuma1?fileName=request464.txt").routeId(messageType+"sasasas")
.split()
.tokenize("\\n")
.log(INFO,"i am initial")
.setHeader("JMSReplyTo", simple("req2"))
.inOut("amq://queue:req?replyTo=req2&preserveMessageQos=true&replyToType=Shared&receiveTimeout=250")
// .inOut("amq://queue:req")
.transform(constant("Bye Camel"))
.log(INFO,"msg id initial = ${in.header.JMSMessageId}")
.log(INFO,"corr id initial = ${in.header.JMSCorrelationID}")
.to("stream:out");
from("amq://queue:req")
.log(INFO,"i am second route")
.log(INFO,"msg id second route = ${in.header.JMSMessageId}")
.log(INFO,"corr id second route = ${in.header.JMSCorrelationID}");
.setHeader("JMSCorrelationID", simple("${in.header.JMSCorrelationID}"));
.transform(simple("Hello in second route ${in.body}"))
.process(exchange -> {
System.out.println(exchange);
System.out.println("route2");
});
//.end();
//.to("amq://queue:req2");
from("amq://queue:req2?disableReplyTo=true")
.log(INFO,"i am third route")
.log(INFO,"msg id third route = ${in.header.JMSMessageId}")
.log(INFO,"corr id third route = ${in.header.JMSCorrelationID}")
.setHeader("JMSCorrelationID", simple("${in.header.JMSCorrelationID}"))
.transform(simple("Hello ${in.body}"))
.process(exchange -> {
System.out.println(exchange);
System.out.println("route3");
System.out.println(exchange.getIn().getHeader("JMSCorrelationID"));
exchange.getIn().setBody("Hello ${in.body}");
exchange.getIn().setHeader(JmsConstants.JMS_DESTINATION, "");
exchange.getIn().setHeader("JMSReplyTo","");
exchange.getIn().setHeader("JmsDestination","");
exchange.getIn().setHeader("CamelJmsDestination","");
})
.to("stream:out")
.end();
Getting following error Timeout occurred after 120000 millis waiting for reply message with correlationID

How to send dictionary with array using JSON?

My fellow co-worker backend programmer said that he has configure an API that expect to receive something like this from my mobile app:
[{"id":50},{"id":60}]
I'm using Alamofire which receive param dictionary to be sent. But I believe this is also the same mechanism using NSURLSession or any other third party plugins.
The question is: how should I construct the dictionary to send an array of ids, like how a HTTP form can have several text field with the same id, and then it will be received on the server end as an array of id? What I've tried so far and all fails:
param.setValue(50, forKey:"id");
param.setValue(60, forKey:"id");
// this only send the last single value
param.setValue([50, 60], forKey:"id");
// this results in error (415 unsupported media type)
param.setValue(50, forKey:"id[0]");
param.setValue(60, forKey:"id[1]");
// this also results in error (415 unsupported media type)
How can I send this correctly just like how web form send? Thanks.
I think keyword for your question is "Alamofire send json"
If your server accepts json data, you can do like this:
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let values = [["id":50],["id":60]]
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(values, options: [])
Alamofire.request(request)
.responseJSON { response in
// do whatever you want here
}
Good luck!
The problem with the first method is you're overwriting the value for the key id, that's the reason why it only sends the last value. Try sending the params as an array.
let dict = NSMutableArray()
param.setValue(50, forKey:"id")
dict.addObject(param)
param.setValue(60, forKey:"id")
dict.addObject(param)
Pass the dict as the parameter for the request method.

Apache Camel EIP route - How to stop split()

I have some problems with a following route:
// from("cxf:....")...
from("direct:start").process(startRequestProcessor) // STEP 1
.choice()
.when(body().isNull())
.to("direct:finish")
.otherwise()
.split(body()) // STEP 2
.bean(TypeMapper.class) // STEP 3
.log("Goes to DynamicRouter:: routeByTypeHeader with header: ${headers.type}")
.recipientList().method(Endpoint1DynamicRouter.class, "routeByTypeHeader") // STEP 4
.ignoreInvalidEndpoints();
from("direct:endpoint2") // STEP 6
.log("Goes to DynamicRouter::routeByCollectionHeader with header: ${headers.collection}")
.recipientList().method(Endpoint2DynamicRouter.class, "routeByCollectionHeader")
.ignoreInvalidEndpoints();
from("direct:endpoint1.1") // STEP 5
.process(new DateRangeProcessor())
.to("direct:collections");
from("direct:endpoint1.2") // STEP 5
.process(new SingleProcessor())
.to("direct:collections");
from("direct:endpoint2.2") // STEP 7
.aggregate(header("collection" /** endpoint2.2 */), CollectionAggregationStrategy)
.completionSize(exchangeProperty("endpoint22"))
.process(new QueryBuilderProcessor())
.bean(MyService, "getDbCriteria")
.setHeader("collection", constant("endpoint2.1"))
.to("direct:endpoint2.1").end();
from("direct:endpoint2.1") // STEP 8
.aggregate(header("collection" /** endpoint2.1 */), CollectionAggregationStrategy)
.completionSize(exchangeProperty("CamelSplitSize"))
.to("direct:finish").end();
from("direct:finish")
.process(new QueryBuilderProcessor())
.bean(MyRepository, "findAll")
.log("ResponseData: ${body}").
marshal().json(JsonLibrary.Gson).end();
The route
Receives json string an converts it to list (HashSet) of JSONObjects.
split the received list to json objects.
Set corresponding headers according to object content
Routes the messages according to headers to endpoint1.1 or endpoint1.2
Convert messages to mongodb Criteria and send to endpoint2
Endpoint2 routes messages according to another header to endpoint2.1 or endpoint2.2.
Endpoint2.2 aggregates all received messages, processes it to get mongodb Criteria and sends it to endpoint2.1 (completionSize is calculated at step 2 and saved in property "endpoint22").
Enpoint2.1 aggregates ALL messages (CamelSplitSize) converts aggregated messages to Query object and sends it to Repository to retrieve the data.
I can see valid response object in debugger but anyway I get an error:
No message body writer has been found for class java.util.HashSet, ContentType: application/json
The problem is not in response object as it works with other routes and it does not contain HashSets.
My guess is that route sends to the output the HashSet created tat STEP 1...
My questions are:
what is wrong in the route output?
both recipientList() try to forward
messages to invalid endpoint ( I have to use .ignoreInvalidEndpoints() to avoid exception):
org.apache.camel.NoSuchEndpointException: No endpoint could be found for:
org.springframework.data.mongodb.core.query.Criteria#20f55e70, please
check your classpath contains the needed Camel component jar.
Any help would be much appreciated!
Thanks.
I find it very strange, but .aggregate() function does not reply exchange. It uses you aggregation strategy but always reply incoming exchange. This is not clear when reading documentation, but you have to use aggregation strategy along with split() to be able to return exchange.

Trying to retrieve first string from PubNub history Response

I know that the response from the pubnub history() is:
[["message","Message","message"],"Start Time Token", "End Time Token"]
im creating an string to receive the response:
String msg = response.toString();
And this should give me the full array, but now to retrieve the first message im doing this:
String[] msgOne = msg[0];
And this is not working.
for pubnub history method , the response is a org.json.JSONArray so to get the messages array you can use something like this.
JSONArray messages = (JSONArray)( ((JSONArray)response).get(0));
JSONArray class here http://www.json.org/javadoc/ provides more info about the methods that you can use on messages variable.

how can I get more error messages out of solrj SolrException

When I send queries to Solr using solrj, I sometimes get SolrException's thrown. When I dig through the exception, it just says "Bad Request", and gives the HTTP return code (which is 400).
When I take the request URL and put it in my browser, I was able to see a richer error message. The browser displays an error message saying one of the fields names is not valid.
I would like to be able to capture this inside my log file. I was able to capture this by copying all the parameters to an Apache HTTP Client POST request (I'm using POST and not GET because GET made the URL too long) and re-executing the request, but this is inefficient. Is there a way to get error message out of SolrException directly?
Here's what I'm doing:
catch (SolrServerException e) {
if(e.getRootCause() instanceof SolrException) {
SolrException ee = (SolrException) e.getRootCause();
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(SOLR_URL);
// copy params over
Iterator<String> iter = request.getParams().getParameterNamesIterator();
while(iter.hasNext()) {
String p = iter.next();
method.setParameter(p, request.getParams().get(p));
}
int statusCode;
try {
// re execute and display the error message
statusCode = client.executeMethod(method);
logger.error(method.getResponseBodyAsString());
} catch (Exception e1) {
// TODO Auto-generated catch block
}
}
These messages aren't available via SolrJ. You can see them in solr's log file, but there is no way to capture them in your client, since solr only returns the 400 error status with a generic message to the client :(

Resources