HHH-5315:
- work units executed both in the before tx completion process and in the synchronization - each test class has its own H2 database - tests in a JTA environment git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19928 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
8ff871941d
commit
b50d8268d5
|
@ -118,6 +118,12 @@
|
|||
<artifactId>javassist</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- For JTA tests -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-testing</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -137,6 +143,11 @@
|
|||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-testing</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-tools</artifactId>
|
||||
|
|
|
@ -37,11 +37,14 @@ import org.hibernate.envers.tools.Pair;
|
|||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import javax.transaction.Synchronization;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class AuditProcess implements BeforeTransactionCompletionProcess {
|
||||
public class AuditProcess implements BeforeTransactionCompletionProcess, Synchronization {
|
||||
private final RevisionInfoGenerator revisionInfoGenerator;
|
||||
private final SessionImplementor session;
|
||||
|
||||
private final LinkedList<AuditWorkUnit> workUnits;
|
||||
private final Queue<AuditWorkUnit> undoQueue;
|
||||
|
@ -49,8 +52,9 @@ public class AuditProcess implements BeforeTransactionCompletionProcess {
|
|||
|
||||
private Object revisionData;
|
||||
|
||||
public AuditProcess(RevisionInfoGenerator revisionInfoGenerator) {
|
||||
public AuditProcess(RevisionInfoGenerator revisionInfoGenerator, SessionImplementor session) {
|
||||
this.revisionInfoGenerator = revisionInfoGenerator;
|
||||
this.session = session;
|
||||
|
||||
workUnits = new LinkedList<AuditWorkUnit>();
|
||||
undoQueue = new LinkedList<AuditWorkUnit>();
|
||||
|
@ -153,4 +157,12 @@ public class AuditProcess implements BeforeTransactionCompletionProcess {
|
|||
session.flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronization methods
|
||||
|
||||
public void beforeCompletion() {
|
||||
doBeforeTransactionCompletion(session);
|
||||
}
|
||||
|
||||
public void afterCompletion(int status) { }
|
||||
}
|
||||
|
|
|
@ -52,10 +52,22 @@ public class AuditProcessManager {
|
|||
AuditProcess auditProcess = auditProcesses.get(transaction);
|
||||
if (auditProcess == null) {
|
||||
// No worries about registering a transaction twice - a transaction is single thread
|
||||
auditProcess = new AuditProcess(revisionInfoGenerator);
|
||||
auditProcess = new AuditProcess(revisionInfoGenerator, session);
|
||||
auditProcesses.put(transaction, auditProcess);
|
||||
|
||||
/*
|
||||
* HHH-5315: the process must be both a BeforeTransactionCompletionProcess and a TX Synchronization.
|
||||
*
|
||||
* In a resource-local tx env, the process is called after the flush, and populates the audit tables.
|
||||
* Also, any exceptions that occur during that are propagated (if a Synchronization was used, the exceptions
|
||||
* would be eaten).
|
||||
*
|
||||
* In a JTA env, the before transaction completion is called before the flush, so not all changes are yet
|
||||
* written. However, Synchronization-s do propagate exceptions, so they can be safely used.
|
||||
*/
|
||||
session.getActionQueue().registerProcess(auditProcess);
|
||||
session.getTransaction().registerSynchronization(auditProcess);
|
||||
|
||||
session.getActionQueue().registerProcess(new AfterTransactionCompletionProcess() {
|
||||
public void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
|
||||
auditProcesses.remove(transaction);
|
||||
|
|
|
@ -27,9 +27,13 @@ import java.io.IOException;
|
|||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.ejb.AvailableSettings;
|
||||
import org.hibernate.envers.AuditReader;
|
||||
import org.hibernate.envers.AuditReaderFactory;
|
||||
import org.hibernate.envers.event.AuditEventListener;
|
||||
import org.hibernate.testing.tm.ConnectionProviderImpl;
|
||||
import org.hibernate.testing.tm.TransactionManagerLookupImpl;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
|
@ -89,11 +93,15 @@ public abstract class AbstractEntityTest {
|
|||
initListeners();
|
||||
}
|
||||
|
||||
cfg.configure("hibernate.test.cfg.xml");
|
||||
|
||||
if (auditStrategy != null && !"".equals(auditStrategy)) {
|
||||
cfg.setProperty("org.hibernate.envers.audit_strategy", auditStrategy);
|
||||
}
|
||||
|
||||
cfg.configure("hibernate.test.cfg.xml");
|
||||
// Separate database for each test class
|
||||
cfg.setProperty("hibernate.connection.url", "jdbc:h2:mem:" + this.getClass().getName());
|
||||
|
||||
configure(cfg);
|
||||
emf = cfg.buildEntityManagerFactory();
|
||||
|
||||
|
@ -117,4 +125,10 @@ public abstract class AbstractEntityTest {
|
|||
public Ejb3Configuration getCfg() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
protected void addJTAConfig(Ejb3Configuration cfg) {
|
||||
cfg.setProperty("connection.provider_class", ConnectionProviderImpl.class.getName());
|
||||
cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, TransactionManagerLookupImpl.class.getName());
|
||||
cfg.setProperty(AvailableSettings.TRANSACTION_TYPE, "JTA");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC 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.
|
||||
*
|
||||
* 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
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.test.integration.jta;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.hibernate.envers.test.integration.reventity.ExceptionListenerRevEntity;
|
||||
import org.hibernate.testing.tm.SimpleJtaTransactionManagerImpl;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||
cfg.addAnnotatedClass(ExceptionListenerRevEntity.class);
|
||||
|
||||
addJTAConfig(cfg);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = RuntimeException.class)
|
||||
public void testTransactionRollback() throws Exception {
|
||||
SimpleJtaTransactionManagerImpl.getInstance().begin();
|
||||
|
||||
// Trying to persist an entity - however the listener should throw an exception, so the entity
|
||||
// shouldn't be persisted
|
||||
newEntityManager();
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
StrTestEntity te = new StrTestEntity("x");
|
||||
em.persist(te);
|
||||
|
||||
SimpleJtaTransactionManagerImpl.getInstance().commit();
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testTransactionRollback")
|
||||
public void testDataNotPersisted() throws Exception {
|
||||
SimpleJtaTransactionManagerImpl.getInstance().begin();
|
||||
|
||||
// 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 count == 0l;
|
||||
|
||||
SimpleJtaTransactionManagerImpl.getInstance().commit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package org.hibernate.envers.test.integration.jta;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.IntTestEntity;
|
||||
import org.hibernate.testing.tm.SimpleJtaTransactionManagerImpl;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 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 Integer id1;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(IntTestEntity.class);
|
||||
|
||||
addJTAConfig(cfg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initData() throws Exception {
|
||||
SimpleJtaTransactionManagerImpl.getInstance().begin();
|
||||
|
||||
newEntityManager();
|
||||
EntityManager em = getEntityManager();
|
||||
em.joinTransaction();
|
||||
IntTestEntity ite = new IntTestEntity(10);
|
||||
em.persist(ite);
|
||||
id1 = ite.getId();
|
||||
|
||||
SimpleJtaTransactionManagerImpl.getInstance().commit();
|
||||
|
||||
//
|
||||
|
||||
SimpleJtaTransactionManagerImpl.getInstance().begin();
|
||||
|
||||
newEntityManager();
|
||||
em = getEntityManager();
|
||||
ite = em.find(IntTestEntity.class, id1);
|
||||
ite.setNumber(20);
|
||||
|
||||
SimpleJtaTransactionManagerImpl.getInstance().commit();
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testRevisionsCounts() throws Exception {
|
||||
assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(IntTestEntity.class, id1));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testHistoryOfId1() {
|
||||
IntTestEntity ver1 = new IntTestEntity(10, id1);
|
||||
IntTestEntity ver2 = new IntTestEntity(20, id1);
|
||||
|
||||
assert getAuditReader().find(IntTestEntity.class, id1, 1).equals(ver1);
|
||||
assert getAuditReader().find(IntTestEntity.class, id1, 2).equals(ver2);
|
||||
}
|
||||
}
|
|
@ -12,10 +12,10 @@
|
|||
<property name="format_sql">true</property>
|
||||
|
||||
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
|
||||
<property name="connection.url">jdbc:h2:mem:envers</property>
|
||||
<property name="connection.driver_class">org.h2.Driver</property>
|
||||
<property name="connection.username">sa</property>
|
||||
<property name="connection.password"></property>
|
||||
<!-- The connection URL is set in AbstractEntityTest -->
|
||||
|
||||
<!--<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>-->
|
||||
<!--<property name="connection.url">jdbc:mysql:///hibernate_tests?useUnicode=true&characterEncoding=UTF-8</property>-->
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<package name="org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.subclass" />
|
||||
<package name="org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.joined" />
|
||||
<package name="org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.union" />
|
||||
<package name="org.hibernate.envers.test.integration.jta" />
|
||||
<package name="org.hibernate.envers.test.integration.manytomany" />
|
||||
<package name="org.hibernate.envers.test.integration.manytomany.biowned" />
|
||||
<package name="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass" />
|
||||
|
|
Loading…
Reference in New Issue