Announcement Announcement Module
Collapse
No announcement yet.
New transactions within JMSTemplate transactions without XASession Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • New transactions within JMSTemplate transactions without XASession

    In the Spring manual the following is said concerning Spring JMS:

    19.2.5. Transaction management

    Spring provides a JmsTransactionManager that manages transactions for a single JMS ConnectionFactory. This allows JMS applications to leverage the managed transaction features of Spring as described in Chapter 9, Transaction management. The JmsTransactionManager performs local resource transactions, binding a JMS Connection/Session pair from the specified ConnectionFactory to the thread. JmsTemplate automatically detects such transactional resources and operates on them accordingly.

    In a J2EE environment, the ConnectionFactory will pool Connections and Sessions, so those resources are efficiently reused across transactions. In a standalone environment, using Spring's SingleConnectionFactory will result in a shared JMS Connection, with each transaction having its own independent Session. Alternatively, consider the use of a provider-specific pooling adapter such as ActiveMQ's PooledConnectionFactory class.

    JmsTemplate can also be used with the JtaTransactionManager and an XA-capable JMS ConnectionFactory for performing distributed transactions. Note that this requires the use of a JTA transaction manager as well as a properly XA-configured ConnectionFactory! (Check your J2EE server's / JMS provider's documentation.)

    Reusing code across a managed and unmanaged transactional environment can be confusing when using the JMS API to create a Session from a Connection. This is because the JMS API has only one factory method to create a Session and it requires values for the transaction and acknowledgement modes. In a managed environment, setting these values is the responsibility of the environment's transactional infrastructure, so these values are ignored by the vendor's wrapper to the JMS Connection. When using the JmsTemplate in an unmanaged environment you can specify these values through the use of the properties sessionTransacted and sessionAcknowledgeMode. When using a PlatformTransactionManager with JmsTemplate, the template will always be given a transactional JMS Session.
    I apply this pattern with DefaultMessageListenerContainer utilising the JMSTemplate. I overrid the method "createSession" as follows:

    Code:
    @Override
    protected Session createSession(Connection connection) throws JMSException {
    	try {
    		return xaSessionCreator.createXASession((XAConnection) connection);
    	} catch (StoppingChannelException e) {
    		throw new RuntimeException(e);
    	}
    }
    The createXASession is implemented as follows:

    Code:
    @Override
    /** Create a new XASession for the given XAConnection and enlist it in the
     * current JTA transaction. If used in combination with Spring JmsTemplate,
     * Spring will handle transaction Synchronisation.
     */
    public XASession createXASession(XAConnection xaConnection)
    		throws JMSException, StoppingChannelException {
    	XASession xaSession = xaConnection.createXASession();
    	try {
    		if (!transactionManager.getTransactionManager().getTransaction()
    				.enlistResource(xaSession.getXAResource())) {
    			throw new StoppingChannelException(
    					"Exception while enlisting XAResource on Transaction");
    		}
    	} catch (Exception e) {
    		throw new StoppingChannelException(
    			"Exception while enlisting XAResource on Transaction", e);
    	}
    	return xaSession;
    }
    Now my question is whether it's possible to declaratively or programmatically create new transactions on top of the one created by JMSTemplate for each message?

    Surely the createSession enlists an XAResource on the current transaction, but if you make a new transaction with annotation @Transactional(propagation = Propagation.REQUIRES_NEW), the JMS session is not enlisted in that new transaction. While Hibernate automatically does this for you, JMS doesn't.

    Can I manually attach an XASession to the new transaction created within the transaction made by the JMSTemplate?

    Thanks for any help, it's greatly appreciated!

    Andreas
Working...
X