You have a bad case of message poisoning ...
The main problems that I see are:
- you directly call the
save() method in onMessage() : this means that there is no way in the container to insert the correct transaction processing proxy using the save method - in any case, the
save() method must have @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) for fixing in a separate transaction, otherwise it joins the onMessage transaction (by default - REQUIRED ) and bypasses your exception handling code, beign after successful execution of onMessage
What I want to do:
Move the save method to a new session without a bean state:
@Stateless public class AnalyzerResultSaver { @PersistenceContext(unitName="QIS") private EntityManager em; @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) private void save(AnalyzerResult alyzres) throws PrdItemNotFoundException { Some s = em.find(Some.class, somepk); s.setSomeField("newvalue");
Add this bean to your MDB:
public class SaveAdMessageDrivenBean implements MessageListener { @Inject private AnalyzerResultSaver saver; @Resource private MessageDrivenContext mdc; public void onMessage(Message message) { try { if (message instanceof ObjectMessage) { ObjectMessage obj = (ObjectMessage)message; AnalyzerResult alyzres = (AnalyzerResult)obj.getObject(); saver.save(alyzres); } } catch (Throwable e) { mdc.setRollbackOnly(); log.log(Level.SEVERE, e); } } }
One more tip: message poisoning still exists in this code. Now this comes from the line calling mdc.setRollbackOnly(); .
I propose here to register an exception and send the message to a poisonous queue, thereby preventing the ad infinitum from sending the message again.
UPDATE:
A poison queue or an error queue simply means that your (hopefully recoverable) discarded messages will not be completely lost. It is heavily used in integration scenarios where the correctness of the message data is not guaranteed.
Setting up a poison queue involves defining a queue or destination topic and adding “bad” messages to that destination.
Periodically, the operator must check this queue (through a special application), as well as change messages and resend to a “good” queue, or discard the message and request an update.
source share