jmslistener transactional junit rollback - spring-boot

I see multiple examples demonstrating on how to test jms-listeners, but what i am really looking for is testing some negative test cases such as,
test if jms transaction is rolled back if there is any error processing the message
test if jms listener handles/throws exception
Below are some examples, which jst shows positive test cases,
How to wait for #JMSListener annotated method to complete in JUnit
Writing tests to verify received msg in jms listener (Spring-Boot)

Use one of the positive test techniques to verify the listener actually received the message.
Then simply us JmsTemplate.receive() to verify the message was rolled back into the queue.
Or, if you are configured to send poison messages to a DLQ after some number of delivery attempts, you can simply receive from the DLQ in your test case.

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.

Quarkus / Smallrye Reactive Messaging - message redelivery

I'm currently investigating the Smallrye Reactive Messaging integration in Quarkus.Sending and receiving messages is really simple and elegant at first glance.
But one thing which I didn't find out is: How to handle a re-delivery of messages?
Example: We receive a message and try to process it. Some exception (maybe a DB not available or an optimistic lock exception or something) happens.
In such a case I would throw an exception so that the message is not acknowledged. But currently I see no way how the message is redelivered.
I set-up a small dummy project to test this:
Quarkus
ActiveMQ Artemis
send a message (via Artemis console) into a queue
-- queue configured with max redelivery = 3
receive the message with Quarkus / Smallrye Reactive Messaging #Incoming annotation
throw exception in the #Incoming method
--> Message is removed from the Artemis queue
--> #Incoming method is only called once
If I shutdown the Quarkus App, the message can be seen again in the Artemis queue with redelivered flag set to true.
But I find no way how I can manage/configure a redelivery in the Smallrye Reactive Messaging so that this layer handles the redelivery of a message for n times and puts the message into a DLQ after the max retries.
Is there any way to do this?

JUnit and jms - events fired are not consumed in the middle of test

We are using spring with junit , jms (activemq) and mySql.
We would like to create some junit tests that after their executions the db will rollback.
In order to achieve that we are using the #Transactional annotation for each tests.
Problem is, one of our tests is calling a service that sends a jms message, (in the middle of the test) the thing is the event is being consumed only after the tests ends (end of transaction maybe?)
thats why the assertion in the end of the test fails.
any ideas why the event is not being consumed right away (p.s we tried to use sleep in order to let the event be consumed, its not working)
Firstly, this is not a unit test ... that's fine ... There are 2 reasons message is not consumed:
The transaction in which the message is sent is not committed. Due to this the lock on the message on the server side is not released.
There is a timing issue and the test ends too soon and doesn't wait got the callback.
That's the whole point of transactions. The message is not available for consumption until the transaction commits (otherwise how could you roll it back if someone's already seen it?). You can do the send in a new transaction (Propagation.REQUIRES_NEW) if you don't want the send to be part of the encompassing transaction.

How do I hold a jms message in queue until it is saved?

I just started using Weblogic JMS. I was able to send messages to the queue and pull them off with a messagebean. Now I want to save the message to a database.
So my question is, how do I tell JMS not to delete the message from the queue until I have successfully written the message to the database?
Thanks
I was able to send messages to the queue and pull them off with a
messagebean.
I suppose you are talking about message-driven bean (MDB)?
So my question is, how do I tell JMS not to delete the message from
the queue until I have successfully written the message to the
database?
MDBs are part of implicit container-managed transaction and the message will not be removed as long as your transaction hasn't commited (that is, as long as your onMessage method hasn't reached its end).
In case of rollback (i.e. you throw an exception or call context.setRollbackOnly() on the MessageDrivenContext), message will be redelivered. You can avoid this behaviour by making transaction bean-managed or using #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED), but in your situation that should not be the case. Stick with default configuration and everything should work as you wish.

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)

Resources