In my camel application, I am trying to send a message from the source AMQ Queue (INLET) doing some TRANSFORMATION(XMLTO JSON) to Target AMQ Queue (OUTLET) The message is successfully transferred from INLET to OUTLET. But the 1st Messages ID is different and the remaining all are the same in the entire route flow.
Below is the Message-IDs :
Message ID :ID:dbf0f290-c7e2-11ec-b776-6eb51c0a3021:-1:-1:-1:-1 (DIFFERENT)
Message ID :queue_INLET_ID_dbf0f290-c7e2-11ec-b776-6eb51c0a3021_-1_-1_-1_-1 (SAME)
Message ID :queue_INLET_ID_dbf0f290-c7e2-11ec-b776-6eb51c0a3021_-1_-1_-1_-1 (SAME)
Message ID :queue_INLET_ID_dbf0f290-c7e2-11ec-b776-6eb51c0a3021_-1_-1_-1_-1 (SAME)
Anyone help me on this.
Before I used exchange.getIn().getMessageId()
After using this exchange.getExchangeId() //Solved my issue
Related
our Logic app connects to MQ and polls messages, for one of hte queue, I am seeing message in below format coming in Message item binary content,
{
"$content-type": "application/octet-stream",
"$content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48bnM0aW9uVGV4dD4KICA8L0V4Y2VwdGlvbj4KPC9uczA6UG9saWN5VXBkYXRlPg==" //truncated value
}
How to get value from content in logic app?
Also for other queues message coming in Message item content and able to get text data correctly.
The issue got resolved after conneccting with MS Helpdesk, need to use string(Message item binary content) when reading messages, this will get decoded.
Usecase: I would like to pick messages from an http end point and route them to a jms endpoint.
My route configuration looks like:
from("jetty:http://0.0.0.0:9080/quote")
.convertBodyTo(String.class)
.to("stream:out")
.to(InOut, "wmq:queue:" + requestQueue +
"?replyTo=" + responseQueue +
"&replyToType=" + replyToType +
"&useMessageIDAsCorrelationID=true");
My understanding is that this way I will get a request-response pattern for the JMS endpoint and correlationId would be the unique identifier to make the response to the corresponding request.
This works well when I have only 1 instance of the application running however when I have more than 1 instances running simultaneously, responses are picked up randomly and not only by the producer.
For example, A and B are 2 instances of the route (and listener) with exact same configuration listening for responses on a shared queue. At times A gets its response but at times it also picks up response for the message produced by B.
Appreciate any help/pointers on this. Thanks!
Basically the issue was with the use of replyToType which was set to Exclusive - this resulted in listener picking up everything instead of using jms selectors to match correlation ids.
I changed the value of replyToType to Shared and its all working fine now.
This is well defined in section "Request-Reply over JMS" at http://camel.apache.org/jms.html
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.
I am using camel route for consuming the message from the queue for every 5 minutes and processing it.
While processing, if there are any exceptions,the camel/activemq sends the messages to the we .DLQ as I am using the client_acknowledge as given below, however I need to have the messages in the same queue(not to send to DLQ) in case of failures in case of processing errors.
Need help in how should I configure my route or component to meet that requirement.
from("jms:queue:test?receiveTimeout=5000&acknowledgementModeName=CLIENT_ACKNOWLEDGE").
log(LoggingLevel.INFO, "Consuming message from test : ")
.to("direct:MyProcessingRoute");
Would it be possible to achieve the following:
Sending msg a to Incoming, route A handles the message
Sending msg b to Incoming, route B handles the message
Sending msg a to Incoming, but since routeA is still handling the first message, this one starts blocking the incoming route to handle more messages.
Once route A is finished, the incoming router sends the third message to A and keeps getting messages from the incoming queue
from(incomingQueue)
.routeId("Incoming")
.choice()
.when(header("key").isEqualTo("a"))
.to("seda:A")
.when(header("key").isEqualTo("b"))
.to("seda:B")
;
from("seda:A")
.routeId("A")
.process(processor);
from("seda:B")
.routeId("B")
.process(processor);
SEDA will ACK back to the producer immediately and queue requests internally in routes A/B....
To block the producer in your incomingQueue route from sending to A/B routes until they have completed, then make your A/B routes DIRECT (synchronous).
note - I think this is what you asked for, but keep in mind that the A msgs/route would also block all B messages as well using this setup...
another option is to use something like ActiveMQ message groups, which allows single-threaded processing of related messages while allowing for parallel processing of other groups, etc...