Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/JtaPropertyConfigReaderCmd.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/JtaPropertyConfigReaderCmd.java (revision 0) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/JtaPropertyConfigReaderCmd.java (revision 0) @@ -0,0 +1,58 @@ +package org.jbpm.pvm.internal.tx; + +import java.util.Properties; + +import org.hibernate.cfg.Configuration; +import org.jbpm.api.cmd.Command; +import org.jbpm.api.cmd.Environment; +import org.jbpm.internal.log.Log; + +/** + * @author Martin Porter + */ +public class JtaPropertyConfigReaderCmd implements Command { + + private static Log log = Log.getLog(JtaPropertyConfigReaderCmd.class.getName()); + + private static final long serialVersionUID = 1L; + public static final String JTA_TRANSACTION_MANAGER_PROP_NAME = "hibernate.transaction.manager_lookup_class"; + public static final String USER_TRANSACTION_PROP_NAME = "jta.UserTransaction"; + + public JtaPropertyConfigReaderCmd() { } + + public Properties execute(Environment environment) + throws Exception { + + if (log.isDebugEnabled()) log.debug("Getting Hibernate Configuration.."); + Configuration configuration = environment.get(Configuration.class); + if (configuration == null) { + throw new RuntimeException( + "Failed to get Hibernate Configuration from jBPM Environment !"); + } + + if (log.isDebugEnabled()) log.debug("Looking For Hibernate Property [" + + JTA_TRANSACTION_MANAGER_PROP_NAME + "]"); + String jtaTansactionManager = configuration + .getProperty(JTA_TRANSACTION_MANAGER_PROP_NAME); + + if (log.isDebugEnabled()) log.debug("Looking For Hibernate Property [" + + USER_TRANSACTION_PROP_NAME + "]"); + String userTransaction = configuration.getProperty(USER_TRANSACTION_PROP_NAME); + + Properties props = new Properties(); + if (jtaTansactionManager != null && jtaTansactionManager.length() > 0) { + if (log.isDebugEnabled()) log.debug("Got JTA Transaction Manager [" + + JTA_TRANSACTION_MANAGER_PROP_NAME + + "] From Hibernate Configuration - Value [" + jtaTansactionManager + "]"); + props.put(JTA_TRANSACTION_MANAGER_PROP_NAME, jtaTansactionManager); + } + if (userTransaction != null && userTransaction.length() > 0) { + if (log.isDebugEnabled()) log.debug("Got User Transaction [" + + USER_TRANSACTION_PROP_NAME + + "] From Hibernate Configuration - Value [" + userTransaction + "]"); + props.put(USER_TRANSACTION_PROP_NAME, userTransaction); + } + if (log.isDebugEnabled()) log.debug("Returning [" + props.size() + "] JTA Properties"); + return props; + } +} \ No newline at end of file Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/JtaTransaction.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/JtaTransaction.java (revision 6382) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/tx/JtaTransaction.java (working copy) @@ -21,6 +21,8 @@ */ package org.jbpm.pvm.internal.tx; +import java.util.Properties; + import javax.naming.InitialContext; import javax.transaction.Status; import javax.transaction.Synchronization; @@ -28,28 +30,34 @@ import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; +import org.hibernate.transaction.TransactionManagerLookupFactory; import org.jbpm.api.JbpmException; import org.jbpm.internal.log.Log; +import org.jbpm.pvm.internal.cmd.CommandService; +import org.jbpm.pvm.internal.env.EnvironmentImpl; - /** * @author Tom Baeyens + * @author Martin Porter */ public class JtaTransaction extends AbstractTransaction implements Transaction { - + private static Log log = Log.getLog(JtaTransaction.class.getName()); - + public static final String JNDINAME_USERTRANSACTION_JBOSS_GLOBAL = "UserTransaction"; public static final String JNDINAME_TRANSACTIONMANAGER_JBOSS_GLOBAL = "java:/TransactionManager"; + protected boolean configurationChecked = false; + protected TransactionManager transactionManager = null; protected String userTransactionJndiName = JNDINAME_USERTRANSACTION_JBOSS_GLOBAL; protected String transactionManagerJndiName = JNDINAME_TRANSACTIONMANAGER_JBOSS_GLOBAL; public boolean isRollbackOnly() { try { - return lookupJeeUserTransaction().getStatus()==Status.STATUS_MARKED_ROLLBACK; + return lookupJeeUserTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK; } catch (SystemException e) { - throw new JbpmException("couldn't get status of user transaction: "+e.getMessage(), e); + throw new JbpmException("couldn't get status of user transaction: " + + e.getMessage(), e); } } @@ -57,7 +65,9 @@ try { lookupJeeUserTransaction().setRollbackOnly(); } catch (Exception e) { - throw new JbpmException("couldn't set user transaction to rollback only: "+e.getMessage(), e); + throw new JbpmException( + "couldn't set user transaction to rollback only: " + + e.getMessage(), e); } } @@ -65,55 +75,59 @@ try { lookupJeeTransaction().registerSynchronization(synchronization); } catch (Exception e) { - throw new JbpmException("couldn't register synchronization: "+e.getMessage(), e); + throw new JbpmException("couldn't register synchronization: " + + e.getMessage(), e); } } - + public void begin() { try { lookupJeeUserTransaction().begin(); } catch (Exception e) { - throw new JbpmException("couldn't begin transaction: "+e.getMessage(), e); + throw new JbpmException("couldn't begin transaction: " + + e.getMessage(), e); } } - + public void rollback() { try { lookupJeeUserTransaction().rollback(); } catch (Exception e) { - throw new JbpmException("couldn't rollback: "+e.getMessage(), e); + throw new JbpmException("couldn't rollback: " + e.getMessage(), e); } } - + public void commit() { try { flushDeserializedObjects(); lookupJeeUserTransaction().commit(); } catch (Exception e) { - throw new JbpmException("couldn't commit: "+e.getMessage(), e); + throw new JbpmException("couldn't commit: " + e.getMessage(), e); } } - + public javax.transaction.Transaction suspend() { try { return lookupJeeTransactionManager().suspend(); } catch (Exception e) { - throw new JbpmException("couldn't suspend: "+e.getMessage(), e); + throw new JbpmException("couldn't suspend: " + e.getMessage(), e); } } - + public void resume(javax.transaction.Transaction transaction) { try { lookupJeeTransactionManager().resume(transaction); } catch (Exception e) { - throw new JbpmException("couldn't resume: "+e.getMessage(), e); + throw new JbpmException("couldn't resume: " + e.getMessage(), e); } } - - // lookups ////////////////////////////////////////////////////////////////// - + + // lookups + // ////////////////////////////////////////////////////////////////// + public UserTransaction lookupJeeUserTransaction() { + checkJTAHibernateConfiguration(); return (UserTransaction) lookupFromJndi(userTransactionJndiName); } @@ -122,31 +136,137 @@ TransactionManager transactionManager = lookupJeeTransactionManager(); return transactionManager.getTransaction(); } catch (Exception e) { - throw new JbpmException("couldn't get transaction from transaction manager "+transactionManagerJndiName+": "+e.getMessage(), e); + throw new JbpmException( + "couldn't get transaction from transaction manager " + + transactionManagerJndiName + ": " + + e.getMessage(), e); } } public TransactionManager lookupJeeTransactionManager() { - return (TransactionManager) lookupFromJndi(transactionManagerJndiName); + + /** + * If there is a TransactionMaanger class it has been specified in the + * Hibernate Properties then use this. Otherwise default to look for it + * in JNDI. + */ + checkJTAHibernateConfiguration(); + if (transactionManager == null) { + if (log.isDebugEnabled()) log.debug("Returning Transaction Manager From JNDI..."); + return (TransactionManager) lookupFromJndi(transactionManagerJndiName); + } else { + if (log.isDebugEnabled()) log.debug("Returning Transaction Manager [" + + transactionManager.getClass().getName() + "]"); + return transactionManager; + } } - - public static Object lookupFromJndi(String jndiName) { + + public Object lookupFromJndi(String jndiName) { + + InitialContext initialContext = null; + Object lookupObject = null; + try { - InitialContext initialContext = new InitialContext(); - return initialContext.lookup(jndiName); - } catch (Exception e) { - throw new JbpmException("couldn't lookup '"+jndiName+"' from jndi: "+e.getMessage()+": "+e.getMessage(), e); + checkJTAHibernateConfiguration(); + initialContext = new InitialContext(); + if (log.isDebugEnabled()) log.debug("Looking Up In JNDI [" + jndiName + "]"); + lookupObject = initialContext.lookup(jndiName); + return lookupObject; } + + catch (Exception e) { + throw new JbpmException("couldn't lookup '" + jndiName + + "' from jndi: " + e.getMessage() + ": " + e.getMessage(), + e); + } + + finally { + if (initialContext != null) { + try { + initialContext.close(); + } catch (Exception e) { + } + } + } } - + public static int getUserTransactionStatus(UserTransaction userTransaction) { int status = -1; try { status = userTransaction.getStatus(); } catch (SystemException e) { - throw new JbpmException("couldn't get transaction status: "+e.getMessage(), e); + throw new JbpmException("couldn't get transaction status: " + + e.getMessage(), e); } - log.trace("jta transaction status: "+JtaStatusHelper.toString(status)); + log.trace("jta transaction status: " + JtaStatusHelper.toString(status)); return status; } + + /* + * Reads the JTA Configuration from the Hibernate Config. + */ + private final void checkJTAHibernateConfiguration() { + + try { + if (!configurationChecked) { + if (log.isDebugEnabled()) log.debug("Checking Hibernate JTA Configuration"); + CommandService commandService = EnvironmentImpl.getFromCurrent(CommandService.class); + if (commandService == null) { + throw new RuntimeException("Failed to get Command Service !"); + } + + if (log.isDebugEnabled()) log.debug("Executing Command to Retrieve JTA Configuration"); + Properties props = commandService.execute(new JtaPropertyConfigReaderCmd()); + + if (props.containsKey(JtaPropertyConfigReaderCmd.USER_TRANSACTION_PROP_NAME)) { + userTransactionJndiName = (String) props + .get(JtaPropertyConfigReaderCmd.USER_TRANSACTION_PROP_NAME); + if (log.isDebugEnabled()) log.debug("Set User Transaction To [" + userTransactionJndiName + "]"); + } + else { + if (log.isDebugEnabled()) log.debug("User Transaction Hibernate Configuration Not Found For [" + JtaPropertyConfigReaderCmd.USER_TRANSACTION_PROP_NAME + "] Using JBoss Default"); + userTransactionJndiName = JNDINAME_USERTRANSACTION_JBOSS_GLOBAL; + } + + if (props.containsKey(JtaPropertyConfigReaderCmd.JTA_TRANSACTION_MANAGER_PROP_NAME)) { + String transactionManagerClassName = (String) props + .get(JtaPropertyConfigReaderCmd.JTA_TRANSACTION_MANAGER_PROP_NAME); + try { + if (log.isDebugEnabled()) log.debug("Getting Instance Of [" + TransactionManager.class.getName() + "] From Factory"); + transactionManager = TransactionManagerLookupFactory.getTransactionManager(props); + if (transactionManager == null) { + log.error("Failed to get [" + TransactionManager.class.getName() + "] From Factory"); + throw new RuntimeException("Failed to create instance of [" + TransactionManager.class.getName() + "]"); + } + if (log.isDebugEnabled()) log.debug("Got Instance Of [" + transactionManager.getClass().getName() + "]"); + } + + catch (Exception e) { + log.error("Failed to create Transaction Manager [" + + transactionManagerClassName + + "] - " + e); + throw new RuntimeException( + "Failed to create Transaction Manager [" + + transactionManagerClassName + + "] - " + e); + } + } + else { + if (log.isDebugEnabled()) log.debug("Transaction Manager Hibernate Configuration Not Found For [" + JtaPropertyConfigReaderCmd.JTA_TRANSACTION_MANAGER_PROP_NAME + "] Using JBoss Default"); + transactionManagerJndiName = JNDINAME_TRANSACTIONMANAGER_JBOSS_GLOBAL; + } + + log.debug("User Transaction JNDI Name = [" + userTransactionJndiName + "]"); + log.debug("Transaction Manager JNDI Name = [" + transactionManagerJndiName + "]"); + log.debug("Transaction Manager = [" + transactionManager + "]"); + configurationChecked = true; + } + } + + catch (Exception e) { + log.error("Unable to Get JTA Configuration - Configuration will NOT be checked again !"); + e.printStackTrace(); + configurationChecked = true; + } + } }