I have a Message Driven Bean listening to MQ Receiver Queue for incoming Messages.
My MDB is implementing MessageListener and overriding OnMessage method, where I can handle any exception related to the received messages.
All the Connection & Queue parameters are in ejb-jar.xml and weblogic-ejb-jar.xml.
So in case of any Connection failure (e.g. MQ is down, I just get Exception in the console).
How should I catch and handle these connection failure related exceptions in MDB? As I have requirement to send Email notifications to Support group in case of such Connection Failures.
I just saw some info about javax.jms.ExceptionListener, but there is no way I could use it for my setup as I don't have direct access to my connectionfactory / connection objects in case of my MDB.
Related
We are trying to use spring-rabbit to create a message listener, in our spring boot application. But, we are getting an issue during receiving message if the queue doesn't exist, the application throws an error, which is called as passive declaration.
Channel error on connection (172.13.1.3:49352 -> 172.13.1.7:5672, vhost: '/', user: 'guest'), channel 1:
message_queue_1_1 | operation queue.declare caused a channel exception not_found: no queue 'add' in vhost '/'
What we want is to declare a queue actively, i.e. if the queue doesn't exist, it should be declared inside the mq.
To declare AMQP objects on the Broker automatically from the application, you really need to configure them as beans and also have a special AmqpAdmin bean to perform the hard declaration logic. The documentation has all the required explanation: https://docs.spring.io/spring-amqp/docs/2.0.4.RELEASE/reference/html/_reference.html#broker-configuration
I'm using spring boot with spring-amqp and annotation based listener to consume message from a rabbitmq broker.
I've a spring component which contains a method like this:
#RabbitListener(queues = "tasks")
public void receiveMessage(#Payload Task task) {...}
I'm using the AUTO mode to acknowledge messages after successful execution of receiveMessage(...). If i detect a special error, i'm throwing AmqpRejectAndDontRequeueException to get this message into a configured dead letter queue. Now i need to nack a message only, so that the message gets requeued into the main queue of rabbitmq and another consumer has the possibility to work on that message again.
Which exception should i throw for that? I wouldn't like to use channel.basicNack(...) like described here (http://docs.spring.io/spring-integration/reference/html/amqp.html) if possible.
As long as defaultRequeueRejected is true (the default) in the container factory, throwing any exception other than AmqpRejectAndDontRequeueException will cause the message to be rejected and requeued.
The exception must not have a AmqpRejectAndDontRequeueException in its cause chain (the container traverses the causes to ensure there is no such exception).
I am trying to understand how acknowledgement modes work in JMS. I was reading this source and it hugely confused me as it was contradicting what Spring's documentation says.
Sources saying one thing:
From http://www.javaworld.com/article/2074123/java-web-development/transaction-and-redelivery-in-jms.html
A message is automatically acknowledged when it successfully returns from the receive() method. If the receiver uses the MessageListener interface, the message is automatically acknowledged when it successfully returns from the onMessage() method. If a failure occurs while executing the receive() method or the onMessage() method, the message is automatically redelivered.
From http://www2.sys-con.com/itsg/virtualcd/Java/archives/0604/chappell/index.html
With AUTO_ACKNOWLEDGE mode the acknowledgment is always the last thing to happen implicitly after the onMessage() handler returns. The client receiving the messages can get finer-grained control over the delivery of guaranteed messages by specifying the CLIENT_ACKNOWLEDGE mode on the consuming session.
Spring Docs saying other things:
From http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractMessageListenerContainer.html
The listener container offers the following message acknowledgment options:
"sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default): Automatic message acknowledgment before listener execution; no redelivery in case of exception thrown.
"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
"sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE": Lazy message acknowledgment during or after listener execution; potential redelivery in case of exception thrown.
"sessionTransacted" set to "true": Transactional acknowledgment after successful listener execution; guaranteed redelivery in case of exception thrown.
What I want to know is that why these sources are saying different things? If all are true then How do I know how/when my message will be acknowledged?
You missed out the key phrase from the abstract container javadocs...
The exact behavior might vary according to the concrete listener container and JMS provider used.
The most commonly used listener container used in Spring is the DefaultMessageListenerContainer which does exhibit that behavior - it is intended for use with transactions (either local or an external transaction manager), in order to have the ability to roll back an already acknowledged message. Its listener is invoked after the receive method, so the standard JMS auto-ack has already been applied. Any JmsTemplate operations on the thread can also use the same session - and thus can be part of the transaction.
On the other hand, the SimpleMessageListenerContainer uses a traditional MessageListener and exhibits the standard JMS behavior (the listener is called from the Consumer before receive() returns; thus exceptions will stop the ack).
I suggest you read the javadocs for those concrete implementations. From the SMLC...
This is the simplest form of a message listener container. It creates a fixed
number of JMS Sessions to invoke the listener, not allowing for dynamic
adaptation to runtime demands. Its main advantage is its low level of
complexity and the minimum requirements on the JMS provider: Not even the
ServerSessionPool facility is required.
See the AbstractMessageListenerContainer javadoc for details on acknowledge
modes and transaction options.
For a different style of MessageListener handling, through looped
MessageConsumer.receive() calls that also allow for transactional reception of
messages (registering them with XA transactions), see
DefaultMessageListenerContainer.
I will open up a JIRA issue for the docs on the abstract container because I can see that it might be misleading.
I configured spring xml based interceptor, which sends a jms message to activemq queue on each invokation of some transactional method after it is commited. It's happening with the following xml code.
<jms:outbound-channel-adapter channel="filteredStakesChannel" destination="stakesQueue" delivery-persistent="true" explicit-qos-enabled="true" />
But if the activemq server is down i get connection refused exception, which is propagated and i don't want this to happen even if the jms delivery fails. Is this possible?
Should i use some error-channel?
The simplest solution is to make fileredStakesChannel an Executor channel and the send will run on a different thread.
http://static.springsource.org/spring-integration/reference/html/messaging-channels-section.html#executor-channel
http://static.springsource.org/spring-integration/reference/html/messaging-channels-section.html#channel-configuration-executorchannel
Use the <task/> namespace to define an executor to use.
I'm using Spring 2.5 with my custom class that implements MessageListener. If a JmsException is thrown in my onMessage( ) method, what happens to the state of the queue?
Is the message considered "delivered" by the queue the moment onMessage is called? Or does the JmsException trigger some kind of rollback and the message is re-entered on the queue?
Thanks in advance!
From the JMS 1.1 spec...
4.5.2 Asynchronous Delivery
A client can register an object that implements the JMS MessageListener interface with a MessageConsumer. As messages arrive for the consumer, the provider delivers them by calling the listener’s onMessage method.
It is possible for a listener to throw a RuntimeException; however, this is considered a client programming error. Well-behaved listeners should catch such exceptions and attempt to divert messages causing them to some form of application-specific ‘unprocessable message’ destination.
The result of a listener throwing a RuntimeException depends on the session’s acknowledgment mode.
AUTO_ACKNOWLEDGE or
DUPS_OK_ACKNOWLEDGE - the message
will be immediately redelivered. The
number of times a JMS provider will
redeliver the same message before
giving up is provider-dependent. The
JMSRedelivered message header field
will be set for a message redelivered
under these circumstances.
CLIENT_ACKNOWLEDGE - the next message
for the listener is delivered. If a
client wishes to have the previous
unacknowledged message redelivered,
it must manually recover the session.
Transacted Session - the next message
for the listener is delivered. The
client can either commit or roll back
the session (in other words, a
RuntimeException does not
automatically rollback the session).
JMS providers should flag clients with message listeners that are throwing
RuntimeExceptions as possibly malfunctioning.