RabbitMQ Channel reuse (SimpleMessageContainer) - spring-rabbit

My spring boot application's is functionality it to listen to the messages on rabbitmq queue, do some processing in onMessage, and then publish the message on another rabbitmq queue. We are using spring-rabbit (1.7.2.RELEASE). We have configured listener using SimpleMessageListenerContainer.
My question is can i publish using he same channel on which I am reading he messages. Does spring-rabbit provides access to channel used by listener? so that same channel can be reused to publish?
Thanks,
Smita

If you use transactions (listener container), any operations performed by a transactional RabbitTemplate on the container thread will participate in the transaction and use the same channel.
If you are not using transactions, you can use a ChannelAwareMessageListener to access the channel the message was received on. See Message Listeners.
If you are using #RabbitListener you can add the Channel as a method parameter.
The current 1.7.x release is 1.7.9.

Related

Spring JMS acknowledgement behavior with TIBCO EMS EXPLICIT_CLIENT_DUPS_OK_ACKNOWLEDGE

I am using Spring JMS with TIBCO EMS queue/topic for my spring boot application. The TIBCO EMS queue is setup with EXPLICIT_CLIENT_DUPS_OK_ACKNOWLEDGE. In my code, I am not setting the acknowledgment mode, so I assume spring will take it s default AUTO_ACKNOWLEDGE. The behavior I notice in my listener onMessage method is, if the application successfully process the message, no redelivery of the same message And if the application throws a RuntimeException, there is a redelivery of the same message. The code is also with setSessionTransacted to true with DefaultJmsListenerContainerFactory. In this scenario, is the spring actually acknowledging the message on my behalf or do the code need to set the message.acknowledge().
See the javadocs for Session. Auto means the provider library automatically acks the message when consumer.receive() returns it, or the consumer.messsageListener() exits.
With a SimpleMessageListenerContainer, your listener is called directly by the provider's Consumer so messages won't be auto-ack'd until your listener exits normally.
The DirectMessageListenerContainer calls receive() instead and calls your listener on its own thread. Hence we need transactions to roll back the ack after an exception is thrown.

Integration with external systems over JMS. Clustered environment

I have an application where I created 2 message listener containers for external system A which listens two queues respectively.
Also I have 1 message listener container which running and listening another queue of external system B. I am using spring DefaultMessageListenerContainer.
My application is running on clustered environment, while defining my message listener container I injected to it my listener which implements javax MessageListener interface and acts as kind of MDB.
So my questions are:
Is it normal to have instance of message listener container per queue?
Will my message driven pojo (MDP) execute onMessage() on each application node?
If yes, how can I avoid it? I want each message to be consumed once on some of the application nodes.
What is default behavior of DefaultMessageListenerContainer, message is acknowledged as soon as I reached onMessage or after I finished execution of onMessage? Or maybe I need to acknowledge it manually?
See the spring framework JMS documentation and the JMS specification.
Yes it is normal - a container can only listen to one destination.
It depends on the destination type; for a topic, each instance will get a copy of the message; for a queue, multiple listeners (consumers) will compete for messages. This has nothing to do with Spring, it's the way JMS works.
See #2.
With the DMLC, it is acknowledged immediately before calling the container; set sessionTransacted = true so the ack is not committed until the listener exits. With a SimpleMessageListenerContainer, the message is ack'd when the listener exits. See the Javadocs for the DMLC and SMLC (as well as the abstract classes they subclass) for the differences.

Spring Integration - How to add message on topic before sending back acknowledgement for SOAP web service using declarative approach

I am consuming SOAP web service using inbound-gateway.We need to put message in kafka topic and return a synchronous acknowledgement to requestor using declarative way of spring integration. Is this possible ?
public Acknowledgement process(#RequestPayload MessagePayload payload) {
// perform validation & logic
// need to send message to kafka topic using declarative way
// sending synchronous ack to request originator
return new Acknowledgement();
}
The kafka outbound channel adapter has a sync property setSync(true) when using java config sync="true" when using XML.
The calling thread (web container) will block until kafka assumes responsibility. If you use a publish-subscribe channel, make the kafka adapter the first consumer, and a service to build the Acknowledgement the second consumer (use the order property in the consumers to ensure proper ordering).
Or you can use a KafkaTemplate directly from your controller.

Asynchronous push of messages in channel (spring-integration)

I have a simple JMS topic listener that i would like to hook with a spring-integration chain.
Basically, when a JMS message is received in the listener it has to be pushed into the chain's channel. Eventually the message is processed and pushed to an outbound-channel-adapter to be consumed.
The Spring Integration documentation mentions the use of asynchronous gateways but that uses Futures.
Isn't there a simple way to just put the message on a channel?
If there is an example that you can point to it would be great.
Thanks
Regards
Martin
If you want to run the flow on the listener thread, simply use a regular gateway (not an async one); this will allow the message to roll-back if the flow fails for any reason.
If you want to "fire and forget" you can make the request channel from the gateway an ExecutorChannel - see here.

Spring Integration - programmatically create / teardown channels

Is it possible to programmatically create / teardown Spring Integration channels, as opposed to declaring them statically in Spring config?
My situation is this:
I have a webapp that requires push notifications, so I'm using long polling. Those long polling calls need to block on the server until they get an event.
What I'm envisioning (open to alternatives, of course), is a Spring Integration queue channel for each session, each listening to a single pubsub channel. So, when a server event happens it will be published to the pubsub, which will then pipe down to the individual session queues where they'll be popped off and sent to the client that's polling.
In order to do this, when a session is created I'd have to register new queue channel listing on the pubsub channel. When the session is destroyed, that new queue will also be destroyed.
Is something like this possible?
I don't want to have the the session listening directly to the pubsub because there's a risk of losing messages, so I want to have a queue in between to buffer them.
Thanks,
Roy
Yes, you can simply instantiate a QueueChannel and make it the outputChannel of a BridgeHandler. Then create an EventDrivenConsumer, passing the pubSub and bridge handler in the constructor.
Call start() on the consumer to make it subscribe to the pubSub, and stop() to unsubscribe when the session is closed.
If you don't want to hand-wire these components, simply declare the queue channel, and bridge in a small application context; make it a child of your main context and it will automatically subscribe to the pubSub in the parent context. Call context.destroy() to disconnect.

Resources