Skip to content

Commit

Permalink
Revert "HHH-14869 Extract JPA listener definitions when building meta…
Browse files Browse the repository at this point in the history
…data rather than when creating the SessionFactory"

This reverts commit 965f5bd.
  • Loading branch information
euano committed Aug 20, 2024
1 parent de96b98 commit 74b91c3
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 274 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.event.internal.CallbackDefinitionResolverLegacyImpl;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.Any;
import org.hibernate.mapping.Component;
Expand Down Expand Up @@ -825,8 +823,6 @@ else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
entityBinder.processComplementaryTableDefinitions( tabAnn );

bindCallbacks( clazzToProcess, persistentClass, context );
}

/**
Expand Down Expand Up @@ -1410,32 +1406,6 @@ private static void bindTypeDef(TypeDef defAnn, MetadataBuildingContext context)

}

private static void bindCallbacks(XClass entityClass, PersistentClass persistentClass,
MetadataBuildingContext context) {
ReflectionManager reflectionManager = context.getBootstrapContext().getReflectionManager();

for ( CallbackType callbackType : CallbackType.values() ) {
persistentClass.addCallbackDefinitions( CallbackDefinitionResolverLegacyImpl.resolveEntityCallbacks(
reflectionManager, entityClass, callbackType ) );
}

context.getMetadataCollector().addSecondPass( new SecondPass() {
@Override
public void doSecondPass(Map persistentClasses) throws MappingException {
for ( @SuppressWarnings("unchecked") Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator();
propertyIterator.hasNext(); ) {
Property property = propertyIterator.next();
if ( property.isComposite() ) {
for ( CallbackType callbackType : CallbackType.values() ) {
property.addCallbackDefinitions( CallbackDefinitionResolverLegacyImpl.resolveEmbeddableCallbacks(
reflectionManager, persistentClass.getMappedClass(), property, callbackType ) );
}
}
}
}
} );
}

public static void bindFetchProfilesForClass(XClass clazzToProcess, MetadataBuildingContext context) {
bindFetchProfiles( clazzToProcess, context );
}
Expand Down Expand Up @@ -1480,6 +1450,7 @@ private static void bindFetchProfile(FetchProfile fetchProfileAnnotation, Metada
}
}


private static void bindDiscriminatorColumnToRootPersistentClass(
RootClass rootClass,
Ejb3DiscriminatorColumn discriminatorColumn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Consumer;

Expand All @@ -22,6 +23,9 @@
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.event.internal.CallbackRegistryImplementor;
import org.hibernate.jpa.event.internal.CallbacksFactory;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.service.spi.Stoppable;

/**
Expand All @@ -35,6 +39,7 @@ public class EventEngine {
private final EventListenerRegistry listenerRegistry;

private final CallbackRegistryImplementor callbackRegistry;
private final CallbackBuilder callbackBuilder;

public EventEngine(
MetadataImplementor mappings,
Expand All @@ -43,8 +48,33 @@ public EventEngine(
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// resolve (JPA) callback handlers

this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
sessionFactory.getServiceRegistry(), mappings.getEntityBindings() );
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions() );
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder(
sessionFactory.getSessionFactoryOptions(),
sessionFactory.getServiceRegistry(),
mappings.getMetadataBuildingOptions().getReflectionManager()
);

for ( PersistentClass persistentClass : mappings.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have dynamic (non-java class) mapping
continue;
}

this.callbackBuilder.buildCallbacksForEntity( persistentClass.getMappedClass(), callbackRegistry );

for ( Iterator<Property> propertyIterator = persistentClass.getDeclaredPropertyIterator(); propertyIterator.hasNext(); ) {
final Property property = propertyIterator.next();

if ( property.isComposite() ) {
this.callbackBuilder.buildCallbacksForEmbeddable(
property,
persistentClass.getMappedClass(),
callbackRegistry
);
}
}
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -162,5 +192,7 @@ public void stop() {
}

callbackRegistry.release();

callbackBuilder.release();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,97 @@
import javax.persistence.MappedSuperclass;
import javax.persistence.PersistenceException;

import org.hibernate.MappingException;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XMethod;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;

import org.jboss.logging.Logger;

/**
* Resolves JPA callback definitions using a HCANN ReflectionManager.
* <p>
* "legacy" in that we want to move to Jandex instead.
* EntityCallbackBuilder implementation using HCANN ReflectionManager. "legacy" in that
* we want to move to Jandex instead.
*
* @author Steve Ebersole
*/
public final class CallbackDefinitionResolverLegacyImpl {
private static final Logger log = Logger.getLogger( CallbackDefinitionResolverLegacyImpl.class );
final class CallbackBuilderLegacyImpl implements CallbackBuilder {
private static final Logger log = Logger.getLogger( CallbackBuilderLegacyImpl.class );

private final ManagedBeanRegistry managedBeanRegistry;
private final ReflectionManager reflectionManager;

CallbackBuilderLegacyImpl(ManagedBeanRegistry managedBeanRegistry, ReflectionManager reflectionManager) {
this.managedBeanRegistry = managedBeanRegistry;
this.reflectionManager = reflectionManager;
}

@Override
public void buildCallbacksForEntity(Class entityClass, CallbackRegistrar callbackRegistrar) {
for ( CallbackType callbackType : CallbackType.values() ) {
if ( callbackRegistrar.hasRegisteredCallbacks( entityClass, callbackType ) ) {
// this most likely means we have a class mapped multiple times using the hbm.xml
// "entity name" feature
if ( log.isDebugEnabled() ) {
log.debugf(
"CallbackRegistry reported that Class [%s] already had %s callbacks registered; " +
"assuming this means the class was mapped twice " +
"(using hbm.xml entity-name support) - skipping subsequent registrations",
entityClass.getName(),
callbackType.getCallbackAnnotation().getSimpleName()
);
}
continue;
}
final Callback[] callbacks = resolveEntityCallbacks( entityClass, callbackType, reflectionManager );
callbackRegistrar.registerCallbacks( entityClass, callbacks );
}
}

@Override
public void buildCallbacksForEmbeddable(
Property embeddableProperty, Class entityClass, CallbackRegistrar callbackRegistrar) {
for ( CallbackType callbackType : CallbackType.values() ) {
final Callback[] callbacks = resolveEmbeddableCallbacks(
entityClass,
embeddableProperty,
callbackType,
reflectionManager
);
callbackRegistrar.registerCallbacks( entityClass, callbacks );
}
}

@Override
public void release() {
// nothing to do
}

@SuppressWarnings({"unchecked", "WeakerAccess"})
public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager reflectionManager,
XClass entityClass, CallbackType callbackType) {
List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
public Callback[] resolveEntityCallbacks(Class entityClass, CallbackType callbackType, ReflectionManager reflectionManager) {
List<Callback> callbacks = new ArrayList<>();
List<String> callbacksMethodNames = new ArrayList<>();
List<Class> orderedListeners = new ArrayList<>();
XClass currentClazz = entityClass;
XClass currentClazz = reflectionManager.toXClass( entityClass );
boolean stopListeners = false;
boolean stopDefaultListeners = false;
do {
CallbackDefinition callbackDefinition = null;
Callback callback = null;
List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callbackDefinition == null ) {
callbackDefinition = new EntityCallback.Definition( method, callbackType );
if ( callback == null ) {
callback = new EntityCallback( method, callbackType );
Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) {
Expand All @@ -78,7 +127,7 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
entityClass.getName()
);
}
callbackDefinitions.add( 0, callbackDefinition ); //superclass first
callbacks.add( 0, callback ); //superclass first
callbacksMethodNames.add( 0, methodName );
}
else {
Expand Down Expand Up @@ -119,7 +168,7 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
}

for ( Class listener : orderedListeners ) {
CallbackDefinition callbackDefinition = null;
Callback callback = null;
if ( listener != null ) {
XClass xListener = reflectionManager.toXClass( listener );
callbacksMethodNames = new ArrayList<>();
Expand All @@ -130,8 +179,12 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callbackDefinition == null ) {
callbackDefinition = new ListenerCallback.Definition( listener, method, callbackType );
if ( callback == null ) {
callback = new ListenerCallback(
managedBeanRegistry.getBean( listener ),
method,
callbackType
);

Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
Expand All @@ -150,7 +203,7 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
entityClass.getName()
);
}
callbackDefinitions.add( 0, callbackDefinition ); // listeners first
callbacks.add( 0, callback ); // listeners first
}
else {
throw new PersistenceException(
Expand All @@ -165,29 +218,29 @@ public static List<CallbackDefinition> resolveEntityCallbacks(ReflectionManager
}
}
}
return callbackDefinitions;
return callbacks.toArray( new Callback[callbacks.size()] );
}

public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionManager reflectionManager,
Class<?> entityClass, Property embeddableProperty,
CallbackType callbackType) {
@SuppressWarnings({"unchecked", "WeakerAccess"})
public Callback[] resolveEmbeddableCallbacks(Class entityClass, Property embeddableProperty, CallbackType callbackType, ReflectionManager reflectionManager) {

final Class embeddableClass = embeddableProperty.getType().getReturnedClass();
final XClass embeddableXClass = reflectionManager.toXClass( embeddableClass );
final Getter embeddableGetter = embeddableProperty.getGetter( entityClass );
final List<CallbackDefinition> callbackDefinitions = new ArrayList<>();
final List<Callback> callbacks = new ArrayList<>();
final List<String> callbacksMethodNames = new ArrayList<>();
XClass currentClazz = embeddableXClass;
do {
CallbackDefinition callbackDefinition = null;
Callback callback = null;
List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callbackDefinition == null ) {
callbackDefinition = new EmbeddableCallback.Definition( embeddableGetter, method, callbackType );
if ( callback == null ) {
callback = new EmbeddableCallback( embeddableGetter, method, callbackType );
Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) {
Expand All @@ -205,7 +258,7 @@ public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionMana
embeddableXClass.getName()
);
}
callbackDefinitions.add( 0, callbackDefinition ); //superclass first
callbacks.add( 0, callback ); //superclass first
callbacksMethodNames.add( 0, methodName );
}
else {
Expand All @@ -225,7 +278,7 @@ public static List<CallbackDefinition> resolveEmbeddableCallbacks(ReflectionMana
}
while ( currentClazz != null );

return callbackDefinitions;
return callbacks.toArray( new Callback[callbacks.size()] );
}

private static boolean useAnnotationAnnotatedByListener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
package org.hibernate.jpa.event.internal;

import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.jpa.event.spi.CallbackRegistrar;
import org.hibernate.jpa.event.spi.CallbackRegistry;

public interface CallbackRegistryImplementor extends CallbackRegistrar, CallbackBuilder.CallbackRegistrar {
public interface CallbackRegistryImplementor extends CallbackRegistry, CallbackBuilder.CallbackRegistrar {

void release();

Expand Down
Loading

0 comments on commit 74b91c3

Please sign in to comment.