camel jms request / reply - jms

I'm quite new to camel so excuse me if this is obvious.
We're trying to set up a camel route (in talend esb) which does the following:
receive a Message by JMS
db update
send the message to another system by JMS using request/reply
use the information in the reply to do another db update
This is all in one route.
What I have found out is that the route doesn't accept any more Messages in 1. while it is waiting for the reply in 3.
I have tried to use the "asyncConsumer" parameter on the JMS component but that didn't help.
How can I design the route so that it can process a second (and more) Message while it is still waiting for a reply in 3. ?
Thanks,
Laci

The parameter Petter explained will help but you will still block threads. Another approach is to design the integration as two separate routes. In the first route you receive the jms message, update the db and send out the second message.
If you use InOnly on the producer of this route and set a JMSReplyTo as well as preserveMessageQuo=true then camel will send out the message but not wait for a reply.
Then you use a second route that listens on the reply to queue you specified and does the second db update. This way you do not block any threads.

Use the concurrentConsumers attribute. It will enable multiple threads to handle your load. Note that you have to specify the number of threads. This can be a bit complex with all options, so be sure to read the Camel JMS documentation properly.
example
from("jms:myQueue?concurrentConsumers=10")
You may want to specify concurrentConsumers on the reply queue for the request reply as well:
.inOut().to("jms:requestQueue:foo?concurrentConsumers=10")
The last part Requires version 2.10.3 though.

Related

Spring AMQP - Is there a synchronous blocking send method that only waits for confirm?

I am using Spring AMQP v1.4.2 and trying to find a send method, possibly in RabbitTemplate, that blocks the thread until a confirm is received from the server to make sure we do not lose messages.
I have seen the sendAndReceive() method but it waits for a reply message in an RPC style, while I just want to wait for a confirm on the channel. I know that I can use the setConfirmCallback() method but then it means it is not synchronous and I may end up on a different thread when the confirmation arrives and I will lose my thread-locals, i.e. lots of Spring goodies.
Is there anyway to achieve that in Spring AMQP?
RabbitMQ gets huge performance benefits by using asynchronous publishing. As you say, you can configure publisher confirms to get an asynchronous confirmation that a message was delivered to a queue.
If you really want to block, you can use setChannelTransacted(true) on the RabbitTemplate; the commit will block until the message is secured in the queue(s).

Acknowledging a message from AMQP in Camel

Currently I'm using bluelock's camel-spring-amqp component for my application.
What I want to achieve is:
Pull a message from RabbitMQ server.
Persist it to a database on successful processing / Send it to another "Error" queue on Exception
Tell the original queue that it is now safe to remove the message from the queue.
As of this writing, I'm able to pull from rabbit and persist to database using camel routes. What I don't really know how to do is acknowledge that my processing is done to the original queue. Here is my current route:
from("spring-amqp:EXCHANGE:queuename?autodelete=false&durable=true&type=direct&routingKey=")
.bean(Transform.class, "transform(byte[])")
.to("jpa:com.my.company.models.MyModel?entityType=java.util.ArrayList")
I realize I can set the acknowledgmentMode to NONE. But I don't know how to "manually" acknowledge once I have persisted my message.
Thanks for any help!
I'm new in Camel but I know a thing or two about RabbitMQ.
With RabbitMQConsumer the message is acknowledged if the processor doesn't throw any exception (line 133 at RabbitMQConsumer source).
So I suppose if you let your processor propagate the exception, the message won't be acknowledged. I haven't used spring-amqp but I guess it should have a similar behaviour.

Processing a single message using Spring jms

I am working on an existing Spring jms application that pulls messages from ActiveMQ using jms:inbound-gateway. This application is a job processor that takes jobs off a queue and sends results back to the queue. Everything currently works great.
I would like to modify this application to accept one and only one job, process it, and then exit, but I have not been able to find a way to cleanly do this. The method that is called must return the results, and the results are automatically placed back onto the queue by Spring. Is there any way to tell Spring to stop accepting messages at 1? How would you know when it's done sending the reply message so you can exit.
In a more general case, if you had an application that wanted to stop accepting messages and finish processing them all so you could exit cleanly, how can that be done?
Thanks in advance for any advice.
It sounds like you should be using JmsTemplate.receive . Inbound gateway is meant for a message driven model. It sounds like while you are using a message queue for transport, you're not really doing a message driven model of processing. Obviously that's not a problem but if your aim is to process a single message you should just use JmsTemplate.
Another way to do this is to use the default message listener container, ensure threads is set to one and then make sure your activemq setup has no read-ahead setup (i.e. reads one message at a time and no more). Then, at the end of your onMessage method, call the DMLC.stop method.

Spring integration - Processing 2 same messages in aggregation differently

I am connecting to TCP socket using spring integration. I send 2 different messages on an outbound gateway which returns same outputs i.e. header as well as payload.
Now I want to process reply messages differently and then aggregate into a single message which can then be processed by main service class.
I tried various techniques but nothing worked.
Is it feasible to do so? If yes, kindly help me out.
You need something to correlate the messages, maybe a header (e.g. the standard correlation id).
Use a header-enricher to set the correlation id header on each outbound message. Send the reply messages to an <aggregator /> with a simple release strategy (release-strategy-expression="size() == 2"). When the second reply is received, a message with a payload (collection of the 2 payloads) will be released.

Spring integration - message store recovery/resend

I have a question regarding the behavior of a jdbc message store. I notice that if a failure occurs for instance if the following sequence is followed:
1)inbound-channel-adapter - Creates a message payload and sends it to a channel
2)The channel is polled for the payload by a jms:outbound-channel-adapter which adds an entry in the JMS queue. I am using ActiveMQ.
When I test for a situation like shutting down the MOM I would like to persist the message in the message-store, but this is not the default behavior. Looks like SI processes the payload in the channel and then pushes it out (deletes it from the store). I can see the message being inserted in the message-store in the database.
Am I wrong in understanding the function of a message-store? I thought that the message would persist until a successful run. Thanks for any feedback.
You need to set up durable subscriptions for that. I think most of the SI JMS components do support that.

Resources