/** * */ package org.springmodules.jsr94; import java.rmi.RemoteException; import javax.rules.InvalidRuleSessionException; import javax.rules.StatefulRuleSession; import org.springmodules.jsr94.rulesource.RuleSource; import org.springframework.beans.factory.InitializingBean; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionException; import org.springframework.transaction.support.AbstractPlatformTransactionManager; import org.springframework.transaction.support.DefaultTransactionStatus; import org.springframework.transaction.support.TransactionSynchronizationManager; /** * Manages JSR94 transactions for stateful sessions. Stateless sessions do not need transaction * management at all. * * @author janm */ public class Jsr94TransactionManager extends AbstractPlatformTransactionManager implements InitializingBean { /** * The serialVersionUID */ private static final long serialVersionUID = 3905803076144084279L; /** * The ruleSource */ private RuleSource ruleSource; /** * Jsr94TransactionObject * * @author janm */ static class Jsr94TransactionObject { private StatefulRuleSession session; private boolean hasTransaction; /** * Gets the value of session * * @return Value of session. */ public final StatefulRuleSession getSession() { return session; } /** * Sets new value for field session * * @param session The session to set. */ public final void setSession(StatefulRuleSession session) { this.session = session; } /** * Gets the value of hasTransaction * * @return Value of hasTransaction. */ public final boolean hasTransaction() { return hasTransaction; } /** * Sets new value for field hasTransaction * * @param hasTransaction The hasTransaction to set. */ public final void setHasTransaction(boolean hasTransaction) { this.hasTransaction = hasTransaction; } } /** * Releases the session * * @throws TransactionException If the session cannot be released */ private void release() throws TransactionException { try { if (TransactionSynchronizationManager.hasResource(ruleSource)) { logger.debug("Releasing session"); StatefulRuleSession session = (StatefulRuleSession) TransactionSynchronizationManager.getResource(ruleSource); session.release(); logger.debug("Session released"); } } catch (InvalidRuleSessionException ex) { throw new Jsr94TransactionException(ex); } catch (RemoteException ex) { throw new Jsr94TransactionException(ex); } } /* (non-Javadoc) * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { if (ruleSource == null) throw new IllegalArgumentException("Must set ruleSource on " + getClass().getName()); } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doGetTransaction() */ protected Object doGetTransaction() throws TransactionException { Jsr94TransactionObject txObject = new Jsr94TransactionObject(); if (TransactionSynchronizationManager.hasResource(ruleSource)) { StatefulRuleSession session = (StatefulRuleSession) TransactionSynchronizationManager.getResource(ruleSource); if (logger.isDebugEnabled()) { logger.debug("Found thread-bound session [" + session + "] for Jsr94 Transaction"); } // set the existing session holder txObject.setSession(session); } return txObject; } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#isExistingTransaction(java.lang.Object) */ protected boolean isExistingTransaction(Object transaction) throws TransactionException { return ((Jsr94TransactionObject) transaction).hasTransaction(); } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doCleanupAfterCompletion(java.lang.Object) */ protected void doCleanupAfterCompletion(Object transaction) { Jsr94TransactionObject txObject = (Jsr94TransactionObject) transaction; TransactionSynchronizationManager.unbindResource(ruleSource); } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinition) */ protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException { Jsr94TransactionObject txObject = (Jsr94TransactionObject) transaction; logger.debug("Beginning transaction"); } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doCommit(org.springframework.transaction.support.DefaultTransactionStatus) */ protected void doCommit(DefaultTransactionStatus status) throws TransactionException { release(); logger.debug("Committed transaction (noop)"); } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus) */ protected void doRollback(DefaultTransactionStatus status) throws TransactionException { release(); logger.debug("Rolled back transaction (noop)"); } /** * Sets new value for field ruleSource * * @param ruleSource The ruleSource to set. */ public final void setRuleSource(RuleSource ruleSource) { this.ruleSource = ruleSource; } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doSuspend(java.lang.Object) */ protected Object doSuspend(Object transaction) throws TransactionException { return transaction; } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doResume(java.lang.Object, java.lang.Object) */ protected void doResume(Object transaction, Object arg1) throws TransactionException { // noop } /* (non-Javadoc) * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus) */ protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { // noop } }