package com.bsb.btm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import javax.jms.JMSException; import javax.jms.Message; /** * @author Stephane Nicoll */ public class MessageHandler { private final Logger logger = LoggerFactory.getLogger(MessageHandler.class); private final PlatformTransactionManager transactionManager; private final boolean createBusinessTransaction; public MessageHandler(PlatformTransactionManager transactionManager, boolean createBusinessTransaction) { this.transactionManager = transactionManager; this.createBusinessTransaction = createBusinessTransaction; } public void handleMessage(final Message message) { try { if (createBusinessTransaction) { // Creating a REQUIRES_NEW transaction and execute the callback new TransactionTemplate(transactionManager, new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW)) .execute(new MyTransactionCallback(message)); } else { // Just process the message with the current transactional context processMessage(message); } } catch (RuntimeException e) { logger.debug("Processing of the message has failed with [" + e.getMessage() + "]"); // Rollback ! throw e; } } private void processMessage(Message message) { final StringBuilder sb = new StringBuilder(); try { sb.append("Arg! I am code monkey! on [") .append(message.getJMSMessageID()) .append("] message redelivered [") .append(message.getJMSRedelivered()).append("]"); } catch (JMSException e) { throw new IllegalStateException("Should not have thrown this exception " + "while reading jms properties on", e); } // Always fail ! throw new NullPointerException(sb.toString()); } // A transaction callback that will always fail private final class MyTransactionCallback implements TransactionCallback { private final Message message; private MyTransactionCallback(Message message) { this.message = message; } @Override public Object doInTransaction(TransactionStatus status) { logger.debug("About to fail in a new transaction? " + status.isNewTransaction()); processMessage(message); // Should never happen throw new IllegalStateException(); } } }