Merge pull request #176 from lukasz-antoniak/HHH-6696

HHH-6696 - Allow specifying revision listener apart from @RevisionEntity annotation
This commit is contained in:
Adam Warski 2011-10-01 01:37:44 -07:00
commit 550865e3d3
7 changed files with 130 additions and 6 deletions

View File

@ -407,7 +407,11 @@
You tell Envers your custom <interfacename>org.hibernate.envers.RevisionListener</interfacename>
implementation to use by specifying it on the
<interfacename>@org.hibernate.envers.RevisionEntity</interfacename> annotation, using the
<methodname>value</methodname> attribute.
<methodname>value</methodname> attribute. If your <interfacename>RevisionListener</interfacename>
class is inaccessible from <interfacename>@RevisionEntity</interfacename> (e.g. exists in a different
module), set <property>org.hibernate.envers.revision_listener</property> property to it's fully
qualified name. Class name defined by the configuration parameter overrides revision entity's
<methodname>value</methodname> attribute.
</para>
</listitem>
</orderedlist>

View File

@ -22,6 +22,9 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.configuration;
import org.hibernate.MappingException;
import org.hibernate.envers.RevisionListener;
import static org.hibernate.envers.tools.Tools.getProperty;
import java.util.Properties;
@ -49,6 +52,9 @@ public class GlobalConfiguration {
// Should Envers track (persist) entity names that have been changed during each revision.
private boolean trackEntitiesChangedInRevisionEnabled;
// Revision listener class name.
private final Class<? extends RevisionListener> revisionListenerClass;
/*
Which operator to use in correlated subqueries (when we want a property to be equal to the result of
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
@ -87,6 +93,17 @@ public class GlobalConfiguration {
"org.hibernate.envers.track_entities_changed_in_revision",
"false");
trackEntitiesChangedInRevisionEnabled = Boolean.parseBoolean(trackEntitiesChangedInRevisionEnabledStr);
String revisionListenerClassName = properties.getProperty("org.hibernate.envers.revision_listener", null);
if (revisionListenerClassName != null) {
try {
revisionListenerClass = (Class<? extends RevisionListener>) Thread.currentThread().getContextClassLoader().loadClass(revisionListenerClassName);
} catch (ClassNotFoundException e) {
throw new MappingException("Revision listener class not found: " + revisionListenerClassName + ".", e);
}
} else {
revisionListenerClass = null;
}
}
public boolean isGenerateRevisionsForCollections() {
@ -120,4 +137,8 @@ public class GlobalConfiguration {
public void setTrackEntitiesChangedInRevisionEnabled(boolean trackEntitiesChangedInRevisionEnabled) {
this.trackEntitiesChangedInRevisionEnabled = trackEntitiesChangedInRevisionEnabled;
}
public Class<? extends RevisionListener> getRevisionListenerClass() {
return revisionListenerClass;
}
}

View File

@ -286,8 +286,8 @@ public class RevisionInfoConfiguration {
}
revisionInfoEntityName = pc.getEntityName();
revisionInfoClass = pc.getMappedClass();
Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass(revisionEntity.value());
revisionInfoTimestampType = pc.getProperty(revisionInfoTimestampData.getName()).getType();
if (globalCfg.isTrackEntitiesChangedInRevisionEnabled() ||
DefaultTrackingModifiedEntitiesRevisionEntity.class.isAssignableFrom(revisionInfoClass) ||
@ -295,12 +295,12 @@ public class RevisionInfoConfiguration {
// If tracking modified entities parameter is enabled, custom revision info entity is a subtype
// of DefaultTrackingModifiedEntitiesRevisionEntity class, or @ModifiedEntityNames annotation is used.
revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(revisionInfoEntityName,
revisionInfoClass, revisionEntity.value(), revisionInfoTimestampData, isTimestampAsDate(),
revisionInfoClass, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(),
modifiedEntityNamesData);
globalCfg.setTrackEntitiesChangedInRevisionEnabled(true);
} else {
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
revisionEntity.value(), revisionInfoTimestampData, isTimestampAsDate());
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate());
}
}
}
@ -308,16 +308,18 @@ public class RevisionInfoConfiguration {
// In case of a custom revision info generator, the mapping will be null.
Document revisionInfoXmlMapping = null;
Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass(RevisionListener.class);
if (revisionInfoGenerator == null) {
if (globalCfg.isTrackEntitiesChangedInRevisionEnabled()) {
revisionInfoClass = DefaultTrackingModifiedEntitiesRevisionEntity.class;
revisionInfoEntityName = DefaultTrackingModifiedEntitiesRevisionEntity.class.getName();
revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
RevisionListener.class, revisionInfoTimestampData, isTimestampAsDate(), modifiedEntityNamesData);
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(), modifiedEntityNamesData);
} else {
revisionInfoClass = DefaultRevisionEntity.class;
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
RevisionListener.class, revisionInfoTimestampData, isTimestampAsDate());
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate());
}
revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
}
@ -337,6 +339,18 @@ public class RevisionInfoConfiguration {
String typename = revisionInfoTimestampType.getName();
return "date".equals(typename) || "time".equals(typename) || "timestamp".equals(typename);
}
/**
* @param defaultListener Revision listener that shall be applied if {@code org.hibernate.envers.revision_listener}
* parameter has not been set.
* @return Revision listener.
*/
private Class<? extends RevisionListener> getRevisionListenerClass(Class<? extends RevisionListener> defaultListener) {
if (globalCfg.getRevisionListenerClass() != null) {
return globalCfg.getRevisionListenerClass();
}
return defaultListener;
}
}
class RevisionInfoConfigurationResult {

View File

@ -0,0 +1,15 @@
package org.hibernate.envers.test.integration.reventity;
import org.hibernate.envers.RevisionListener;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
public class CountingRevisionListener implements RevisionListener {
public static int revisionCount = 0;
@Override
public void newRevision(Object revisionEntity) {
++revisionCount;
}
}

View File

@ -0,0 +1,38 @@
package org.hibernate.envers.test.integration.reventity;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.test.AbstractEntityTest;
import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.entities.StrTestEntity;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
import javax.persistence.EntityManager;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@TestForIssue(jiraKey = "HHH-6696")
public class GloballyConfiguredRevListenerTest extends AbstractEntityTest {
public void configure(Ejb3Configuration cfg) {
cfg.addAnnotatedClass(StrTestEntity.class);
cfg.setProperty("org.hibernate.envers.revision_listener", "org.hibernate.envers.test.integration.reventity.CountingRevisionListener");
}
@Test
@Priority(10)
public void initData() {
EntityManager em = getEntityManager();
CountingRevisionListener.revisionCount = 0;
// Revision 1
em.getTransaction().begin();
StrTestEntity te = new StrTestEntity("data");
em.persist(te);
em.getTransaction().commit();
Assert.assertEquals(1, CountingRevisionListener.revisionCount);
}
}

View File

@ -0,0 +1,16 @@
package org.hibernate.envers.test.integration.reventity;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.testing.TestForIssue;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@TestForIssue(jiraKey = "HHH-6696")
public class OverrideCustomRevListenerTest extends GloballyConfiguredRevListenerTest {
@Override
public void configure(Ejb3Configuration cfg) {
super.configure(cfg);
cfg.addAnnotatedClass(ListenerRevEntity.class);
}
}

View File

@ -0,0 +1,16 @@
package org.hibernate.envers.test.integration.reventity;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.testing.TestForIssue;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@TestForIssue(jiraKey = "HHH-6696")
public class OverrideDefaultRevListenerTest extends GloballyConfiguredRevListenerTest {
@Override
public void configure(Ejb3Configuration cfg) {
super.configure(cfg);
cfg.addAnnotatedClass(LongRevNumberRevEntity.class);
}
}