Author: epbernard Date: 2006-03-11 13:17:43 -0500 (Sat, 11 Mar 2006) New Revision: 9601 Added: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransaction.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransactionFactory.java Modified: trunk/Hibernate3/src/org/hibernate/transaction/JTATransaction.java trunk/Hibernate3/src/org/hibernate/transaction/JTATransactionFactory.java trunk/HibernateExt/ejb/lib/ejb3-persistence.jar trunk/HibernateExt/ejb/lib/hibernate-annotations.jar trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/CurrentEntityManagerImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java trunk/HibernateExt/metadata/lib/ejb3-persistence.jar Log: EJB-125 EJB-145 Modified: trunk/Hibernate3/src/org/hibernate/transaction/JTATransaction.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/transaction/JTATransaction.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/Hibernate3/src/org/hibernate/transaction/JTATransaction.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -333,7 +333,7 @@ } } - /*package*/ UserTransaction getUserTransaction() { + protected UserTransaction getUserTransaction() { return ut; } } Modified: trunk/Hibernate3/src/org/hibernate/transaction/JTATransactionFactory.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/transaction/JTATransactionFactory.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/Hibernate3/src/org/hibernate/transaction/JTATransactionFactory.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -30,8 +30,8 @@ private static final Log log = LogFactory.getLog(JTATransactionFactory.class); private static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction"; - private InitialContext context; - private String utName; + protected InitialContext context; + protected String utName; public void configure(Properties props) throws HibernateException { try { Modified: trunk/HibernateExt/ejb/lib/ejb3-persistence.jar =================================================================== (Binary files differ) Modified: trunk/HibernateExt/ejb/lib/hibernate-annotations.jar =================================================================== (Binary files differ) Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -36,6 +36,7 @@ import org.hibernate.Session; import org.hibernate.StaleObjectStateException; import org.hibernate.UnresolvableObjectException; +import org.hibernate.ejb.transaction.JoinableJTATransaction; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionImplementor; import org.hibernate.proxy.HibernateProxy; @@ -47,58 +48,54 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManagerImplementor, Serializable { private static Log log = LogFactory.getLog( AbstractEntityManagerImpl.class ); - public static enum JoinStatus { - NOT_JOINED, - MARKED_FOR_JOINED, - JOINED - } - protected transient TransactionImpl tx = new TransactionImpl( this ); protected PersistenceContextType persistenceContextType; private FlushModeType flushMode = FlushModeType.AUTO; private PersistenceUnitTransactionType transactionType; - private JoinStatus joinStatus; protected AbstractEntityManagerImpl(PersistenceContextType type, PersistenceUnitTransactionType transactionType) { this.persistenceContextType = type; this.transactionType = transactionType; - if (PersistenceContextType.TRANSACTION == type) { + } - } + protected void postInit() { + //register in Sync if needed + getSession().getTransaction(); // joinable transaction needs to initialize if possible + getSession().isOpen(); //to register transaction } public Query createQuery(String ejbqlString) { - adjustFlushMode(); + //adjustFlushMode(); return new QueryImpl( getSession().createQuery( ejbqlString ), this ); } public Query createNamedQuery(String name) { - adjustFlushMode(); + //adjustFlushMode(); return new QueryImpl( getSession().getNamedQuery( name ), this ); } public Query createNativeQuery(String sqlString) { - adjustFlushMode(); + //adjustFlushMode(); SQLQuery q = getSession().createSQLQuery( sqlString ); return new QueryImpl( q, this ); } public Query createNativeQuery(String sqlString, Class resultClass) { - adjustFlushMode(); + //adjustFlushMode(); SQLQuery q = getSession().createSQLQuery( sqlString ); q.addEntity( "alias1", resultClass.getName(), LockMode.READ ); return new QueryImpl( q, this ); } public Query createNativeQuery(String sqlString, String resultSetMapping) { - adjustFlushMode(); + //adjustFlushMode(); SQLQuery q = getSession().createSQLQuery( sqlString ); q.setResultSetMapping( resultSetMapping ); return new QueryImpl( q, this ); } public <T> T getReference(Class<T> entityClass, Object primaryKey) { - adjustFlushMode(); + //adjustFlushMode(); try { T rtn = (T) getSession().load( entityClass, (Serializable) primaryKey ); return rtn; @@ -116,7 +113,7 @@ } public <A> A find(Class<A> entityClass, Object primaryKey) { - adjustFlushMode(); + //adjustFlushMode(); try { A rtn = (A) getSession().get( entityClass, (Serializable) primaryKey ); return rtn; @@ -144,7 +141,7 @@ public void persist(Object entity) { checkTransactionNeeded(); - adjustFlushMode(); + //adjustFlushMode(); try { getSession().persist( entity ); } @@ -155,7 +152,7 @@ public <A> A merge(A entity) { checkTransactionNeeded(); - adjustFlushMode(); + //adjustFlushMode(); try { return (A) getSession().merge( entity ); } @@ -172,7 +169,7 @@ public void remove(Object entity) { checkTransactionNeeded(); - adjustFlushMode(); + //adjustFlushMode(); try { getSession().delete( entity ); } @@ -183,7 +180,7 @@ public void refresh(Object entity) { checkTransactionNeeded(); - adjustFlushMode(); + //adjustFlushMode(); try { getSession().refresh( entity ); } @@ -211,7 +208,7 @@ public void flush() { if ( ! isTransactionInProgress() ) throw new TransactionRequiredException( "no transaction is in progress" ); - adjustFlushMode(); + //adjustFlushMode(); getSession().flush(); } @@ -238,7 +235,7 @@ } public void clear() { - adjustFlushMode(); + //adjustFlushMode(); getSession().clear(); } @@ -250,15 +247,15 @@ else if ( mode == FlushMode.COMMIT ) { this.flushMode = FlushModeType.COMMIT; } - else if ( mode == FlushMode.NEVER ) { - if ( PersistenceContextType.EXTENDED == persistenceContextType && !isTransactionInProgress() ) { - //we are in flushMode none for EXTENDED - return flushMode; - } - else { - return null; //TODO exception? - } - } +// else if ( mode == FlushMode.NEVER ) { +// if ( PersistenceContextType.EXTENDED == persistenceContextType && !isTransactionInProgress() ) { +// //we are in flushMode none for EXTENDED +// return flushMode; +// } +// else { +// return null; //TODO exception? +// } +// } else { return null; //TODO exception? } @@ -268,7 +265,7 @@ public void lock(Object entity, LockModeType lockMode) { if ( ! isTransactionInProgress() ) throw new TransactionRequiredException( "no transaction is in progress" ); - adjustFlushMode(); + //adjustFlushMode(); if ( !contains( entity ) ) throw new IllegalArgumentException( "entity not in the persistence context" ); getSession().lock( entity, getLockMode( lockMode ) ); @@ -288,7 +285,8 @@ /** * adjust the flush mode to match the no tx / no flush behavior */ - public void adjustFlushMode() { + //remove + private void adjustFlushMode() { Session session = getSession(); boolean isTransactionActive = isTransactionInProgress(); @@ -332,14 +330,20 @@ public void joinTransaction() { //set the joined status - if (joinStatus != JoinStatus.JOINED) { - joinStatus = JoinStatus.MARKED_FOR_JOINED; + if (transactionType == PersistenceUnitTransactionType.JTA) { final Session session = getSession(); - session.isOpen(); //attach hibernate core to the tx - + JoinableJTATransaction joinableJTATransaction = (JoinableJTATransaction) session.getTransaction(); + if (joinableJTATransaction.getStatus() == JoinableJTATransaction.JoinStatus.JOINED) return; //no-op + joinableJTATransaction.markForJoined(); + session.isOpen(); //register to the Tx + if (joinableJTATransaction.getStatus() == JoinableJTATransaction.JoinStatus.NOT_JOINED) { + throw new TransactionRequiredException( "No active JTA transaction on joinTransaction call" ); + } + else if (joinableJTATransaction.getStatus() == JoinableJTATransaction.JoinStatus.MARKED_FOR_JOINED) { + throw new AssertionFailure( "Transaction MARKED_FOR_JOINED after isOpen() call" ); + } //register the clear on rollback - if (joinStatus == JoinStatus.JOINED) { - session.getTransaction().registerSynchronization( new Synchronization() { + joinableJTATransaction.registerSynchronization( new Synchronization() { public void beforeCompletion() { } @@ -352,8 +356,8 @@ } } } - } ); - } + } + ); } } Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/CurrentEntityManagerImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/CurrentEntityManagerImpl.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/CurrentEntityManagerImpl.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -22,6 +22,7 @@ public CurrentEntityManagerImpl(SessionFactory sessionFactory, PersistenceUnitTransactionType transactionType) { super( PersistenceContextType.TRANSACTION, transactionType ); this.sessionFactory = sessionFactory; + postInit(); } public Session getSession() { Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/Ejb3Configuration.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -31,13 +31,11 @@ import javassist.bytecode.ClassFile; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.MappingException; import org.hibernate.SessionFactory; -import org.hibernate.AssertionFailure; -import org.hibernate.transaction.JTATransactionFactory; -import org.hibernate.transaction.JDBCTransactionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; @@ -49,12 +47,14 @@ import org.hibernate.ejb.packaging.JarVisitor; import org.hibernate.ejb.packaging.PersistenceMetadata; import org.hibernate.ejb.packaging.PersistenceXmlLoader; +import org.hibernate.ejb.transaction.JoinableJTATransactionFactory; import org.hibernate.ejb.util.LogHelper; import org.hibernate.engine.FilterDefinition; import org.hibernate.event.EventListeners; import org.hibernate.mapping.AuxiliaryDatabaseObject; import org.hibernate.mapping.PersistentClass; import org.hibernate.secure.JACCConfiguration; +import org.hibernate.transaction.JDBCTransactionFactory; import org.hibernate.util.CollectionHelper; import org.hibernate.util.ReflectHelper; import org.hibernate.util.StringHelper; @@ -674,7 +674,7 @@ ); boolean hasTxStrategy = StringHelper.isNotEmpty( preparedProperties.getProperty( Environment.TRANSACTION_STRATEGY ) ); if (! hasTxStrategy && transactionType == PersistenceUnitTransactionType.JTA) { - preparedProperties.setProperty( Environment.TRANSACTION_STRATEGY, JTATransactionFactory.class.getName() ); + preparedProperties.setProperty( Environment.TRANSACTION_STRATEGY, JoinableJTATransactionFactory.class.getName() ); } else if (! hasTxStrategy && transactionType == PersistenceUnitTransactionType.RESOURCE_LOCAL) { preparedProperties.setProperty( Environment.TRANSACTION_STRATEGY, JDBCTransactionFactory.class.getName() ); Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/EntityManagerImpl.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -28,6 +28,7 @@ this.sessionFactory = sessionFactory; this.open = true; this.discardOnClose = discardOnClose; + postInit(); } public Session getSession() { Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -1,10 +1,12 @@ //$Id$ package org.hibernate.ejb; +import javax.persistence.PersistenceException; + /** * @author Emmanuel Bernard */ public interface HibernateEntityManagerImplementor extends HibernateEntityManager { boolean isTransactionInProgress(); - void adjustFlushMode(); + public PersistenceException throwPersistenceException(PersistenceException e); } Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -23,7 +23,7 @@ */ public class QueryImpl implements Query, HibernateQuery { private org.hibernate.Query query; - private AbstractEntityManagerImpl em; + private HibernateEntityManagerImplementor em; public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) { this.query = query; Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -31,7 +31,7 @@ if ( tx != null && tx.isActive() ) { throw new IllegalStateException( "Transaction already active" ); } - entityManager.adjustFlushMode(); + //entityManager.adjustFlushMode(); tx = getSession().beginTransaction(); } @@ -60,7 +60,7 @@ rollbackOnly = false; } //if closed and we commit, the mode should have been adjusted already - if ( entityManager.isOpen() ) entityManager.adjustFlushMode(); + //if ( entityManager.isOpen() ) entityManager.adjustFlushMode(); } public void rollback() { @@ -76,7 +76,7 @@ finally { rollbackOnly = false; } - if ( entityManager.isOpen() ) entityManager.adjustFlushMode(); + //if ( entityManager.isOpen() ) entityManager.adjustFlushMode(); } public void setRollbackOnly() { Added: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransaction.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransaction.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransaction.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -0,0 +1,66 @@ +//$Id: $ +package org.hibernate.ejb.transaction; + +import javax.naming.InitialContext; +import javax.transaction.SystemException; + +import org.hibernate.HibernateException; +import org.hibernate.TransactionException; +import org.hibernate.jdbc.JDBCContext; +import org.hibernate.transaction.JTATransaction; +import org.hibernate.transaction.TransactionFactory; +import org.hibernate.util.JTAHelper; + +/** + * Implements a joinable transaction. Until the transaction is marked for joined, the TM.isTransactionInProgress() + * must return false + * If a + * @author Emmanuel Bernard + */ +public class JoinableJTATransaction extends JTATransaction { + private JoinStatus status; + public JoinableJTATransaction( + InitialContext context, String utName, JDBCContext jdbcContext, + TransactionFactory.Context transactionContext + ) { + super( context, utName, jdbcContext, transactionContext ); + status = JoinStatus.MARKED_FOR_JOINED; + tryJoiningTransaction(); + } + + void tryJoiningTransaction() { + if (status == JoinStatus.MARKED_FOR_JOINED) { + try { + if ( getUserTransaction() != null && JTAHelper.isInProgress( getUserTransaction().getStatus() ) ) { + status = JoinStatus.JOINED; + } + else { + status = JoinStatus.NOT_JOINED; + } + } + catch( SystemException se ) { + throw new TransactionException( "Unable to check transaction status", se ); + } + } + } + + @Override + public void begin() throws HibernateException { + super.begin(); + status = JoinStatus.JOINED; + } + + public JoinStatus getStatus() { + return status; + } + + public void markForJoined() { + if (status != JoinStatus.JOINED) status = JoinStatus.MARKED_FOR_JOINED; + } + + public static enum JoinStatus { + NOT_JOINED, + MARKED_FOR_JOINED, + JOINED + } +} Added: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransactionFactory.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransactionFactory.java 2006-03-11 14:34:56 UTC (rev 9600) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/transaction/JoinableJTATransactionFactory.java 2006-03-11 18:17:43 UTC (rev 9601) @@ -0,0 +1,30 @@ +//$Id: $ +package org.hibernate.ejb.transaction; + +import org.hibernate.HibernateException; +import org.hibernate.Transaction; +import org.hibernate.jdbc.JDBCContext; +import org.hibernate.transaction.JTATransactionFactory; + +/** + * A transaction is in progress if the underlying JTA tx is in progress and if the Tx is marked as + * MARKED_FOR_JOINED + * + * @author Emmanuel Bernard + */ +public class JoinableJTATransactionFactory extends JTATransactionFactory { + public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext) + throws HibernateException { + return new JoinableJTATransaction(context, utName, jdbcContext, transactionContext); + } + + @Override + public boolean isTransactionInProgress( + JDBCContext jdbcContext, Context transactionContext, Transaction transaction + ) { + if (transaction == null) return false; //should not happen though + JoinableJTATransaction joinableJTATransaction = ( (JoinableJTATransaction) transaction ); + joinableJTATransaction.tryJoiningTransaction(); + return joinableJTATransaction.getStatus() == JoinableJTATransaction.JoinStatus.JOINED; + } +} Modified: trunk/HibernateExt/metadata/lib/ejb3-persistence.jar =================================================================== (Binary files differ) |