From cf181b41b59f1595ffefdf2e51f35a0d41553d56 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 26 Mar 2012 20:09:18 -0500 Subject: [PATCH] HHH-7199 - proper JTA and auto-commit interaction for envers testsuite --- .../java/org/hibernate/test/tm/CMTTest.java | 3 + .../test/EnversTestingJtaBootstrap.java | 70 --------------- .../integration/jta/JtaExceptionListener.java | 30 +++---- .../test/integration/jta/JtaTransaction.java | 26 +++--- .../TestExceptionRevisionListener.java | 7 +- .../testing/jta/TestingJtaBootstrap.java | 86 ++++++++++++++++--- 6 files changed, 104 insertions(+), 118 deletions(-) delete mode 100644 hibernate-envers/src/matrix/java/org/hibernate/envers/test/EnversTestingJtaBootstrap.java diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/tm/CMTTest.java b/hibernate-core/src/matrix/java/org/hibernate/test/tm/CMTTest.java index bed3c6ee79..d10bf0390f 100755 --- a/hibernate-core/src/matrix/java/org/hibernate/test/tm/CMTTest.java +++ b/hibernate-core/src/matrix/java/org/hibernate/test/tm/CMTTest.java @@ -381,6 +381,7 @@ public class CMTTest extends BaseCoreFunctionalTestCase { assertFalse( s.isOpen() ); assertEquals( sessionFactory().getStatistics().getFlushCount(), 0 ); + assertEquals( sessionFactory().getStatistics().getEntityInsertCount(), 0 ); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); s = openSession(); @@ -395,6 +396,8 @@ public class CMTTest extends BaseCoreFunctionalTestCase { s.persist( "Item", item ); TestingJtaBootstrap.INSTANCE.getTransactionManager().commit(); assertFalse( s.isOpen() ); + assertEquals( sessionFactory().getStatistics().getFlushCount(), 1 ); + assertEquals( sessionFactory().getStatistics().getEntityInsertCount(), 1 ); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); s = openSession(); diff --git a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/EnversTestingJtaBootstrap.java b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/EnversTestingJtaBootstrap.java deleted file mode 100644 index 52d5b2afbe..0000000000 --- a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/EnversTestingJtaBootstrap.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.hibernate.envers.test; - -import java.sql.SQLException; -import java.util.Map; -import javax.transaction.Status; -import javax.transaction.TransactionManager; - -import com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean; -import com.arjuna.ats.internal.arjuna.objectstore.VolatileStore; -import com.arjuna.common.internal.util.propertyservice.BeanPopulator; -import org.enhydra.jdbc.standard.StandardXADataSource; - -import org.hibernate.cfg.Environment; -import org.hibernate.ejb.AvailableSettings; -import org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl; -import org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform; - -/** - * Copied from {@link org.hibernate.testing.jta.TestingJtaBootstrap}, as Envers tests use a different URL for - * testing databases. - * @author Adam Warski (adam at warski dot org) - */ -public class EnversTestingJtaBootstrap { - public static TransactionManager updateConfigAndCreateTM(Map configValues) { - BeanPopulator - .getDefaultInstance(ObjectStoreEnvironmentBean.class) - .setObjectStoreType( VolatileStore.class.getName() ); - - BeanPopulator - .getNamedInstance( ObjectStoreEnvironmentBean.class, "communicationStore" ) - .setObjectStoreType( VolatileStore.class.getName() ); - - BeanPopulator - .getNamedInstance( ObjectStoreEnvironmentBean.class, "stateStore" ) - .setObjectStoreType( VolatileStore.class.getName() ); - - TransactionManager transactionManager = com.arjuna.ats.jta.TransactionManager.transactionManager(); - - StandardXADataSource dataSource = new StandardXADataSource(); - dataSource.setTransactionManager( transactionManager ); - try { - dataSource.setDriverName( configValues.get(Environment.DRIVER).toString() ); - } - catch (SQLException e) { - throw new RuntimeException( "Unable to set DataSource JDBC driver name", e ); - } - dataSource.setUrl(configValues.get(Environment.URL).toString() + ";AUTOCOMMIT=OFF"); - dataSource.setUser(configValues.get(Environment.USER).toString()); - - configValues.remove(Environment.URL); - configValues.remove(Environment.USER); - configValues.remove(Environment.DRIVER); - - configValues.put( org.hibernate.cfg.AvailableSettings.JTA_PLATFORM, new JBossStandAloneJtaPlatform() ); - configValues.put( Environment.CONNECTION_PROVIDER, DatasourceConnectionProviderImpl.class.getName() ); - configValues.put( Environment.DATASOURCE, dataSource ); - - configValues.put(AvailableSettings.TRANSACTION_TYPE, "JTA"); - - return transactionManager; - } - - public static void tryCommit(TransactionManager tm) throws Exception { - if (tm.getStatus() == Status.STATUS_MARKED_ROLLBACK) { - tm.rollback(); - } else { - tm.commit(); - } - } -} diff --git a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaExceptionListener.java b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaExceptionListener.java index f89b395922..1d40561ce0 100644 --- a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaExceptionListener.java +++ b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaExceptionListener.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * Copyright (c) 2008-2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -26,27 +26,24 @@ package org.hibernate.envers.test.integration.jta; import java.util.Properties; import javax.persistence.EntityManager; import javax.transaction.RollbackException; -import javax.transaction.TransactionManager; import org.junit.Assert; import org.junit.Test; +import org.hibernate.AssertionFailure; import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.test.AbstractEntityTest; -import org.hibernate.envers.test.EnversTestingJtaBootstrap; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.integration.reventity.ExceptionListenerRevEntity; -import static org.hibernate.envers.test.EnversTestingJtaBootstrap.tryCommit; +import org.hibernate.testing.jta.TestingJtaBootstrap; /** * Same as {@link org.hibernate.envers.test.integration.reventity.ExceptionListener}, but in a JTA environment. * @author Adam Warski (adam at warski dot org) */ public class JtaExceptionListener extends AbstractEntityTest { - private TransactionManager tm; - public void configure(Ejb3Configuration cfg) { cfg.addAnnotatedClass(StrTestEntity.class); cfg.addAnnotatedClass(ExceptionListenerRevEntity.class); @@ -55,38 +52,39 @@ public class JtaExceptionListener extends AbstractEntityTest { @Override public void addConfigurationProperties(Properties configuration) { super.addConfigurationProperties(configuration); - tm = EnversTestingJtaBootstrap.updateConfigAndCreateTM(configuration); + TestingJtaBootstrap.prepare( configuration ); } @Test(expected = RollbackException.class) @Priority(5) // must run before testDataNotPersisted() public void testTransactionRollback() throws Exception { - tm.begin(); + TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); try { + newEntityManager(); + EntityManager em = getEntityManager(); + // Trying to persist an entity - however the listener should throw an exception, so the entity // shouldn't be persisted - newEntityManager(); - EntityManager em = getEntityManager(); StrTestEntity te = new StrTestEntity("x"); em.persist(te); } finally { - tryCommit(tm); + TestingJtaBootstrap.tryCommit(); } } @Test public void testDataNotPersisted() throws Exception { - tm.begin(); + TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); try { // Checking if the entity became persisted newEntityManager(); EntityManager em = getEntityManager(); - Long count = (Long) em.createQuery("select count(s) from StrTestEntity s where s.str = 'x'").getSingleResult(); - Assert.assertEquals( Long.valueOf( 0 ), count ); + long count = em.createQuery("from StrTestEntity s where s.str = 'x'").getResultList().size(); + Assert.assertEquals( 0, count ); } finally { - tryCommit(tm); + TestingJtaBootstrap.tryCommit(); } } } diff --git a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaTransaction.java b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaTransaction.java index 1d33e03018..2658bdd566 100644 --- a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaTransaction.java +++ b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/jta/JtaTransaction.java @@ -1,27 +1,24 @@ package org.hibernate.envers.test.integration.jta; +import javax.persistence.EntityManager; import java.util.Arrays; import java.util.Properties; -import javax.persistence.EntityManager; -import javax.transaction.TransactionManager; - -import org.junit.Test; import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.test.AbstractEntityTest; -import org.hibernate.envers.test.EnversTestingJtaBootstrap; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.IntTestEntity; -import org.hibernate.testing.FailureExpected; -import static org.hibernate.envers.test.EnversTestingJtaBootstrap.tryCommit; +import org.junit.Test; + +import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.jta.TestingJtaBootstrap; /** * Same as {@link org.hibernate.envers.test.integration.basic.Simple}, but in a JTA environment. * @author Adam Warski (adam at warski dot org) */ public class JtaTransaction extends AbstractEntityTest { - private TransactionManager tm; private Integer id1; public void configure(Ejb3Configuration cfg) { @@ -31,14 +28,13 @@ public class JtaTransaction extends AbstractEntityTest { @Override public void addConfigurationProperties(Properties configuration) { super.addConfigurationProperties(configuration); - tm = EnversTestingJtaBootstrap.updateConfigAndCreateTM(configuration); + TestingJtaBootstrap.prepare( configuration ); } @Test @Priority(10) - @FailureExpected(jiraKey = "HHH-6624") public void initData() throws Exception { - tm.begin(); + TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); EntityManager em; IntTestEntity ite; @@ -49,12 +45,12 @@ public class JtaTransaction extends AbstractEntityTest { em.persist(ite); id1 = ite.getId(); } finally { - tryCommit(tm); + TestingJtaBootstrap.tryCommit(); } // - tm.begin(); + TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); try { newEntityManager(); @@ -62,18 +58,16 @@ public class JtaTransaction extends AbstractEntityTest { ite = em.find(IntTestEntity.class, id1); ite.setNumber(20); } finally { - tryCommit(tm); + TestingJtaBootstrap.tryCommit(); } } @Test - @FailureExpected(jiraKey = "HHH-6624") public void testRevisionsCounts() throws Exception { assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(IntTestEntity.class, id1)); } @Test - @FailureExpected(jiraKey = "HHH-6624") public void testHistoryOfId1() { IntTestEntity ver1 = new IntTestEntity(10, id1); IntTestEntity ver2 = new IntTestEntity(20, id1); diff --git a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/reventity/TestExceptionRevisionListener.java b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/reventity/TestExceptionRevisionListener.java index ca94ed1472..130555b81e 100644 --- a/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/reventity/TestExceptionRevisionListener.java +++ b/hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/reventity/TestExceptionRevisionListener.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * Copyright (c) 2008-2012, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -22,6 +22,7 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.envers.test.integration.reventity; + import org.hibernate.envers.RevisionListener; /** @@ -29,6 +30,6 @@ import org.hibernate.envers.RevisionListener; */ public class TestExceptionRevisionListener implements RevisionListener { public void newRevision(Object revisionEntity) { - throw new RuntimeException(); + throw new RuntimeException( "forcing transaction failure!" ); } } \ No newline at end of file diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/jta/TestingJtaBootstrap.java b/hibernate-testing/src/main/java/org/hibernate/testing/jta/TestingJtaBootstrap.java index 143bef2c98..4479d35c07 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/jta/TestingJtaBootstrap.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/jta/TestingJtaBootstrap.java @@ -23,12 +23,14 @@ */ package org.hibernate.testing.jta; +import javax.sql.DataSource; +import javax.transaction.Status; +import javax.transaction.TransactionManager; +import javax.transaction.UserTransaction; +import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.Properties; -import javax.sql.DataSource; -import javax.transaction.TransactionManager; -import javax.transaction.UserTransaction; import com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean; import com.arjuna.ats.internal.arjuna.objectstore.VolatileStore; @@ -38,14 +40,13 @@ import org.enhydra.jdbc.standard.StandardXADataSource; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; import org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl; -import org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform; +import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform; /** * Manages the {@link TransactionManager}, {@link UserTransaction} and {@link DataSource} instances used for testing. * * @author Steve Ebersole */ -@SuppressWarnings( {"UnusedDeclaration", "unchecked"}) public class TestingJtaBootstrap { public static final TestingJtaBootstrap INSTANCE = new TestingJtaBootstrap(); @@ -70,8 +71,8 @@ public class TestingJtaBootstrap { this.userTransaction = com.arjuna.ats.jta.UserTransaction.userTransaction(); Properties environmentProperties = Environment.getProperties(); - StandardXADataSource dataSource = new StandardXADataSource(); - dataSource.setTransactionManager( com.arjuna.ats.jta.TransactionManager.transactionManager() ); + JtaAwareDataSource dataSource = new JtaAwareDataSource(); + dataSource.setTransactionManager( transactionManager ); try { dataSource.setDriverName( environmentProperties.getProperty( Environment.DRIVER ) ); } @@ -81,6 +82,8 @@ public class TestingJtaBootstrap { dataSource.setUrl( environmentProperties.getProperty( Environment.URL ) ); dataSource.setUser( environmentProperties.getProperty( Environment.USER ) ); dataSource.setPassword( environmentProperties.getProperty( Environment.PASS ) ); + environmentProperties.remove( Environment.USER ); + environmentProperties.remove( Environment.PASS ); final String isolationString = environmentProperties.getProperty( Environment.ISOLATION ); if ( isolationString != null ) { dataSource.setTransactionIsolation( Integer.valueOf( isolationString ) ); @@ -92,17 +95,74 @@ public class TestingJtaBootstrap { return transactionManager; } - public UserTransaction getUserTransaction() { - return userTransaction; - } - public DataSource getDataSource() { return dataSource; } + @SuppressWarnings("unchecked") public static void prepare(Map configValues) { - configValues.put( AvailableSettings.JTA_PLATFORM, new JBossStandAloneJtaPlatform() ); - configValues.put( Environment.CONNECTION_PROVIDER, DatasourceConnectionProviderImpl.class.getName() ); + configValues.put( AvailableSettings.JTA_PLATFORM, TestingJtaPlatformImpl.INSTANCE ); + configValues.put( Environment.CONNECTION_PROVIDER, JtaAwareDataSourceConnectionProvider.class.getName() ); configValues.put( Environment.DATASOURCE, INSTANCE.getDataSource() ); + configValues.put( "javax.persistence.transactionType", "JTA" ); + } + + /** + * Used by envers... + */ + public static void tryCommit() throws Exception { + if ( INSTANCE.transactionManager.getStatus() == Status.STATUS_MARKED_ROLLBACK ) { + INSTANCE.transactionManager.rollback(); + } + else { + INSTANCE.transactionManager.commit(); + } + } + + // ReTarDed + public static class JtaAwareDataSource extends StandardXADataSource { + @Override + public Connection getConnection() throws SQLException { + if ( getTransactionManager() == null ) { + setTransactionManager( TestingJtaBootstrap.INSTANCE.transactionManager ); + } + final Connection connection = getXAConnection().getConnection(); + connection.setAutoCommit( false ); + return connection; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; // JDK6 stuff + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; // JDK6 stuff + } + } + + public static class TestingJtaPlatformImpl extends AbstractJtaPlatform { + public static final TestingJtaPlatformImpl INSTANCE = new TestingJtaPlatformImpl(); + + @Override + protected TransactionManager locateTransactionManager() { + return TestingJtaBootstrap.INSTANCE.transactionManager; + } + + @Override + protected UserTransaction locateUserTransaction() { + return TestingJtaBootstrap.INSTANCE.userTransaction; + } + } + + public static class JtaAwareDataSourceConnectionProvider extends DatasourceConnectionProviderImpl { + public static final JtaAwareDataSourceConnectionProvider INSTANCE = new JtaAwareDataSourceConnectionProvider(); + + @Override + public Connection getConnection() throws SQLException { + // ignore username/password as it can cause infinite looping in the Enhydra code lol + return TestingJtaBootstrap.INSTANCE.dataSource.getConnection(); + } } }