Mark transaction as rollback only in MessageDrivenBean without repeating message

I have the following MessageDrivenBean:

@MessageDriven(mappedName = "jms/...", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryAttempts", propertyValue = "5"), @ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryInterval", propertyValue = "1000") }) public class MyMessageListener implements MessageListener { @Resource private MessageDrivenContext context; @Override @TransactionAttribute(REQUIRED) public void onMessage(Message message) { } } 

Inside the onMessage method, I do some processing, which is not important here. In certain situations, I want to refuse processing. In such situations, I want to mark the transaction as a rollback only and do not want to repeat the processing.

At least on Glassfish 3.1.1, if I call context.setRollbackOnly() on MessageDrivenContext and finish processing without throwing an exception, the message overflows at infinitely very, very short intervals. So this is not an option for me.

If I throw a RuntimeException , the message will be re-added as I pointed it out. It is reinstalled 5 times with an interval of 1 second. But in my case, I don’t want to repeat the processing at all.

If I just finish processing without raising any exception and not calling context.setRollbackOnly() , the transaction is committed as expected. But I need to cancel the transaction, because I may have already changed some JPA entities.

I have a question: how can I mark a transaction as rollback only after sending additional message delivery?

+4
source share
1 answer

I see two options:

  • Annotate a bean using @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) , use a bean transaction and not AUTO_ACKNOWLEDGE (explicitly acknowledge the message in MDB). Not an option, if your MDB is part of a larger XA transaction, you will not be able to influence the outcome of a global transaction.
  • Inspect the getJMSRedelivered() flag in the message and simply discard the sent message. The problem here is that when you re-deliver, you don’t know if this is a delivery that you should ignore (you said that in some cases you want to repeat the processing) - you will have to temporarily store (in the database or cache) message identifiers that weren’t processed, so you know if you can safely ignore them.
+1
source

Source: https://habr.com/ru/post/1389692/


All Articles