HHH-8769 gracefully handle the lack of dynamic mode support in Envers
This commit is contained in:
parent
8d3d259963
commit
bea160a7ad
|
@ -23,14 +23,12 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.DOMWriter;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
|
@ -46,12 +44,13 @@ import org.hibernate.envers.internal.tools.graph.GraphTopologicalSort;
|
|||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.DOMWriter;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -77,12 +76,15 @@ public class EntitiesConfigurator {
|
|||
while ( classes.hasNext() ) {
|
||||
final PersistentClass pc = classes.next();
|
||||
|
||||
// Collecting information from annotations on the persistent class pc
|
||||
final AnnotationsMetadataReader annotationsMetadataReader =
|
||||
new AnnotationsMetadataReader( globalCfg, reflectionManager, pc );
|
||||
final ClassAuditingData auditData = annotationsMetadataReader.getAuditData();
|
||||
// Ensure we're in POJO, not dynamic model, mapping.
|
||||
if (pc.getClassName() != null) {
|
||||
// Collecting information from annotations on the persistent class pc
|
||||
final AnnotationsMetadataReader annotationsMetadataReader =
|
||||
new AnnotationsMetadataReader(globalCfg, reflectionManager, pc);
|
||||
final ClassAuditingData auditData = annotationsMetadataReader.getAuditData();
|
||||
|
||||
classesAuditingData.addClassAuditingData( pc, auditData );
|
||||
classesAuditingData.addClassAuditingData(pc, auditData);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that all information is read we can update the calculated fields.
|
||||
|
|
|
@ -23,11 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
|
@ -58,8 +55,10 @@ import org.hibernate.mapping.PersistentClass;
|
|||
import org.hibernate.type.LongType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
import javax.persistence.Column;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -319,77 +318,78 @@ public class RevisionInfoConfiguration {
|
|||
final Iterator<PersistentClass> classes = cfg.getClassMappings();
|
||||
while ( classes.hasNext() ) {
|
||||
PersistentClass pc = classes.next();
|
||||
XClass clazz;
|
||||
try {
|
||||
clazz = reflectionManager.classForName( pc.getClassName(), this.getClass() );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new MappingException( e );
|
||||
}
|
||||
|
||||
final RevisionEntity revisionEntity = clazz.getAnnotation( RevisionEntity.class );
|
||||
if ( revisionEntity != null ) {
|
||||
if ( revisionEntityFound ) {
|
||||
throw new MappingException( "Only one entity may be annotated with @RevisionEntity!" );
|
||||
// Ensure we're in POJO, not dynamic model, mapping.
|
||||
if (pc.getClassName() != null) {
|
||||
XClass clazz;
|
||||
try {
|
||||
clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
// Checking if custom revision entity isn't audited
|
||||
if ( clazz.getAnnotation( Audited.class ) != null ) {
|
||||
throw new MappingException( "An entity annotated with @RevisionEntity cannot be audited!" );
|
||||
}
|
||||
final RevisionEntity revisionEntity = clazz.getAnnotation(RevisionEntity.class);
|
||||
if (revisionEntity != null) {
|
||||
if (revisionEntityFound) {
|
||||
throw new MappingException("Only one entity may be annotated with @RevisionEntity!");
|
||||
}
|
||||
|
||||
revisionEntityFound = true;
|
||||
// Checking if custom revision entity isn't audited
|
||||
if (clazz.getAnnotation(Audited.class) != null) {
|
||||
throw new MappingException("An entity annotated with @RevisionEntity cannot be audited!");
|
||||
}
|
||||
|
||||
final MutableBoolean revisionNumberFound = new MutableBoolean();
|
||||
final MutableBoolean revisionTimestampFound = new MutableBoolean();
|
||||
final MutableBoolean modifiedEntityNamesFound = new MutableBoolean();
|
||||
revisionEntityFound = true;
|
||||
|
||||
searchForRevisionInfoCfg(
|
||||
clazz,
|
||||
reflectionManager,
|
||||
revisionNumberFound,
|
||||
revisionTimestampFound,
|
||||
modifiedEntityNamesFound
|
||||
);
|
||||
final MutableBoolean revisionNumberFound = new MutableBoolean();
|
||||
final MutableBoolean revisionTimestampFound = new MutableBoolean();
|
||||
final MutableBoolean modifiedEntityNamesFound = new MutableBoolean();
|
||||
|
||||
if ( !revisionNumberFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionNumber!"
|
||||
searchForRevisionInfoCfg(
|
||||
clazz,
|
||||
reflectionManager,
|
||||
revisionNumberFound,
|
||||
revisionTimestampFound,
|
||||
modifiedEntityNamesFound
|
||||
);
|
||||
}
|
||||
|
||||
if ( !revisionTimestampFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionTimestamp!"
|
||||
);
|
||||
}
|
||||
if (!revisionNumberFound.isSet()) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionNumber!"
|
||||
);
|
||||
}
|
||||
|
||||
revisionInfoEntityName = pc.getEntityName();
|
||||
revisionInfoClass = pc.getMappedClass();
|
||||
final Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass( revisionEntity.value() );
|
||||
revisionInfoTimestampType = pc.getProperty( revisionInfoTimestampData.getName() ).getType();
|
||||
if ( globalCfg.isTrackEntitiesChangedInRevision()
|
||||
|| (globalCfg.isUseRevisionEntityWithNativeId() && DefaultTrackingModifiedEntitiesRevisionEntity.class
|
||||
.isAssignableFrom( revisionInfoClass ))
|
||||
|| (!globalCfg.isUseRevisionEntityWithNativeId() && SequenceIdTrackingModifiedEntitiesRevisionEntity.class
|
||||
.isAssignableFrom( revisionInfoClass ))
|
||||
|| modifiedEntityNamesFound.isSet() ) {
|
||||
// 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, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(),
|
||||
modifiedEntityNamesData
|
||||
);
|
||||
globalCfg.setTrackEntitiesChangedInRevision( true );
|
||||
}
|
||||
else {
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(
|
||||
revisionInfoEntityName, revisionInfoClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate()
|
||||
);
|
||||
if (!revisionTimestampFound.isSet()) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionTimestamp!"
|
||||
);
|
||||
}
|
||||
|
||||
revisionInfoEntityName = pc.getEntityName();
|
||||
revisionInfoClass = pc.getMappedClass();
|
||||
final Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass(revisionEntity.value());
|
||||
revisionInfoTimestampType = pc.getProperty(revisionInfoTimestampData.getName()).getType();
|
||||
if (globalCfg.isTrackEntitiesChangedInRevision()
|
||||
|| (globalCfg.isUseRevisionEntityWithNativeId() && DefaultTrackingModifiedEntitiesRevisionEntity.class
|
||||
.isAssignableFrom(revisionInfoClass))
|
||||
|| (!globalCfg.isUseRevisionEntityWithNativeId() && SequenceIdTrackingModifiedEntitiesRevisionEntity.class
|
||||
.isAssignableFrom(revisionInfoClass))
|
||||
|| modifiedEntityNamesFound.isSet()) {
|
||||
// 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, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(),
|
||||
modifiedEntityNamesData
|
||||
);
|
||||
globalCfg.setTrackEntitiesChangedInRevision(true);
|
||||
} else {
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(
|
||||
revisionInfoEntityName, revisionInfoClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.dynamicmodel;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Felix Feisst (feisst dot felix at gmail dot com)
|
||||
|
@ -24,7 +23,6 @@ public class DynamicModelTest extends BaseEnversJPAFunctionalTestCase {
|
|||
* Tests that an EntityManager can be created when using a dynamic model mapping.
|
||||
*/
|
||||
@Test
|
||||
@FailureExpected(jiraKey = "HHH-8769")
|
||||
public void testDynamicModelMapping() {
|
||||
EntityManager entityManager = getOrCreateEntityManager();
|
||||
assertNotNull( "Expected an entity manager to be returned", entityManager );
|
||||
|
|
Loading…
Reference in New Issue