package org.jboss.seam.ioc.spring; import org.jboss.seam.ScopeType; import org.jboss.seam.contexts.Lifecycle; import org.jboss.seam.log.LogProvider; import org.jboss.seam.log.Logging; import org.springframework.transaction.support.TransactionSynchronizationAdapter; import org.springframework.transaction.support.TransactionSynchronizationManager; /** * Utility Class for managing a spring Transactional Seam lifecycle * * @author Mike Youngstrom * */ public class SeamLifecycleUtils { private static final LogProvider log = Logging.getLogProvider(SeamLifecycleUtils.class); /** * Ensure Seam lifecycle Synchronization happens last */ public static final int SEAM_LIFECYCLE_SYNCHRONIZATION_ORDER = Integer.MAX_VALUE; /** * Starts a Seam Call if one is not available and if executing within a Spring * Transaction. */ public static void beginTransactionalSeamCall() { if (ScopeType.APPLICATION.isContextActive()) { log.debug("Application available. Won't start a new call"); return; } if (TransactionSynchronizationManager.isSynchronizationActive()) { TransactionSynchronizationManager .registerSynchronization(new SeamLifecycleSynchronization()); log.debug("Beginning Transactional Seam Call"); Lifecycle.beginCall(); return; } throw new IllegalStateException( "Seam application context not available and cannot be started. " + "Seam Managed Persistence Context not available. " + "Try placing the spring bean call inside of a spring transaction or try making the spring bean " + "a Seam Component using <seam:component/>."); } /** * Callback for resource cleanup at the end of a transaction where a Seam * Lifecycle was created. * * @see org.springframework.transaction.jta.JtaTransactionManager */ private static class SeamLifecycleSynchronization extends TransactionSynchronizationAdapter { @Override public int getOrder() { return SEAM_LIFECYCLE_SYNCHRONIZATION_ORDER; } @Override public void afterCompletion(int status) { //Close the seam call we started if it is still active. if(ScopeType.APPLICATION.isContextActive()) { log.debug("Ending Transactional Seam Call"); Lifecycle.endCall(); } else { log.warn("Spring started a transactional Seam call but somebody else closed before it before the transaction committed."); } } } }