From 45f3ced6daf96f1a697f350e134512562b48d3fd Mon Sep 17 00:00:00 2001 From: Lukasz Antoniak Date: Thu, 29 Sep 2011 20:50:07 +0200 Subject: [PATCH] HHH-6696 - RevisionListener class configuration parameter --- .../main/docbook/devguide/en-US/Envers.xml | 6 +++- .../configuration/GlobalConfiguration.java | 21 +++++++++++ .../RevisionInfoConfiguration.java | 24 ++++++++++--- .../reventity/CountingRevisionListener.java | 15 ++++++++ .../GloballyConfiguredRevListenerTest.java | 36 +++++++++++++++++++ .../reventity/OverrideRevListenerTest.java | 14 ++++++++ 6 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/CountingRevisionListener.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/GloballyConfiguredRevListenerTest.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/OverrideRevListenerTest.java diff --git a/documentation/src/main/docbook/devguide/en-US/Envers.xml b/documentation/src/main/docbook/devguide/en-US/Envers.xml index 76191889ff..ebb4af5418 100644 --- a/documentation/src/main/docbook/devguide/en-US/Envers.xml +++ b/documentation/src/main/docbook/devguide/en-US/Envers.xml @@ -407,7 +407,11 @@ You tell Envers your custom org.hibernate.envers.RevisionListener implementation to use by specifying it on the @org.hibernate.envers.RevisionEntity annotation, using the - value attribute. + value attribute. If your RevisionListener + class is inaccessible from @RevisionEntity (e.g. exists in a different + module), set org.hibernate.envers.revision_listener property to it's fully + qualified name. Class name defined by the configuration parameter overrides revision entity's + value attribute. diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java index 6a54186b56..efbed9f1a1 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java @@ -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 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 (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) 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 getRevisionListenerClass() { + return revisionListenerClass; + } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java index a25b8f71f6..f2cf0c1a29 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java @@ -286,8 +286,8 @@ public class RevisionInfoConfiguration { } revisionInfoEntityName = pc.getEntityName(); - revisionInfoClass = pc.getMappedClass(); + Class 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 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 getRevisionListenerClass(Class defaultListener) { + if (globalCfg.getRevisionListenerClass() != null) { + return globalCfg.getRevisionListenerClass(); + } + return defaultListener; + } } class RevisionInfoConfigurationResult { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/CountingRevisionListener.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/CountingRevisionListener.java new file mode 100644 index 0000000000..e05e82b422 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/CountingRevisionListener.java @@ -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; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/GloballyConfiguredRevListenerTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/GloballyConfiguredRevListenerTest.java new file mode 100644 index 0000000000..bab6f3fbd6 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/GloballyConfiguredRevListenerTest.java @@ -0,0 +1,36 @@ +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.junit.Assert; +import org.junit.Test; + +import javax.persistence.EntityManager; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +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); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/OverrideRevListenerTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/OverrideRevListenerTest.java new file mode 100644 index 0000000000..278be9d9f7 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/OverrideRevListenerTest.java @@ -0,0 +1,14 @@ +package org.hibernate.envers.test.integration.reventity; + +import org.hibernate.ejb.Ejb3Configuration; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class OverrideRevListenerTest extends GloballyConfiguredRevListenerTest { + @Override + public void configure(Ejb3Configuration cfg) { + super.configure(cfg); + cfg.addAnnotatedClass(ListenerRevEntity.class); + } +}