Integration with external systems over JMS. Clustered environment - spring

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.

Related

How and where to use JmsListenerEndpointRegistry start and stop function using SpringBoot?

I want to stop/pause the queue so that (https://issues.apache.org/jira/browse/AMQ-5229)
NO messages sent to the associate consumers
messages still to be enqueued on the queue
ability to be able to browse the queue
all the JMX counters for the queue to be available and correct.
Added: Apache ActiveMQ (Version 5.16.2)
But I don't know where to create the bean of JmsListenerEndpointRegistry and call start and stop method.
Sample code will be appreciated. Thanks.
The JmsListenerEndpointRegistry is automatically configured by Spring Boot.
Simply #Autowired it into the controlling class, give the JmsListener an id and stop/start it using the id.
Note: this does not use the AMQ feature you referenced; it simply tells the listener container to stop/start receiving messages.

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.

RabbitMQ Channel reuse (SimpleMessageContainer)

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.

ActiveMQ / JMS Message Handler Test

This is not totally on JMS Queue handler test. So, continue reading.
We have an architecture where spring channel listens to a queue from ActiveMQ. The listener of this queue will receive messages and has a static list of sub-listeners (identified by unique subjects). All the messages will have some parameters including the subject to which this message has to be delivered.
SMSService will drop its messages to the activemq with a subject SEND_SMS. It will be listened either by some HTTP Service or SMPP Service. You can even design your own Listener and wire that as a spring component with the required "subject".
Problem:
There is a better chance that this internal subject might change. This doesn't even throw an explicit Runtime Exception when there are no listeners. Is there a way to test this message being actually received by the intended listener?
`
As tim Bish siad, your problem statement is much too vague.
Have you tried to create your own ActivemMQ interceptor (I do not know if it could be usefull for your problem)

JBoss doesn't sends a JmsTemplate (Spring) message

Well, actually JBoss does send the message, but only when the current transaction started by the EJB is finished.
We have this problem with JBoss 4.0.3 and Spring's JmsTemplate. An EJB sends a message to a queue with a temporary queue as the reply_to field. Then, inside the same transaction, we listen for the response given by the first MDB. The problem is that the JmsTemplate's method "send" isn't executed after the transaction have finished. So, by the time the message is sent to the queue, and processed by the MDB, the listener of the temporary queue is gone.
This is called "Synchronous Reception"
Two things change this behavior but does raise some concerns:
Change the EJB's transaction type to BMT. (Concern: BMT sucks)
Create a thread that all it does is to call the JmsTemplate.send() method.
As a side note, this is an EJB that is working correctly on a weblogic environment, and the message does get sent when it should, in the middle of the transaction not when it's over.
Thanks for any help.
JBoss's behaviour is correct. JMS is a transactional API, and sends should only be executed when the tx commits.
It may be possible to convince JmsTemplate not use the current transactional context, although it makes a point of trying to hide the unpleasantness of the JMS API from you.
You could wrap the JMS template in code, either a Stateless session bean or a service method using Spring's transaction management, that uses a transaction propagation of REQUIRES_NEW. That way the sending of the message is in its own transaction that will commit the sending of the message outside the scope of the wrapping transaction.
I'm not sure why this would work on Weblogic though. My guess would be that on Weblogic it's not recognizing the queue as an XA Queue.

Resources