HHH-7199 - proper JTA and auto-commit interaction for envers testsuite

This commit is contained in:
Steve Ebersole 2012-03-26 20:09:18 -05:00
parent 38a6c426ff
commit cf181b41b5
6 changed files with 104 additions and 118 deletions

View File

@ -381,6 +381,7 @@ public class CMTTest extends BaseCoreFunctionalTestCase {
assertFalse( s.isOpen() ); assertFalse( s.isOpen() );
assertEquals( sessionFactory().getStatistics().getFlushCount(), 0 ); assertEquals( sessionFactory().getStatistics().getFlushCount(), 0 );
assertEquals( sessionFactory().getStatistics().getEntityInsertCount(), 0 );
TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin();
s = openSession(); s = openSession();
@ -395,6 +396,8 @@ public class CMTTest extends BaseCoreFunctionalTestCase {
s.persist( "Item", item ); s.persist( "Item", item );
TestingJtaBootstrap.INSTANCE.getTransactionManager().commit(); TestingJtaBootstrap.INSTANCE.getTransactionManager().commit();
assertFalse( s.isOpen() ); assertFalse( s.isOpen() );
assertEquals( sessionFactory().getStatistics().getFlushCount(), 1 );
assertEquals( sessionFactory().getStatistics().getEntityInsertCount(), 1 );
TestingJtaBootstrap.INSTANCE.getTransactionManager().begin(); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin();
s = openSession(); s = openSession();

View File

@ -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();
}
}
}

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * 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 java.util.Properties;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.transaction.RollbackException; import javax.transaction.RollbackException;
import javax.transaction.TransactionManager;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.hibernate.AssertionFailure;
import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.test.AbstractEntityTest; import org.hibernate.envers.test.AbstractEntityTest;
import org.hibernate.envers.test.EnversTestingJtaBootstrap;
import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.entities.StrTestEntity; import org.hibernate.envers.test.entities.StrTestEntity;
import org.hibernate.envers.test.integration.reventity.ExceptionListenerRevEntity; 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. * Same as {@link org.hibernate.envers.test.integration.reventity.ExceptionListener}, but in a JTA environment.
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public class JtaExceptionListener extends AbstractEntityTest { public class JtaExceptionListener extends AbstractEntityTest {
private TransactionManager tm;
public void configure(Ejb3Configuration cfg) { public void configure(Ejb3Configuration cfg) {
cfg.addAnnotatedClass(StrTestEntity.class); cfg.addAnnotatedClass(StrTestEntity.class);
cfg.addAnnotatedClass(ExceptionListenerRevEntity.class); cfg.addAnnotatedClass(ExceptionListenerRevEntity.class);
@ -55,38 +52,39 @@ public class JtaExceptionListener extends AbstractEntityTest {
@Override @Override
public void addConfigurationProperties(Properties configuration) { public void addConfigurationProperties(Properties configuration) {
super.addConfigurationProperties(configuration); super.addConfigurationProperties(configuration);
tm = EnversTestingJtaBootstrap.updateConfigAndCreateTM(configuration); TestingJtaBootstrap.prepare( configuration );
} }
@Test(expected = RollbackException.class) @Test(expected = RollbackException.class)
@Priority(5) // must run before testDataNotPersisted() @Priority(5) // must run before testDataNotPersisted()
public void testTransactionRollback() throws Exception { public void testTransactionRollback() throws Exception {
tm.begin(); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin();
try { try {
newEntityManager();
EntityManager em = getEntityManager();
// Trying to persist an entity - however the listener should throw an exception, so the entity // Trying to persist an entity - however the listener should throw an exception, so the entity
// shouldn't be persisted // shouldn't be persisted
newEntityManager();
EntityManager em = getEntityManager();
StrTestEntity te = new StrTestEntity("x"); StrTestEntity te = new StrTestEntity("x");
em.persist(te); em.persist(te);
} finally { } finally {
tryCommit(tm); TestingJtaBootstrap.tryCommit();
} }
} }
@Test @Test
public void testDataNotPersisted() throws Exception { public void testDataNotPersisted() throws Exception {
tm.begin(); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin();
try { try {
// Checking if the entity became persisted // Checking if the entity became persisted
newEntityManager(); newEntityManager();
EntityManager em = getEntityManager(); EntityManager em = getEntityManager();
Long count = (Long) em.createQuery("select count(s) from StrTestEntity s where s.str = 'x'").getSingleResult(); long count = em.createQuery("from StrTestEntity s where s.str = 'x'").getResultList().size();
Assert.assertEquals( Long.valueOf( 0 ), count ); Assert.assertEquals( 0, count );
} finally { } finally {
tryCommit(tm); TestingJtaBootstrap.tryCommit();
} }
} }
} }

View File

@ -1,27 +1,24 @@
package org.hibernate.envers.test.integration.jta; package org.hibernate.envers.test.integration.jta;
import javax.persistence.EntityManager;
import java.util.Arrays; import java.util.Arrays;
import java.util.Properties; import java.util.Properties;
import javax.persistence.EntityManager;
import javax.transaction.TransactionManager;
import org.junit.Test;
import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.test.AbstractEntityTest; import org.hibernate.envers.test.AbstractEntityTest;
import org.hibernate.envers.test.EnversTestingJtaBootstrap;
import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.entities.IntTestEntity; 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. * Same as {@link org.hibernate.envers.test.integration.basic.Simple}, but in a JTA environment.
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public class JtaTransaction extends AbstractEntityTest { public class JtaTransaction extends AbstractEntityTest {
private TransactionManager tm;
private Integer id1; private Integer id1;
public void configure(Ejb3Configuration cfg) { public void configure(Ejb3Configuration cfg) {
@ -31,14 +28,13 @@ public class JtaTransaction extends AbstractEntityTest {
@Override @Override
public void addConfigurationProperties(Properties configuration) { public void addConfigurationProperties(Properties configuration) {
super.addConfigurationProperties(configuration); super.addConfigurationProperties(configuration);
tm = EnversTestingJtaBootstrap.updateConfigAndCreateTM(configuration); TestingJtaBootstrap.prepare( configuration );
} }
@Test @Test
@Priority(10) @Priority(10)
@FailureExpected(jiraKey = "HHH-6624")
public void initData() throws Exception { public void initData() throws Exception {
tm.begin(); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin();
EntityManager em; EntityManager em;
IntTestEntity ite; IntTestEntity ite;
@ -49,12 +45,12 @@ public class JtaTransaction extends AbstractEntityTest {
em.persist(ite); em.persist(ite);
id1 = ite.getId(); id1 = ite.getId();
} finally { } finally {
tryCommit(tm); TestingJtaBootstrap.tryCommit();
} }
// //
tm.begin(); TestingJtaBootstrap.INSTANCE.getTransactionManager().begin();
try { try {
newEntityManager(); newEntityManager();
@ -62,18 +58,16 @@ public class JtaTransaction extends AbstractEntityTest {
ite = em.find(IntTestEntity.class, id1); ite = em.find(IntTestEntity.class, id1);
ite.setNumber(20); ite.setNumber(20);
} finally { } finally {
tryCommit(tm); TestingJtaBootstrap.tryCommit();
} }
} }
@Test @Test
@FailureExpected(jiraKey = "HHH-6624")
public void testRevisionsCounts() throws Exception { public void testRevisionsCounts() throws Exception {
assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(IntTestEntity.class, id1)); assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(IntTestEntity.class, id1));
} }
@Test @Test
@FailureExpected(jiraKey = "HHH-6624")
public void testHistoryOfId1() { public void testHistoryOfId1() {
IntTestEntity ver1 = new IntTestEntity(10, id1); IntTestEntity ver1 = new IntTestEntity(10, id1);
IntTestEntity ver2 = new IntTestEntity(20, id1); IntTestEntity ver2 = new IntTestEntity(20, id1);

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.envers.test.integration.reventity; package org.hibernate.envers.test.integration.reventity;
import org.hibernate.envers.RevisionListener; import org.hibernate.envers.RevisionListener;
/** /**
@ -29,6 +30,6 @@ import org.hibernate.envers.RevisionListener;
*/ */
public class TestExceptionRevisionListener implements RevisionListener { public class TestExceptionRevisionListener implements RevisionListener {
public void newRevision(Object revisionEntity) { public void newRevision(Object revisionEntity) {
throw new RuntimeException(); throw new RuntimeException( "forcing transaction failure!" );
} }
} }

View File

@ -23,12 +23,14 @@
*/ */
package org.hibernate.testing.jta; 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.sql.SQLException;
import java.util.Map; import java.util.Map;
import java.util.Properties; 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.arjuna.common.ObjectStoreEnvironmentBean;
import com.arjuna.ats.internal.arjuna.objectstore.VolatileStore; 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.AvailableSettings;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl; 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. * Manages the {@link TransactionManager}, {@link UserTransaction} and {@link DataSource} instances used for testing.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@SuppressWarnings( {"UnusedDeclaration", "unchecked"})
public class TestingJtaBootstrap { public class TestingJtaBootstrap {
public static final TestingJtaBootstrap INSTANCE = new TestingJtaBootstrap(); public static final TestingJtaBootstrap INSTANCE = new TestingJtaBootstrap();
@ -70,8 +71,8 @@ public class TestingJtaBootstrap {
this.userTransaction = com.arjuna.ats.jta.UserTransaction.userTransaction(); this.userTransaction = com.arjuna.ats.jta.UserTransaction.userTransaction();
Properties environmentProperties = Environment.getProperties(); Properties environmentProperties = Environment.getProperties();
StandardXADataSource dataSource = new StandardXADataSource(); JtaAwareDataSource dataSource = new JtaAwareDataSource();
dataSource.setTransactionManager( com.arjuna.ats.jta.TransactionManager.transactionManager() ); dataSource.setTransactionManager( transactionManager );
try { try {
dataSource.setDriverName( environmentProperties.getProperty( Environment.DRIVER ) ); dataSource.setDriverName( environmentProperties.getProperty( Environment.DRIVER ) );
} }
@ -81,6 +82,8 @@ public class TestingJtaBootstrap {
dataSource.setUrl( environmentProperties.getProperty( Environment.URL ) ); dataSource.setUrl( environmentProperties.getProperty( Environment.URL ) );
dataSource.setUser( environmentProperties.getProperty( Environment.USER ) ); dataSource.setUser( environmentProperties.getProperty( Environment.USER ) );
dataSource.setPassword( environmentProperties.getProperty( Environment.PASS ) ); dataSource.setPassword( environmentProperties.getProperty( Environment.PASS ) );
environmentProperties.remove( Environment.USER );
environmentProperties.remove( Environment.PASS );
final String isolationString = environmentProperties.getProperty( Environment.ISOLATION ); final String isolationString = environmentProperties.getProperty( Environment.ISOLATION );
if ( isolationString != null ) { if ( isolationString != null ) {
dataSource.setTransactionIsolation( Integer.valueOf( isolationString ) ); dataSource.setTransactionIsolation( Integer.valueOf( isolationString ) );
@ -92,17 +95,74 @@ public class TestingJtaBootstrap {
return transactionManager; return transactionManager;
} }
public UserTransaction getUserTransaction() {
return userTransaction;
}
public DataSource getDataSource() { public DataSource getDataSource() {
return dataSource; return dataSource;
} }
@SuppressWarnings("unchecked")
public static void prepare(Map configValues) { public static void prepare(Map configValues) {
configValues.put( AvailableSettings.JTA_PLATFORM, new JBossStandAloneJtaPlatform() ); configValues.put( AvailableSettings.JTA_PLATFORM, TestingJtaPlatformImpl.INSTANCE );
configValues.put( Environment.CONNECTION_PROVIDER, DatasourceConnectionProviderImpl.class.getName() ); configValues.put( Environment.CONNECTION_PROVIDER, JtaAwareDataSourceConnectionProvider.class.getName() );
configValues.put( Environment.DATASOURCE, INSTANCE.getDataSource() ); 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> T unwrap(Class<T> 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();
}
} }
} }