Author: epbernard Date: 2006-03-08 17:41:38 -0500 (Wed, 08 Mar 2006) New Revision: 9578 Added: trunk/HibernateExt/ejb-api/src/javax/persistence/EntityExistsException.java trunk/HibernateExt/ejb-api/src/javax/persistence/RollbackException.java Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/EntityManager.java trunk/HibernateExt/ejb-api/src/javax/persistence/EntityNotFoundException.java trunk/HibernateExt/ejb-api/src/javax/persistence/EntityTransaction.java trunk/HibernateExt/ejb-api/src/javax/persistence/NoResultException.java trunk/HibernateExt/ejb-api/src/javax/persistence/NonUniqueResultException.java trunk/HibernateExt/ejb-api/src/javax/persistence/TransactionRequiredException.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/Book.java trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/FlushAndTransactionTest.java Log: EJB-138 EJB-90 Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -12,10 +12,15 @@ import javax.persistence.EntityTransaction; import javax.persistence.FlushModeType; import javax.persistence.LockModeType; +import javax.persistence.NoResultException; +import javax.persistence.NonUniqueResultException; import javax.persistence.PersistenceContextType; +import javax.persistence.PersistenceException; import javax.persistence.Query; import javax.persistence.TransactionRequiredException; import javax.persistence.spi.PersistenceUnitTransactionType; +import javax.transaction.SystemException; +import javax.transaction.TransactionManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,12 +34,13 @@ import org.hibernate.Session; import org.hibernate.StaleObjectStateException; import org.hibernate.UnresolvableObjectException; +import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionImplementor; import org.hibernate.proxy.HibernateProxy; /** * @author <a href="mailto:ga...@hi...">Gavin King</a> - * @version $Revision$ + * @author Emmanuel Bernard */ public abstract class AbstractEntityManagerImpl implements HibernateEntityManagerImplementor, Serializable { private static Log log = LogFactory.getLog( AbstractEntityManagerImpl.class ); @@ -51,32 +57,32 @@ public Query createQuery(String ejbqlString) { adjustFlushMode(); - return new QueryImpl( getSession().createQuery( ejbqlString ) ); + return new QueryImpl( getSession().createQuery( ejbqlString ), this ); } public Query createNamedQuery(String name) { adjustFlushMode(); - return new QueryImpl( getSession().getNamedQuery( name ) ); + return new QueryImpl( getSession().getNamedQuery( name ), this ); } public Query createNativeQuery(String sqlString) { adjustFlushMode(); SQLQuery q = getSession().createSQLQuery( sqlString ); - return new QueryImpl( q ); + return new QueryImpl( q, this ); } public Query createNativeQuery(String sqlString, Class resultClass) { adjustFlushMode(); SQLQuery q = getSession().createSQLQuery( sqlString ); q.addEntity( "alias1", resultClass.getName(), LockMode.READ ); - return new QueryImpl( q ); + return new QueryImpl( q, this ); } public Query createNativeQuery(String sqlString, String resultSetMapping) { adjustFlushMode(); SQLQuery q = getSession().createSQLQuery( sqlString ); q.setResultSetMapping( resultSetMapping ); - return new QueryImpl( q ); + return new QueryImpl( q, this ); } public <T> T getReference(Class<T> entityClass, Object primaryKey) { @@ -86,7 +92,8 @@ return rtn; } catch (ObjectNotFoundException e) { - throw new EntityNotFoundException( e.getMessage(), e ); + throwPersistenceException( new EntityNotFoundException( e.getMessage(), e ) ); + return null; //for the compiler to stop complaining } catch (MappingException e) { throw new IllegalArgumentException( e.getMessage(), e ); @@ -115,8 +122,11 @@ } private void checkTransactionNeeded() { - if ( ! isTransactionInProgress() && persistenceContextType == PersistenceContextType.TRANSACTION ) { - throw new TransactionRequiredException( "no transaction is in progress for a TRANSACTION type persistence context" ); + if ( persistenceContextType == PersistenceContextType.TRANSACTION && ! isTransactionInProgress() ) { + //no need to mark as rollback, no tx in progress + throw new TransactionRequiredException( + "no transaction is in progress for a TRANSACTION type persistence context" + ); } } @@ -166,7 +176,7 @@ getSession().refresh( entity ); } catch (UnresolvableObjectException uoe) { - throw new EntityNotFoundException( uoe ); + throwPersistenceException( new EntityNotFoundException( uoe ) ); } catch (MappingException e) { throw new IllegalArgumentException( e.getMessage(), e ); @@ -174,9 +184,6 @@ } public boolean contains(Object entity) { - //TODO: needed for spec compliance, but inconvenient - // for testing of EM lifecycle - //checkTransactionActive(); try { if ( entity != null && ! ( entity instanceof HibernateProxy ) @@ -191,7 +198,7 @@ } public void flush() { - if (! isTransactionInProgress() ) throw new TransactionRequiredException("no transaction is in progress"); + if ( ! isTransactionInProgress() ) throw new TransactionRequiredException( "no transaction is in progress" ); adjustFlushMode(); getSession().flush(); } @@ -215,7 +222,7 @@ getSession().setFlushMode( FlushMode.COMMIT ); } else { - throw new AssertionFailure("Unknown FlushModeType: " + flushMode); + throw new AssertionFailure( "Unknown FlushModeType: " + flushMode ); } } @@ -226,13 +233,13 @@ public FlushModeType getFlushMode() { FlushMode mode = getSession().getFlushMode(); - if (mode == FlushMode.AUTO) { + if ( mode == FlushMode.AUTO ) { this.flushMode = FlushModeType.AUTO; } - else if (mode == FlushMode.COMMIT) { + else if ( mode == FlushMode.COMMIT ) { this.flushMode = FlushModeType.COMMIT; } - else if (mode == FlushMode.NEVER) { + else if ( mode == FlushMode.NEVER ) { if ( PersistenceContextType.EXTENDED == persistenceContextType && !getTransaction().isActive() ) { //we are in flushMode none for EXTENDED return flushMode; @@ -249,26 +256,28 @@ } public void lock(Object entity, LockModeType lockMode) { - if (! isTransactionInProgress() ) throw new TransactionRequiredException("no transaction is in progress"); + if ( ! isTransactionInProgress() ) throw new TransactionRequiredException( "no transaction is in progress" ); adjustFlushMode(); if ( !contains( entity ) ) throw new IllegalArgumentException( "entity not in the persistence context" ); - getSession().lock( entity, getLockMode(lockMode) ); - + getSession().lock( entity, getLockMode( lockMode ) ); + } private LockMode getLockMode(LockModeType lockMode) { - switch (lockMode) { + switch ( lockMode ) { case READ: return LockMode.UPGRADE; //assuming we are on read-commited and we need to prevent non repeteable read case WRITE: - log.warn( "LockModeType.WRITE does not increment the version number"); + log.warn( "LockModeType.WRITE does not increment the version number" ); return LockMode.UPGRADE; default: - throw new AssertionFailure( "Unknown LockModeType: " + lockMode); + throw new AssertionFailure( "Unknown LockModeType: " + lockMode ); } } - /** adjust the flush mode to match the no tx / no flush behavior */ + /** + * adjust the flush mode to match the no tx / no flush behavior + */ public void adjustFlushMode() { Session session = getSession(); @@ -288,6 +297,40 @@ return ( (SessionImplementor) getSession() ).isTransactionInProgress(); } + protected void markAsRollback() { + if ( tx.isActive() ) { + tx.setRollbackOnly(); + } + else { + if ( PersistenceUnitTransactionType.JTA == transactionType ) { + TransactionManager transactionManager = + ( (SessionFactoryImplementor) getSession().getSessionFactory() ).getTransactionManager(); + if ( transactionManager == null ) { + throw new PersistenceException( + "Using a JTA persistence context wo setting hibernate.transaction.manager_lookup_class" + ); + } + try { + transactionManager.setRollbackOnly(); + } + catch (SystemException e) { + throw new PersistenceException( "Unable to set the JTA transaction as RollbackOnly", e ); + } + } + } + } + + public void joinTransaction() { + + } + + /** + * returns the session + */ + public Object getDelegate() { + return getSession(); + }; + private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); } @@ -296,4 +339,9 @@ ois.defaultReadObject(); tx = new TransactionImpl( this ); } + + public PersistenceException throwPersistenceException(PersistenceException e) { + if ( ! ( e instanceof NoResultException || ( e instanceof NonUniqueResultException ) ) ) markAsRollback(); + throw e; + } } Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/QueryImpl.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -9,6 +9,7 @@ import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TemporalType; +import javax.persistence.TransactionRequiredException; import static javax.persistence.TemporalType.*; import org.hibernate.CacheMode; @@ -22,9 +23,11 @@ */ public class QueryImpl implements Query, HibernateQuery { private org.hibernate.Query query; + private AbstractEntityManagerImpl em; - public QueryImpl(org.hibernate.Query query) { + public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) { this.query = query; + this.em = em; } public org.hibernate.Query getHibernateQuery() { @@ -32,6 +35,9 @@ } public int executeUpdate() { + if ( ! em.isTransactionInProgress() ) { + throw em.throwPersistenceException( new TransactionRequiredException("Executing an update/delete query") ); + } return query.executeUpdate(); } @@ -44,13 +50,14 @@ Object result = query.uniqueResult(); if ( result == null ) { - throw new NoResultException( "No entity found for query" ); + em.throwPersistenceException( new NoResultException( "No entity found for query" ) ); } return result; } catch (NonUniqueResultException e) { - throw new javax.persistence.NonUniqueResultException( e.getMessage() ); + em.throwPersistenceException( new javax.persistence.NonUniqueResultException( e.getMessage() ) ); + return null; //for the compiler to stop complaining } } Modified: trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java =================================================================== --- trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb/src/java/org/hibernate/ejb/TransactionImpl.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -3,6 +3,7 @@ import javax.persistence.EntityTransaction; import javax.persistence.PersistenceException; +import javax.persistence.RollbackException; import org.hibernate.Session; import org.hibernate.Transaction; @@ -14,6 +15,7 @@ private AbstractEntityManagerImpl entityManager; private Transaction tx; + private boolean rollbackOnly; public TransactionImpl(AbstractEntityManagerImpl entityManager) { this.entityManager = entityManager; @@ -24,6 +26,7 @@ } public void begin() { + rollbackOnly = false; if ( tx != null && tx.isActive() ) { throw new IllegalStateException( "Transaction already active" ); } @@ -35,7 +38,17 @@ if ( tx == null || !tx.isActive() ) { throw new IllegalStateException( "Transaction not active" ); } - tx.commit(); + if (rollbackOnly) { + tx.rollback(); + throw new RollbackException("Transaction marked as rollbackOnly"); + } + try { + tx.commit(); + } + catch (Exception e) { + throw new RollbackException( "Error while commiting the transaction", e); + } + rollbackOnly = false; //if closed and we commit, the mode should have been adjusted already if ( entityManager.isOpen() ) entityManager.adjustFlushMode(); } @@ -46,13 +59,23 @@ } try { tx.rollback(); - entityManager.adjustFlushMode(); } catch (RuntimeException e) { throw new PersistenceException("unexpected error when rollbacking", e); } + entityManager.adjustFlushMode(); } + public void setRollbackOnly() { + if ( ! isActive() ) throw new IllegalStateException( "Transaction not active" ); + this.rollbackOnly = true; + } + + public boolean getRollbackOnly() { + if ( ! isActive() ) throw new IllegalStateException( "Transaction not active" ); + return rollbackOnly; + } + public boolean isActive() { try { return tx != null && tx.isActive(); Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/Book.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/Book.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/Book.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -13,6 +13,21 @@ public class Book { @Id @GeneratedValue(strategy= GenerationType.TABLE) public Integer id; + public String name; - public String name; + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } Modified: trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/FlushAndTransactionTest.java =================================================================== --- trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/FlushAndTransactionTest.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb/src/test/org/hibernate/ejb/test/transaction/FlushAndTransactionTest.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -5,6 +5,8 @@ import javax.persistence.LockModeType; import javax.persistence.PersistenceContextType; import javax.persistence.TransactionRequiredException; +import javax.persistence.EntityNotFoundException; +import javax.persistence.RollbackException; import org.hibernate.ejb.test.TestCase; import org.hibernate.ejb.HibernateEntityManagerFactory; @@ -180,6 +182,29 @@ em.close(); } + public void testRollbackOnlyOnPersistenceException() throws Exception { + Book book = new Book(); + book.name = "Stolen keys"; + book.id = new Integer( 50 ); + EntityManager em = factory.createEntityManager(); + em.getTransaction().begin(); + try { + em.refresh( book ); + fail("Get reference on wrong entity should fail"); + } + catch (EntityNotFoundException e) { + //success + } + try { + em.getTransaction().commit(); + fail("Commit should be rollbacked"); + } + catch (RollbackException e) { + //success + } + + } + public Class[] getAnnotatedClasses() { return new Class[] { Book.class Added: trunk/HibernateExt/ejb-api/src/javax/persistence/EntityExistsException.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/EntityExistsException.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/EntityExistsException.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -0,0 +1,23 @@ +//$Id: $ +package javax.persistence; + +/** + * @author Emmanuel Bernard + */ +public class EntityExistsException extends PersistenceException { + public EntityExistsException() { + super(); + } + + public EntityExistsException(Throwable cause) { + super( cause ); + } + + public EntityExistsException(String message) { + super( message ); + } + + public EntityExistsException(String message, Throwable cause) { + super( message, cause ); + } +} Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/EntityManager.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/EntityManager.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/EntityManager.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -9,11 +9,16 @@ * Make an instance managed and persistent. * * @param entity + * @throws EntityExistsException if the entity already exists. + * (The EntityExistsException may be thrown when the persist + * operation is invoked, or the EntityExistsException or + * another PersistenceException may be thrown at commit + * time.) * @throws IllegalArgumentException if not an entity - * or entity is detached - * @throws TransactionRequiredException if there is - * no transaction and the persistence context is - * of type PersistenceContextType.TRANSACTION + * @throws TransactionRequiredException if invoked on a + * container-managed entity manager of type + * PersistenceContextType.TRANSACTION and there is + * no transaction. */ public void persist(Object entity); @@ -25,9 +30,10 @@ * @return the instance that the state was merged to * @throws IllegalArgumentException if instance is not an * entity or is a removed entity - * @throws TransactionRequiredException if there is - * no transaction and the persistence context is - * of type PersistenceContextType.TRANSACTION + * @throws TransactionRequiredException if invoked on a + * container-managed entity manager of type + * PersistenceContextType.TRANSACTION and there is + * no transaction. */ public <T> T merge(T entity); @@ -37,9 +43,10 @@ * @param entity * @throws IllegalArgumentException if not an entity * or if a detached entity - * @throws TransactionRequiredException if there is - * no transaction and the persistence context is - * of type PersistenceContextType.TRANSACTION + * @throws TransactionRequiredException if invoked on a + * container-managed entity manager of type + * PersistenceContextType.TRANSACTION and there is + * no transaction. */ public void remove(Object entity); @@ -58,13 +65,10 @@ public <T> T find(Class<T> entityClass, Object primaryKey); /** - * EntityManager Enterprise JavaBeans 3.0, Proposed Final Draft Entity Operations - * 39 12/19/05 - * Sun Microsystems, Inc. * Get an instance, whose state may be lazily fetched. * If the requested instance does not exist in the database, - * throws EntityNotFoundException when the instance state is - * first accessed. (The persistence provider runtime is + * the EntityNotFoundException is thrown when the instance + * state is first accessed. (The persistence provider runtime is * permitted to throw the EntityNotFoundException when * getReference is called.) * The application should not expect that the instance state will @@ -131,9 +135,10 @@ * @param entity * @throws IllegalArgumentException if not an entity * or entity is not managed - * @throws TransactionRequiredException if there is - * no transaction and the persistence context is - * of type PersistenceContextType.TRANSACTION + * @throws TransactionRequiredException if invoked on a + * container-managed entity manager of type + * PersistenceContextType.TRANSACTION and there is + * no transaction. * @throws EntityNotFoundException if the entity no longer * exists in the database */ @@ -208,6 +213,18 @@ public Query createNativeQuery(String sqlString, String resultSetMapping); /** + * Indicate to the EntityManager that a JTA transaction is + * active. This method should be called on a JTA application + * managed EntityManager that was created outside the scope + * of the active transaction to associate it with the current + * JTA transaction. + * + * @throws TransactionRequiredException if there is + * no transaction. + */ + public void joinTransaction(); + + /** * Close an application-managed EntityManager. * After an EntityManager has been closed, all methods on the * EntityManager instance will throw the IllegalStateException @@ -232,9 +249,10 @@ * Return the resource-level transaction object. * The EntityTransaction instance may be used serially to * begin and commit multiple transactions. + * * @return EntityTransaction instance * @throws IllegalStateException if invoked on a JTA - * EntityManager or an EntityManager that has been closed. + * EntityManager or an EntityManager that has been closed. */ public EntityTransaction getTransaction(); } \ No newline at end of file Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/EntityNotFoundException.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/EntityNotFoundException.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/EntityNotFoundException.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -4,7 +4,7 @@ /** * @author Gavin King */ -public class EntityNotFoundException extends RuntimeException { +public class EntityNotFoundException extends PersistenceException { public EntityNotFoundException() { super(); Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/EntityTransaction.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/EntityTransaction.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/EntityTransaction.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -14,7 +14,7 @@ * changes to the database. * * @throws IllegalStateException if isActive() is false. - * @throws PersistenceException if the commit fails. + * @throws RollbackException if the commit fails. */ public void commit(); @@ -28,10 +28,26 @@ public void rollback(); /** + * Mark the current transaction so that the only possible + * outcome of the transaction is for the transaction to be + * rolled back. + * + * @throws IllegalStateException if isActive() is false. + */ + public void setRollbackOnly(); + + /** + * Determine whether the current transaction has been marked + * for rollback. + * + * @throws IllegalStateException if isActive() is false. + */ + public boolean getRollbackOnly(); + + /** * Indicate whether a transaction is in progress. - * * @throws PersistenceException if an unexpected error - * condition is encountered. + * condition is encountered. */ public boolean isActive(); -} +} \ No newline at end of file Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/NoResultException.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/NoResultException.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/NoResultException.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -6,7 +6,7 @@ * * @author Emmanuel Bernard */ -public class NoResultException extends RuntimeException { +public class NoResultException extends PersistenceException { public NoResultException() { super(); Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/NonUniqueResultException.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/NonUniqueResultException.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/NonUniqueResultException.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -4,7 +4,7 @@ /** * @author Gavin King */ -public class NonUniqueResultException extends RuntimeException { +public class NonUniqueResultException extends PersistenceException { public NonUniqueResultException() { super(); Added: trunk/HibernateExt/ejb-api/src/javax/persistence/RollbackException.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/RollbackException.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/RollbackException.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -0,0 +1,25 @@ +//$Id: $ +package javax.persistence; + +/** + * Exception occurs while commiting the transaction + * + * @author Emmanuel Bernard + */ +public class RollbackException extends PersistenceException { + public RollbackException() { + super(); + } + + public RollbackException(Throwable cause) { + super( cause ); + } + + public RollbackException(String message) { + super( message ); + } + + public RollbackException(String message, Throwable cause) { + super( message, cause ); + } +} Modified: trunk/HibernateExt/ejb-api/src/javax/persistence/TransactionRequiredException.java =================================================================== --- trunk/HibernateExt/ejb-api/src/javax/persistence/TransactionRequiredException.java 2006-03-08 19:57:35 UTC (rev 9577) +++ trunk/HibernateExt/ejb-api/src/javax/persistence/TransactionRequiredException.java 2006-03-08 22:41:38 UTC (rev 9578) @@ -4,7 +4,7 @@ /** * @author Gavin King */ -public class TransactionRequiredException extends RuntimeException { +public class TransactionRequiredException extends PersistenceException { public TransactionRequiredException() { super(); |