HHH-10477 - Setting to allow delayed access to CDI

This commit is contained in:
Steve Ebersole 2016-01-25 15:33:15 -06:00
parent 7f9fd50e26
commit f3d98cb4ef
35 changed files with 1215 additions and 317 deletions

View File

@ -33,6 +33,10 @@ dependencies {
testCompile( libraries.validation ) testCompile( libraries.validation )
testCompile( "org.jboss.weld:weld-core:2.0.0.Beta6" ) testCompile( "org.jboss.weld:weld-core:2.0.0.Beta6" )
testCompile( "org.jboss.weld.arquillian.container:arquillian-weld-ee-embedded-1.1:1.1.2.Final" ) testCompile( "org.jboss.weld.arquillian.container:arquillian-weld-ee-embedded-1.1:1.1.2.Final" )
testCompile( "javax.enterprise:cdi-api:1.1-PFD" ) {
// we need to force it to make sure we influence the one coming from arquillian
force=true
}
testCompile( libraries.mockito ) testCompile( libraries.mockito )
testRuntime( libraries.validator ) testRuntime( libraries.validator )

View File

@ -555,4 +555,12 @@ public interface AvailableSettings {
* Used to pass along the name of the persistence unit. * Used to pass along the name of the persistence unit.
*/ */
String PERSISTENCE_UNIT_NAME = "hibernate.ejb.persistenceUnitName"; String PERSISTENCE_UNIT_NAME = "hibernate.ejb.persistenceUnitName";
/**
* Defines delayed access to CDI BeanManager. Starting in 5.1 the preferred means for CDI
* bootstrapping is through org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager
*
* @since 5.0.8
*/
String DELAY_CDI_ACCESS = "hibernate.delay_cdi_access";
} }

View File

@ -11,7 +11,7 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultDeleteEventListener; import org.hibernate.event.internal.DefaultDeleteEventListener;
import org.hibernate.event.spi.DeleteEvent; import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;

View File

@ -12,7 +12,7 @@ import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.internal.DefaultFlushEntityEventListener; import org.hibernate.event.internal.DefaultFlushEntityEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;

View File

@ -10,7 +10,7 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultMergeEventListener; import org.hibernate.event.internal.DefaultMergeEventListener;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
/** /**

View File

@ -15,7 +15,7 @@ import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.event.internal.DefaultPersistEventListener; import org.hibernate.event.internal.DefaultPersistEventListener;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;

View File

@ -8,7 +8,7 @@ package org.hibernate.jpa.event.internal.core;
import org.hibernate.event.spi.PostDeleteEvent; import org.hibernate.event.spi.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener; import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;

View File

@ -8,7 +8,7 @@ package org.hibernate.jpa.event.internal.core;
import org.hibernate.event.spi.PostInsertEvent; import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;

View File

@ -8,7 +8,7 @@ package org.hibernate.jpa.event.internal.core;
import org.hibernate.event.spi.PostLoadEvent; import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener; import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
/** /**

View File

@ -17,7 +17,7 @@ import org.hibernate.event.spi.PostCollectionUpdateEvent;
import org.hibernate.event.spi.PostCollectionUpdateEventListener; import org.hibernate.event.spi.PostCollectionUpdateEventListener;
import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener; import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;

View File

@ -10,7 +10,7 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultSaveEventListener; import org.hibernate.event.internal.DefaultSaveEventListener;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
/** /**

View File

@ -10,7 +10,7 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener; import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
/** /**

View File

@ -0,0 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
/**
* @author Steve Ebersole
*/
public abstract class AbstractCallback implements Callback {
private final CallbackType callbackType;
public AbstractCallback(CallbackType callbackType) {
this.callbackType = callbackType;
}
@Override
public boolean isActive() {
return true;
}
@Override
public CallbackType getCallbackType() {
return callbackType;
}
}

View File

@ -1,76 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
/**
* CID-based implementation of the ListenerFactory contract. Listener instances are kept in a map keyed by Class
* to achieve singleton-ness.
*
* @author Steve Ebersole
*/
public class BeanManagerListenerFactory implements ListenerFactory {
private final BeanManager beanManager;
private final Map<Class,BeanMetaData> listeners = new ConcurrentHashMap<Class, BeanMetaData>();
public static BeanManagerListenerFactory fromBeanManagerReference(Object beanManagerReference) {
return new BeanManagerListenerFactory( ( BeanManager ) beanManagerReference );
}
public BeanManagerListenerFactory(BeanManager beanManager) {
this.beanManager = beanManager;
}
@Override
public <T> T buildListener(Class<T> listenerClass) {
BeanMetaData<T> beanMetaData = listeners.get( listenerClass );
if ( beanMetaData == null ) {
beanMetaData = new BeanMetaData<T>( listenerClass );
listeners.put( listenerClass, beanMetaData );
}
return beanMetaData.instance;
}
@Override
public void release() {
for ( BeanMetaData beanMetaData : listeners.values() ) {
beanMetaData.release();
}
listeners.clear();
}
private class BeanMetaData<T> {
private final InjectionTarget<T> injectionTarget;
private final CreationalContext<T> creationalContext;
private final T instance;
private BeanMetaData(Class<T> listenerClass) {
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( listenerClass );
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
this.creationalContext = beanManager.createCreationalContext( null );
this.instance = injectionTarget.produce( creationalContext );
injectionTarget.inject( this.instance, creationalContext );
injectionTarget.postConstruct( this.instance );
}
private void release() {
injectionTarget.preDestroy( instance );
injectionTarget.dispose( instance );
creationalContext.release();
}
}
}

View File

@ -25,33 +25,36 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XMethod; import org.hibernate.annotations.common.reflection.XMethod;
import org.hibernate.jpa.event.spi.jpa.Callback; import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory; import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
/** /**
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a> * EntityCallbackBuilder implementation using HCANN ReflectionManager. "legacy" in that
* we want to move to Jandex instead.
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class LegacyCallbackProcessor implements CallbackProcessor { public class CallbackBuilderLegacyImpl implements CallbackBuilder {
private static final Logger log = Logger.getLogger( LegacyCallbackProcessor.class ); private static final Logger log = Logger.getLogger( CallbackBuilderLegacyImpl.class );
private final ListenerFactory jpaListenerFactory; private final ListenerFactory jpaListenerFactory;
private final ReflectionManager reflectionManager; private final ReflectionManager reflectionManager;
public LegacyCallbackProcessor(ListenerFactory jpaListenerFactory, ReflectionManager reflectionManager) { public CallbackBuilderLegacyImpl(ListenerFactory jpaListenerFactory, ReflectionManager reflectionManager) {
this.jpaListenerFactory = jpaListenerFactory; this.jpaListenerFactory = jpaListenerFactory;
this.reflectionManager = reflectionManager; this.reflectionManager = reflectionManager;
} }
@Override @Override
public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl callbackRegistry) { public void buildCallbacksForEntity(String entityClassName, CallbackRegistrar callbackRegistrar) {
final String entityClassName = (String) entityObject;
try { try {
final XClass entityXClass = reflectionManager.classForName( entityClassName ); final XClass entityXClass = reflectionManager.classForName( entityClassName );
final Class entityClass = reflectionManager.toClass( entityXClass ); final Class entityClass = reflectionManager.toClass( entityXClass );
for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) { for ( CallbackType callbackType : CallbackType.values() ) {
if ( callbackRegistry.hasRegisteredCallbacks( entityClass, annotationClass ) ) { if ( callbackRegistrar.hasRegisteredCallbacks( entityClass, callbackType ) ) {
// this most likely means we have a class mapped multiple times using the hbm.xml // this most likely means we have a class mapped multiple times using the hbm.xml
// "entity name" feature // "entity name" feature
log.debugf( log.debugf(
@ -59,12 +62,12 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
"assuming this means the class was mapped twice " + "assuming this means the class was mapped twice " +
"(using hbm.xml entity-name support) - skipping subsequent registrations", "(using hbm.xml entity-name support) - skipping subsequent registrations",
entityClassName, entityClassName,
annotationClass.getSimpleName() callbackType.getCallbackAnnotation().getSimpleName()
); );
continue; continue;
} }
final Callback[] callbacks = resolveCallbacks( entityXClass, annotationClass, reflectionManager ); final Callback[] callbacks = resolveCallbacks( entityXClass, callbackType, reflectionManager );
callbackRegistry.addEntityCallbacks( entityClass, annotationClass, callbacks ); callbackRegistrar.registerCallbacks( entityClass, callbacks );
} }
} }
catch (ClassLoadingException e) { catch (ClassLoadingException e) {
@ -72,7 +75,12 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
} }
} }
public Callback[] resolveCallbacks(XClass beanClass, Class annotation, ReflectionManager reflectionManager) { @Override
public void release() {
// nothign to do
}
public Callback[] resolveCallbacks(XClass beanClass, CallbackType callbackType, ReflectionManager reflectionManager) {
List<Callback> callbacks = new ArrayList<Callback>(); List<Callback> callbacks = new ArrayList<Callback>();
List<String> callbacksMethodNames = new ArrayList<String>(); //used to track overridden methods List<String> callbacksMethodNames = new ArrayList<String>(); //used to track overridden methods
List<Class> orderedListeners = new ArrayList<Class>(); List<Class> orderedListeners = new ArrayList<Class>();
@ -83,26 +91,26 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
Callback callback = null; Callback callback = null;
List<XMethod> methods = currentClazz.getDeclaredMethods(); List<XMethod> methods = currentClazz.getDeclaredMethods();
for ( final XMethod xMethod : methods ) { for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( annotation ) ) { if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
Method method = reflectionManager.toMethod( xMethod ); Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName(); final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) { if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method //overridden method, remove the superclass overridden method
if ( callback == null ) { if ( callback == null ) {
callback = new EntityCallback( method ); callback = new EntityCallback( method, callbackType );
Class returnType = method.getReturnType(); Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes(); Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) { if ( returnType != Void.TYPE || args.length != 0 ) {
throw new RuntimeException( throw new RuntimeException(
"Callback methods annotated on the bean class must return void and take no arguments: " + annotation "Callback methods annotated on the bean class must return void and take no arguments: "
.getName() + " - " + xMethod + callbackType.getCallbackAnnotation().getName() + " - " + xMethod
); );
} }
method.setAccessible( true ); method.setAccessible( true );
log.debugf( log.debugf(
"Adding %s as %s callback for entity %s", "Adding %s as %s callback for entity %s",
methodName, methodName,
annotation.getSimpleName(), callbackType.getCallbackAnnotation().getSimpleName(),
beanClass.getName() beanClass.getName()
); );
callbacks.add( 0, callback ); //superclass first callbacks.add( 0, callback ); //superclass first
@ -111,7 +119,7 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
else { else {
throw new PersistenceException( throw new PersistenceException(
"You can only annotate one callback method with " "You can only annotate one callback method with "
+ annotation.getName() + " in bean class: " + beanClass.getName() + callbackType.getCallbackAnnotation().getName() + " in bean class: " + beanClass.getName()
); );
} }
} }
@ -152,20 +160,24 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
callbacksMethodNames = new ArrayList<String>(); callbacksMethodNames = new ArrayList<String>();
List<XMethod> methods = xListener.getDeclaredMethods(); List<XMethod> methods = xListener.getDeclaredMethods();
for ( final XMethod xMethod : methods ) { for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( annotation ) ) { if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
final Method method = reflectionManager.toMethod( xMethod ); final Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName(); final String methodName = method.getName();
if ( !callbacksMethodNames.contains( methodName ) ) { if ( !callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method //overridden method, remove the superclass overridden method
if ( callback == null ) { if ( callback == null ) {
callback = new ListenerCallback( jpaListenerFactory.buildListener( listener ), method ); callback = new ListenerCallback(
jpaListenerFactory.buildListener( listener ),
method,
callbackType
);
Class returnType = method.getReturnType(); Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes(); Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 1 ) { if ( returnType != Void.TYPE || args.length != 1 ) {
throw new PersistenceException( throw new PersistenceException(
"Callback methods annotated in a listener bean class must return void and take one argument: " + annotation "Callback methods annotated in a listener bean class must return void and take one argument: "
.getName() + " - " + method + callbackType.getCallbackAnnotation().getName() + " - " + method
); );
} }
if ( !method.isAccessible() ) { if ( !method.isAccessible() ) {
@ -174,7 +186,7 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
log.debugf( log.debugf(
"Adding %s as %s callback for entity %s", "Adding %s as %s callback for entity %s",
methodName, methodName,
annotation.getSimpleName(), callbackType.getCallbackAnnotation().getSimpleName(),
beanClass.getName() beanClass.getName()
); );
callbacks.add( 0, callback ); // listeners first callbacks.add( 0, callback ); // listeners first
@ -182,8 +194,9 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
else { else {
throw new PersistenceException( throw new PersistenceException(
"You can only annotate one callback method with " "You can only annotate one callback method with "
+ annotation.getName() + " in bean class: " + beanClass.getName() + " and callback listener: " + callbackType.getCallbackAnnotation().getName()
+ listener.getName() + " in bean class: " + beanClass.getName()
+ " and callback listener: " + listener.getName()
); );
} }
} }
@ -232,9 +245,4 @@ public class LegacyCallbackProcessor implements CallbackProcessor {
} }
} }
} }
@Override
public void release() {
// nothing to do here
}
} }

View File

@ -1,41 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
/**
* Delegate for interpreting, parsing and processing callbacks
*
* @author Steve Ebersole
*/
public interface CallbackProcessor {
public static final Class[] CALLBACK_ANNOTATION_CLASSES = new Class[] {
PreUpdate.class, PostUpdate.class,
PrePersist.class, PostPersist.class,
PreRemove.class, PostRemove.class,
PostLoad.class
};
/**
* Ugh, Object to account for Configuration/Metamodel split. Should eventually be EntityBinding from
* metamodel code base. Currently each Integrator method passes in different type and each impl
* interprets differently.
*
* @param entityObject
* @param registry
*/
public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl registry);
public void release();
}

View File

@ -8,16 +8,11 @@ package org.hibernate.jpa.event.internal.jpa;
import java.util.HashMap; import java.util.HashMap;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
import org.hibernate.jpa.event.spi.jpa.Callback; import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry; import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
/** /**
* Keep track of all lifecycle callbacks and listeners for a given persistence unit * Keep track of all lifecycle callbacks and listeners for a given persistence unit
@ -26,7 +21,7 @@ import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@SuppressWarnings({"unchecked", "serial"}) @SuppressWarnings({"unchecked", "serial"})
public class CallbackRegistryImpl implements CallbackRegistry { public class CallbackRegistryImpl implements CallbackRegistry, CallbackBuilder.CallbackRegistrar {
private HashMap<Class, Callback[]> preCreates = new HashMap<Class, Callback[]>(); private HashMap<Class, Callback[]> preCreates = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> postCreates = new HashMap<Class, Callback[]>(); private HashMap<Class, Callback[]> postCreates = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> preRemoves = new HashMap<Class, Callback[]>(); private HashMap<Class, Callback[]> preRemoves = new HashMap<Class, Callback[]>();
@ -36,13 +31,27 @@ public class CallbackRegistryImpl implements CallbackRegistry {
private HashMap<Class, Callback[]> postLoads = new HashMap<Class, Callback[]>(); private HashMap<Class, Callback[]> postLoads = new HashMap<Class, Callback[]>();
@Override @Override
public void preCreate(Object bean) { public boolean hasRegisteredCallbacks(Class entityClass, CallbackType callbackType) {
callback( preCreates.get( bean.getClass() ), bean ); final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbackType );
return notEmpty( map.get( entityClass ) );
} }
@Override @Override
public boolean hasPostCreateCallbacks(Class entityClass) { public void registerCallbacks(Class entityClass, Callback[] callbacks) {
return notEmpty( preCreates.get( entityClass ) ); if ( callbacks == null || callbacks.length == 0 ) {
return;
}
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbacks[0].getCallbackType() );
if ( map.containsKey( entityClass ) ) {
throw new PersistenceException( "Error build callback listeners; entity [" + entityClass.getName() + " was already processed" );
}
map.put( entityClass, callbacks );
}
@Override
public void preCreate(Object bean) {
callback( preCreates.get( bean.getClass() ), bean );
} }
private boolean notEmpty(Callback[] callbacks) { private boolean notEmpty(Callback[] callbacks) {
@ -59,11 +68,6 @@ public class CallbackRegistryImpl implements CallbackRegistry {
return callback( preUpdates.get( bean.getClass() ), bean ); return callback( preUpdates.get( bean.getClass() ), bean );
} }
@Override
public boolean hasPostUpdateCallbacks(Class entityClass) {
return notEmpty( postUpdates.get( entityClass ) );
}
@Override @Override
public void postUpdate(Object bean) { public void postUpdate(Object bean) {
callback( postUpdates.get( bean.getClass() ), bean ); callback( postUpdates.get( bean.getClass() ), bean );
@ -74,11 +78,6 @@ public class CallbackRegistryImpl implements CallbackRegistry {
callback( preRemoves.get( bean.getClass() ), bean ); callback( preRemoves.get( bean.getClass() ), bean );
} }
@Override
public boolean hasPostRemoveCallbacks(Class entityClass) {
return notEmpty( postRemoves.get( entityClass ) );
}
@Override @Override
public void postRemove(Object bean) { public void postRemove(Object bean) {
callback( postRemoves.get( bean.getClass() ), bean ); callback( postRemoves.get( bean.getClass() ), bean );
@ -101,56 +100,36 @@ public class CallbackRegistryImpl implements CallbackRegistry {
} }
} }
@Override private HashMap<Class, Callback[]> determineAppropriateCallbackMap(CallbackType callbackType) {
public boolean hasRegisteredCallbacks(Class entityClass, Class annotationClass) { if ( callbackType == CallbackType.PRE_PERSIST ) {
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( annotationClass );
return map != null && map.containsKey( entityClass );
}
/**
* Great care should be taken calling this. Not a fan of it being public, but that is needed because of
* @param entityClass
* @param annotationClass
* @param callbacks
*/
public void addEntityCallbacks(Class entityClass, Class annotationClass, Callback[] callbacks) {
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( annotationClass );
if ( map.containsKey( entityClass ) ) {
throw new PersistenceException( "Error build callback listeners; entity [" + entityClass.getName() + " was already processed" );
}
map.put( entityClass, callbacks );
}
private HashMap<Class, Callback[]> determineAppropriateCallbackMap(Class annotationClass) {
if ( PrePersist.class.equals( annotationClass ) ) {
return preCreates; return preCreates;
} }
if ( PostPersist.class.equals( annotationClass ) ) { if ( callbackType == CallbackType.POST_PERSIST ) {
return postCreates; return postCreates;
} }
if ( PreRemove.class.equals( annotationClass ) ) { if ( callbackType == CallbackType.PRE_REMOVE ) {
return preRemoves; return preRemoves;
} }
if ( PostRemove.class.equals( annotationClass ) ) { if ( callbackType == CallbackType.POST_REMOVE ) {
return postRemoves; return postRemoves;
} }
if ( PreUpdate.class.equals( annotationClass ) ) { if ( callbackType == CallbackType.PRE_UPDATE ) {
return preUpdates; return preUpdates;
} }
if ( PostUpdate.class.equals( annotationClass ) ) { if ( callbackType == CallbackType.POST_UPDATE ) {
return postUpdates; return postUpdates;
} }
if ( PostLoad.class.equals( annotationClass ) ) { if ( callbackType == CallbackType.POST_LOAD ) {
return postLoads; return postLoads;
} }
throw new PersistenceException( "Unrecognized JPA callback annotation [" + annotationClass.getName() + "]" ); throw new PersistenceException( "Unrecognized JPA callback type [" + callbackType + "]" );
} }
public void release() { public void release() {
@ -165,4 +144,54 @@ public class CallbackRegistryImpl implements CallbackRegistry {
postLoads.clear(); postLoads.clear();
} }
// deprecations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean hasPostCreateCallbacks(Class entityClass) {
return notEmpty( preCreates.get( entityClass ) );
}
@Override
public boolean hasPostUpdateCallbacks(Class entityClass) {
return notEmpty( postUpdates.get( entityClass ) );
}
@Override
public boolean hasPostRemoveCallbacks(Class entityClass) {
return notEmpty( postRemoves.get( entityClass ) );
}
@Override
public boolean hasRegisteredCallbacks(Class entityClass, Class annotationClass) {
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( toCallbackType( annotationClass ) );
return map != null && map.containsKey( entityClass );
}
private CallbackType toCallbackType(Class annotationClass) {
if ( annotationClass == CallbackType.POST_LOAD.getCallbackAnnotation() ) {
return CallbackType.POST_LOAD;
}
else if ( annotationClass == CallbackType.PRE_PERSIST.getCallbackAnnotation() ) {
return CallbackType.PRE_PERSIST;
}
else if ( annotationClass == CallbackType.POST_PERSIST.getCallbackAnnotation() ) {
return CallbackType.POST_PERSIST;
}
else if ( annotationClass == CallbackType.PRE_UPDATE.getCallbackAnnotation() ) {
return CallbackType.PRE_UPDATE;
}
else if ( annotationClass == CallbackType.POST_UPDATE.getCallbackAnnotation() ) {
return CallbackType.POST_UPDATE;
}
else if ( annotationClass == CallbackType.PRE_REMOVE.getCallbackAnnotation() ) {
return CallbackType.PRE_REMOVE;
}
else if ( annotationClass == CallbackType.POST_REMOVE.getCallbackAnnotation() ) {
return CallbackType.POST_REMOVE;
}
throw new PersistenceException( "Unrecognized JPA callback annotation [" + annotationClass + "]" );
}
} }

View File

@ -10,6 +10,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.jpa.Callback; import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
/** /**
* Represents a JPA callback on the entity itself * Represents a JPA callback on the entity itself
@ -17,10 +18,11 @@ import org.hibernate.jpa.event.spi.jpa.Callback;
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a> * @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityCallback implements Callback { public class EntityCallback extends AbstractCallback implements Callback {
private Method callbackMethod; private final Method callbackMethod;
public EntityCallback(Method callbackMethod) { public EntityCallback(Method callbackMethod, CallbackType callbackType) {
super( callbackType );
this.callbackMethod = callbackMethod; this.callbackMethod = callbackMethod;
} }
@ -43,9 +45,4 @@ public class EntityCallback implements Callback {
throw new RuntimeException( e ); throw new RuntimeException( e );
} }
} }
@Override
public boolean isActive() {
return true;
}
} }

View File

@ -10,6 +10,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.jpa.Callback; import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.jpa.Listener;
/** /**
* Represents a JPA callback using a dedicated listener * Represents a JPA callback using a dedicated listener
@ -17,11 +19,12 @@ import org.hibernate.jpa.event.spi.jpa.Callback;
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a> * @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ListenerCallback implements Callback { public class ListenerCallback extends AbstractCallback implements Callback {
private final Method callbackMethod; private final Method callbackMethod;
private final Object listenerInstance; private final Listener listenerInstance;
public ListenerCallback(Object listenerInstance, Method callbackMethod) { public ListenerCallback(Listener listenerInstance, Method callbackMethod, CallbackType callbackType) {
super( callbackType );
this.listenerInstance = listenerInstance; this.listenerInstance = listenerInstance;
this.callbackMethod = callbackMethod; this.callbackMethod = callbackMethod;
} }
@ -29,7 +32,7 @@ public class ListenerCallback implements Callback {
@Override @Override
public boolean performCallback(Object entity) { public boolean performCallback(Object entity) {
try { try {
callbackMethod.invoke( listenerInstance, entity ); callbackMethod.invoke( listenerInstance.getListener(), entity );
return true; return true;
} }
catch (InvocationTargetException e) { catch (InvocationTargetException e) {
@ -45,9 +48,4 @@ public class ListenerCallback implements Callback {
throw new RuntimeException( e ); throw new RuntimeException( e );
} }
} }
@Override
public boolean isActive() {
return true;
}
} }

View File

@ -0,0 +1,122 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import org.hibernate.jpa.event.spi.jpa.Listener;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.jboss.logging.Logger;
/**
* CDI-based implementation of the ListenerFactory contract. This implementation
* delayes access to the CDI BeanManager until first need.
* <p/>
* This class appears unused, but that is because it is only referenced via reflection from
* {@link org.hibernate.jpa.event.spi.jpa.ListenerFactoryBuilder}.
*
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
public class ListenerFactoryBeanManagerDelayedImpl implements ListenerFactory {
private static final Logger log = Logger.getLogger( ListenerFactoryBeanManagerDelayedImpl.class );
private final BeanManager beanManager;
private final Map<Class,ListenerImpl> listenerMap = new ConcurrentHashMap<Class, ListenerImpl>();
/**
* Used via reflection from ListenerFactoryBuilder, the intent being to isolate CDI dependency
* to just this class and its delegates in the case that a BeanManager is passed.
*
* @param reference The BeanManager reference
*
* @return A instantiated ListenerFactoryBeanManagerImpl
*/
public static ListenerFactoryBeanManagerDelayedImpl fromBeanManagerReference(Object reference) {
return new ListenerFactoryBeanManagerDelayedImpl( (BeanManager) reference );
}
public ListenerFactoryBeanManagerDelayedImpl(BeanManager beanManager) {
this.beanManager = beanManager;
log.debugf( "Delayed access requested to CDI BeanManager : " + beanManager );
}
@Override
@SuppressWarnings("unchecked")
public <T> Listener<T> buildListener(Class<T> listenerClass) {
ListenerImpl listenerImpl = listenerMap.get( listenerClass );
if ( listenerImpl == null ) {
listenerImpl = new ListenerImpl( listenerClass );
listenerMap.put( listenerClass, listenerImpl );
}
return (Listener<T>) listenerImpl;
}
@Override
public void release() {
for ( ListenerImpl listenerImpl : listenerMap.values() ) {
listenerImpl.release();
}
listenerMap.clear();
}
private class ListenerImpl<T> implements Listener<T> {
private final Class<T> listenerClass;
private boolean initialized = false;
private InjectionTarget<T> injectionTarget;
private CreationalContext<T> creationalContext;
private T listenerInstance;
private ListenerImpl(Class<T> listenerClass) {
this.listenerClass = listenerClass;
log.debugf( "Delayed CDI listener built : " + listenerClass );
}
public void initialize() {
log.debug( "Initializing delayed CDI listener on first use : " + listenerClass );
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( listenerClass );
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
this.creationalContext = beanManager.createCreationalContext( null );
this.listenerInstance = injectionTarget.produce( creationalContext );
injectionTarget.inject( this.listenerInstance, creationalContext );
injectionTarget.postConstruct( this.listenerInstance );
this.initialized = true;
}
@Override
public T getListener() {
if ( !initialized ) {
initialize();
}
return listenerInstance;
}
public void release() {
if ( !initialized ) {
log.debug( "Skipping release for CDI listener [" + listenerClass + "] as it was not initialized" );
return;
}
log.debug( "Releasing CDI listener : " + listenerClass );
injectionTarget.preDestroy( listenerInstance );
injectionTarget.dispose( listenerInstance );
creationalContext.release();
}
}
}

View File

@ -0,0 +1,100 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import org.hibernate.jpa.event.spi.jpa.Listener;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.jboss.logging.Logger;
/**
* CDI-based implementation of the ListenerFactory contract. This implementation works in
* the JPA standard prescribed manner.
* <p/>
* This class appears unused, but that is because it is only referenced via reflection from
* {@link org.hibernate.jpa.event.spi.jpa.ListenerFactoryBuilder}.
*
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
public class ListenerFactoryBeanManagerStandardImpl implements ListenerFactory {
private static final Logger log = Logger.getLogger( ListenerFactoryBeanManagerStandardImpl.class );
private final BeanManager beanManager;
private final Map<Class,ListenerImpl> listenerMap = new ConcurrentHashMap<Class, ListenerImpl>();
/**
* Used via reflection from ListenerFactoryBuilder, the intent being to isolate CDI dependency
* to just this class and its delegates in the case that a BeanManager is passed.
*
* @param reference The BeanManager reference
*
* @return A instantiated ListenerFactoryBeanManagerImpl
*/
public static ListenerFactoryBeanManagerStandardImpl fromBeanManagerReference(Object reference) {
return new ListenerFactoryBeanManagerStandardImpl( (BeanManager) reference );
}
public ListenerFactoryBeanManagerStandardImpl(BeanManager beanManager) {
this.beanManager = beanManager;
log.debugf( "Standard access requested to CDI BeanManager : " + beanManager );
}
@Override
@SuppressWarnings("unchecked")
public <T> Listener<T> buildListener(Class<T> listenerClass) {
ListenerImpl listenerImpl = listenerMap.get( listenerClass );
if ( listenerImpl == null ) {
listenerImpl = new ListenerImpl( listenerClass );
listenerMap.put( listenerClass, listenerImpl );
}
return (Listener<T>) listenerImpl;
}
@Override
public void release() {
for ( ListenerImpl listenerImpl : listenerMap.values() ) {
listenerImpl.release();
}
listenerMap.clear();
}
private class ListenerImpl<T> implements Listener<T> {
private final InjectionTarget<T> injectionTarget;
private final CreationalContext<T> creationalContext;
private final T listenerInstance;
private ListenerImpl(Class<T> listenerClass) {
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( listenerClass );
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
this.creationalContext = beanManager.createCreationalContext( null );
this.listenerInstance = injectionTarget.produce( creationalContext );
injectionTarget.inject( this.listenerInstance, creationalContext );
injectionTarget.postConstruct( this.listenerInstance );
}
@Override
public T getListener() {
return listenerInstance;
}
public void release() {
injectionTarget.preDestroy( listenerInstance );
injectionTarget.dispose( listenerInstance );
creationalContext.release();
}
}
}

View File

@ -0,0 +1,66 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.PersistenceException;
import org.hibernate.jpa.event.spi.jpa.Listener;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
/**
* Standard implementation of the ListenerFactory contract using simple instantiation.
*
* @author Steve Ebersole
*/
public class ListenerFactoryStandardImpl implements ListenerFactory {
private final ConcurrentHashMap<Class, ListenerImpl> listenerInstances = new ConcurrentHashMap<Class, ListenerImpl>();
@Override
@SuppressWarnings("unchecked")
public <T> Listener<T> buildListener(Class<T> listenerClass) {
ListenerImpl listenerImpl = listenerInstances.get( listenerClass );
if ( listenerImpl == null ) {
try {
T listenerInstance = listenerClass.newInstance();
listenerImpl = new ListenerImpl( listenerInstance );
}
catch (Exception e) {
throw new PersistenceException(
"Unable to create instance of " + listenerClass.getName() + " as a JPA callback listener",
e
);
}
ListenerImpl existing = listenerInstances.putIfAbsent(
listenerClass,
listenerImpl
);
if ( existing != null ) {
listenerImpl = existing;
}
}
return (Listener<T>) listenerImpl;
}
@Override
public void release() {
listenerInstances.clear();
}
private static class ListenerImpl<T> implements Listener<T> {
private final T listenerInstance;
public ListenerImpl(T listenerInstance) {
this.listenerInstance = listenerInstance;
}
@Override
public T getListener() {
return listenerInstance;
}
}
}

View File

@ -1,50 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.internal.jpa;
import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.PersistenceException;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
/**
* Standard implementation of the ListenerFactory contract using simple instantiation. Listener instances
* are kept in a map keyed by Class to achieve singleton-ness.
*
* @author Steve Ebersole
*/
public class StandardListenerFactory implements ListenerFactory {
private final ConcurrentHashMap listenerInstances = new ConcurrentHashMap();
@Override
@SuppressWarnings("unchecked")
public <T> T buildListener(Class<T> listenerClass) {
Object listenerInstance = listenerInstances.get( listenerClass );
if ( listenerInstance == null ) {
try {
listenerInstance = listenerClass.newInstance();
}
catch (Exception e) {
throw new PersistenceException(
"Unable to create instance of " + listenerClass.getName() + " as a JPA callback listener",
e
);
}
Object existing = listenerInstances.putIfAbsent( listenerClass, listenerInstance );
if ( existing != null ) {
listenerInstance = existing;
}
}
return (T) listenerInstance;
}
@Override
public void release() {
listenerInstances.clear();
}
}

View File

@ -40,12 +40,12 @@ import org.hibernate.jpa.event.internal.core.JpaPostLoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostUpdateEventListener; import org.hibernate.jpa.event.internal.core.JpaPostUpdateEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveEventListener; import org.hibernate.jpa.event.internal.core.JpaSaveEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveOrUpdateEventListener; import org.hibernate.jpa.event.internal.core.JpaSaveOrUpdateEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackProcessor;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl; import org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl;
import org.hibernate.jpa.event.internal.jpa.LegacyCallbackProcessor; import org.hibernate.jpa.event.internal.jpa.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.internal.jpa.StandardListenerFactory; import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory; import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.hibernate.jpa.event.spi.jpa.ListenerFactoryBuilder;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.service.spi.SessionFactoryServiceRegistry;
@ -57,7 +57,7 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistry;
*/ */
public class JpaIntegrator implements Integrator { public class JpaIntegrator implements Integrator {
private ListenerFactory jpaListenerFactory; private ListenerFactory jpaListenerFactory;
private CallbackProcessor callbackProcessor; private CallbackBuilder callbackBuilder;
private CallbackRegistryImpl callbackRegistry; private CallbackRegistryImpl callbackRegistry;
private static final DuplicationStrategy JPA_DUPLICATION_STRATEGY = new JPADuplicationStrategy(); private static final DuplicationStrategy JPA_DUPLICATION_STRATEGY = new JPADuplicationStrategy();
@ -126,18 +126,14 @@ public class JpaIntegrator implements Integrator {
.getReflectionManager(); .getReflectionManager();
this.callbackRegistry = new CallbackRegistryImpl(); this.callbackRegistry = new CallbackRegistryImpl();
final Object beanManagerRef = sessionFactory.getSessionFactoryOptions().getBeanManagerReference(); this.jpaListenerFactory = ListenerFactoryBuilder.buildListenerFactory( sessionFactory.getSessionFactoryOptions() );
this.jpaListenerFactory = beanManagerRef == null this.callbackBuilder = new CallbackBuilderLegacyImpl( jpaListenerFactory, reflectionManager );
? new StandardListenerFactory()
: buildBeanManagerListenerFactory( beanManagerRef );
this.callbackProcessor = new LegacyCallbackProcessor( jpaListenerFactory, reflectionManager );
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) { for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) { if ( persistentClass.getClassName() == null ) {
// we can have non java class persisted by hibernate // we can have non java class persisted by hibernate
continue; continue;
} }
callbackProcessor.processCallbacksForEntity( persistentClass.getClassName(), callbackRegistry ); callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
} }
for ( EventType eventType : EventType.values() ) { for ( EventType eventType : EventType.values() ) {
@ -191,8 +187,8 @@ public class JpaIntegrator implements Integrator {
if ( callbackRegistry != null ) { if ( callbackRegistry != null ) {
callbackRegistry.release(); callbackRegistry.release();
} }
if ( callbackProcessor != null ) { if ( callbackBuilder != null ) {
callbackProcessor.release(); callbackBuilder.release();
} }
if ( jpaListenerFactory != null ) { if ( jpaListenerFactory != null ) {
jpaListenerFactory.release(); jpaListenerFactory.release();

View File

@ -9,12 +9,29 @@ package org.hibernate.jpa.event.spi.jpa;
import java.io.Serializable; import java.io.Serializable;
/** /**
* Represents a JPA event callback. * Represents a JPA event callback (the method).
* <p/>
* Generally there are 2 flavors of this; either an annotated method on the entity itself
* or an annotated method on a separate "listener" class. This contract unifies both of
* these cases.
* *
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a> * @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface Callback extends Serializable { public interface Callback extends Serializable {
/**
* Is this callback active (will it do anything)?
*
* @return {@code true} if the callback is active, {@code false} otherwise.
*
* @deprecated I can actually find no usages of this method and have no idea
* why it is here :)
*/
@Deprecated
boolean isActive();
CallbackType getCallbackType();
/** /**
* Contract for performing the callback * Contract for performing the callback
* *
@ -22,12 +39,5 @@ public interface Callback extends Serializable {
* *
* @return Did a callback actually happen? * @return Did a callback actually happen?
*/ */
public boolean performCallback(Object entity); boolean performCallback(Object entity);
/**
* Is this callback active (will it do anything)?
*
* @return
*/
public boolean isActive();
} }

View File

@ -0,0 +1,32 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.spi.jpa;
/**
* Contract for walking an entity hierarchy and building a list of JPA callbacks
*
* @author Steve Ebersole
*/
public interface CallbackBuilder {
/**
* Represents the target of JPA callback registrations as part the EntityCallbackBuilder
*/
interface CallbackRegistrar extends CallbackRegistry {
/**
* Register the callback against the given entity.
*
* @param entityClass The entity Class to register the Callbacks against
* @param callbacks The Callbacks to register against the given entity Class
*/
void registerCallbacks(Class entityClass, Callback[] callbacks);
}
void buildCallbacksForEntity(String entityName, CallbackRegistrar callbackRegistrar);
void release();
}

View File

@ -12,19 +12,52 @@ import java.io.Serializable;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface CallbackRegistry extends Serializable { public interface CallbackRegistry extends Serializable {
/**
* Do we have any registered callbacks of the given type for the given entity?
*
* @param entityClass The entity Class to check against
* @param callbackType The type of callback to look for
*
* @return {@code true} indicates there are already registered callbacks of
* that type for that class; {@code false} indicates there are not.
*/
boolean hasRegisteredCallbacks(Class entityClass, CallbackType callbackType);
void preCreate(Object entity); void preCreate(Object entity);
boolean hasPostCreateCallbacks(Class entityClass);
void postCreate(Object entity); void postCreate(Object entity);
boolean preUpdate(Object entity); boolean preUpdate(Object entity);
boolean hasPostUpdateCallbacks(Class entityClass);
void postUpdate(Object entity); void postUpdate(Object entity);
void preRemove(Object entity); void preRemove(Object entity);
boolean hasPostRemoveCallbacks(Class entityClass);
void postRemove(Object entity); void postRemove(Object entity);
boolean postLoad(Object entity); boolean postLoad(Object entity);
/**
* @deprecated Use {@link #hasRegisteredCallbacks(Class, CallbackType)} instead passing
* {@link CallbackType#POST_PERSIST}
*/
@Deprecated
boolean hasPostCreateCallbacks(Class entityClass);
/**
* @deprecated Use {@link #hasRegisteredCallbacks(Class, CallbackType)} instead passing
* {@link CallbackType#POST_UPDATE}
*/
@Deprecated
boolean hasPostUpdateCallbacks(Class entityClass);
/**
* @deprecated Use {@link #hasRegisteredCallbacks(Class, CallbackType)} instead passing
* {@link CallbackType#POST_REMOVE}
*/
@Deprecated
boolean hasPostRemoveCallbacks(Class entityClass);
/**
* @deprecated Use {@link #hasRegisteredCallbacks(Class, CallbackType)} instead.
*/
@Deprecated
boolean hasRegisteredCallbacks(Class entityClass, Class annotationClass); boolean hasRegisteredCallbacks(Class entityClass, Class annotationClass);
} }

View File

@ -4,10 +4,9 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.jpa.event.internal.jpa; package org.hibernate.jpa.event.spi.jpa;
import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener; import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
/** /**
* Contract for injecting the registry of Callbacks into event listeners. * Contract for injecting the registry of Callbacks into event listeners.
@ -21,5 +20,5 @@ public interface CallbackRegistryConsumer extends HibernateEntityManagerEventLis
* *
* @param callbackRegistry The CallbackRegistry * @param callbackRegistry The CallbackRegistry
*/ */
public void injectCallbackRegistry(CallbackRegistry callbackRegistry); void injectCallbackRegistry(CallbackRegistry callbackRegistry);
} }

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.spi.jpa;
import java.lang.annotation.Annotation;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
/**
* @author Steve Ebersole
*/
public enum CallbackType {
PRE_UPDATE( PreUpdate.class ),
POST_UPDATE( PostUpdate.class ),
PRE_PERSIST( PrePersist.class ),
POST_PERSIST( PostPersist.class ),
PRE_REMOVE( PreRemove.class ),
POST_REMOVE( PostRemove.class ),
POST_LOAD( PostLoad.class )
;
private Class<? extends Annotation> callbackAnnotation;
CallbackType(Class<? extends Annotation> callbackAnnotation) {
this.callbackAnnotation = callbackAnnotation;
}
public Class<? extends Annotation> getCallbackAnnotation() {
return callbackAnnotation;
}
}

View File

@ -0,0 +1,17 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.spi.jpa;
/**
* Encapsulates access to the listener instance for listener callbacks
* ({@link javax.persistence.EntityListeners}).
*
* @author Steve Ebersole
*/
public interface Listener<T> {
T getListener();
}

View File

@ -7,12 +7,16 @@
package org.hibernate.jpa.event.spi.jpa; package org.hibernate.jpa.event.spi.jpa;
/** /**
* Factory for building instances user-specified event listeners. * Contract for building instances of JPA callback listener classes.
* <p/>
* Listener instances should be uniqued by Class such that the same instance is
* returned for any calls to {@link #buildListener} with the same class.
*
* @see javax.persistence.EntityListeners
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ListenerFactory { public interface ListenerFactory {
public <T> T buildListener(Class<T> listenerClass); <T> Listener<T> buildListener(Class<T> listenerClass);
void release();
public void release();
} }

View File

@ -0,0 +1,95 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.event.spi.jpa;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.hibernate.HibernateException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.event.internal.jpa.ListenerFactoryStandardImpl;
/**
* Builder for ListenerFactory based on configuration options
*
* @author Steve Ebersole
*/
public class ListenerFactoryBuilder {
public static ListenerFactory buildListenerFactory(SessionFactoryOptions options) {
final Object beanManagerRef = options.getBeanManagerReference();
if ( beanManagerRef == null ) {
return new ListenerFactoryStandardImpl();
}
else {
final boolean delayAccessToCdi = options.getServiceRegistry()
.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DELAY_CDI_ACCESS, StandardConverters.BOOLEAN, false );
if ( delayAccessToCdi ) {
return buildDelayedBeanManagerListenerFactory( beanManagerRef );
}
else {
return buildStandardBeanManagerListenerFactory( beanManagerRef );
}
}
}
private static final String CDI_LISTENER_FACTORY_STANDARD_CLASS = "org.hibernate.jpa.event.internal.jpa.ListenerFactoryBeanManagerStandardImpl";
private static final String CDI_LISTENER_FACTORY_DELAYED_CLASS = "org.hibernate.jpa.event.internal.jpa.ListenerFactoryBeanManagerDelayedImpl";
private static final String CDI_LISTENER_FACTORY_METHOD_NAME = "fromBeanManagerReference";
private static ListenerFactory buildStandardBeanManagerListenerFactory(Object beanManagerRef) {
return buildBeanManagerListenerFactory( beanManagerRef, CDI_LISTENER_FACTORY_STANDARD_CLASS );
}
private static ListenerFactory buildDelayedBeanManagerListenerFactory(Object beanManagerRef) {
return buildBeanManagerListenerFactory( beanManagerRef, CDI_LISTENER_FACTORY_DELAYED_CLASS );
}
@SuppressWarnings("unchecked")
private static ListenerFactory buildBeanManagerListenerFactory(
Object beanManagerRef,
String listenerClass) {
try {
// specifically using our ClassLoader here...
final Class beanManagerListenerFactoryClass = ListenerFactoryBuilder.class.getClassLoader()
.loadClass( listenerClass );
final Method beanManagerListenerFactoryBuilderMethod = beanManagerListenerFactoryClass.getMethod(
CDI_LISTENER_FACTORY_METHOD_NAME,
Object.class
);
try {
return (ListenerFactory) beanManagerListenerFactoryBuilderMethod.invoke( null, beanManagerRef );
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
catch (ClassNotFoundException e) {
throw new HibernateException(
"Could not locate BeanManager ListenerFactory class [" + listenerClass + "] to handle CDI extensions",
e
);
}
catch (HibernateException e) {
throw e;
}
catch (Throwable e) {
throw new HibernateException(
"Could not access BeanManager ListenerFactory class [" + listenerClass + "] to handle CDI extensions",
e
);
}
}
}

View File

@ -1,3 +1,27 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2016, Red Hat Inc. 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 Inc.
*
* 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
*/
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
@ -18,9 +42,13 @@ import org.jboss.weld.bootstrap.api.Environments;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class BaseCDIIntegrationTest extends BaseEntityManagerFunctionalTestCase { public abstract class BaseCdiIntegrationTest extends BaseEntityManagerFunctionalTestCase {
private TestContainer testContainer; private TestContainer testContainer;
public TestContainer getTestContainer() {
return testContainer;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void addConfigOptions(Map options) { protected void addConfigOptions(Map options) {

View File

@ -1,3 +1,27 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2016, Red Hat Inc. 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 Inc.
*
* 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
*/
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
@ -6,9 +30,10 @@
*/ */
package org.hibernate.jpa.test.cdi; package org.hibernate.jpa.test.cdi;
import javax.enterprise.context.spi.CreationalContext; import java.text.SimpleDateFormat;
import javax.enterprise.inject.spi.AnnotatedType; import java.util.ArrayList;
import javax.enterprise.inject.spi.InjectionTarget; import java.util.Date;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EntityListeners; import javax.persistence.EntityListeners;
@ -16,10 +41,6 @@ import javax.persistence.EntityManager;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.PrePersist; import javax.persistence.PrePersist;
import javax.persistence.Table; import javax.persistence.Table;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.junit.Test; import org.junit.Test;
@ -28,7 +49,7 @@ import static org.junit.Assert.assertEquals;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BasicCDITest extends BaseCDIIntegrationTest { public class BasicCdiTest extends BaseCdiIntegrationTest {
private static int count; private static int count;
@Override @Override

View File

@ -0,0 +1,427 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2016, Red Hat Inc. 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 Inc.
*
* 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
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.test.cdi;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanAttributes;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.InjectionTargetFactory;
import javax.enterprise.inject.spi.InterceptionType;
import javax.enterprise.inject.spi.Interceptor;
import javax.enterprise.inject.spi.ObserverMethod;
import javax.enterprise.inject.spi.ProducerFactory;
import javax.inject.Inject;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import org.hibernate.jpa.AvailableSettings;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Steve Ebersole
*/
public class DelayedCdiTest extends BaseCdiIntegrationTest {
private BeanManagerImpl beanManager = new BeanManagerImpl();
private static int count;
@Override
public Class[] getCdiBeans() {
return new Class[] { EventQueue.class };
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { MyEntity.class };
}
@Override
protected void addConfigOptions(Map options) {
options.put( AvailableSettings.DELAY_CDI_ACCESS, "true" );
super.addConfigOptions( options );
}
@Override
protected BeanManager getBeanManager() {
// this is the BeanManager used to bootstrap Hibernate. Here
// we want this to be our custom BeanManagerImpl
return beanManager;
}
@Override
protected void afterEntityManagerFactoryBuilt() {
beanManager.delegate = getTestContainer().getBeanManager( getTestContainer().getDeployment().getBeanDeploymentArchives().iterator().next() );
}
@Test
@SuppressWarnings("unchecked")
public void testIt() {
count = 0;
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
em.persist( new MyEntity( 1 ) );
em.getTransaction().commit();
em.close();
assertEquals( 1, count );
em = getOrCreateEntityManager();
em.getTransaction().begin();
em.remove( em.getReference( MyEntity.class, 1 ) );
em.getTransaction().commit();
em.close();
}
@Entity
@EntityListeners( Monitor.class )
@Table(name = "my_entity")
public static class MyEntity {
private Integer id;
private String name;
public MyEntity() {
}
public MyEntity(Integer id) {
this.id = id;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class EventQueue {
private List<Event> events;
public void addEvent(Event anEvent) {
if ( events == null ) {
events = new ArrayList<Event>();
}
events.add( anEvent );
count++;
}
}
public static class Event {
private final String who;
private final String what;
private final String when;
public Event(String who, String what, String when) {
this.who = who;
this.what = what;
this.when = when;
}
public String getWho() {
return who;
}
public String getWhat() {
return what;
}
public String getWhen() {
return when;
}
}
public static class Monitor {
private final EventQueue eventQueue;
@Inject
public Monitor(EventQueue eventQueue) {
this.eventQueue = eventQueue;
}
@PrePersist
public void onCreate(Object entity) {
eventQueue.addEvent(
new Event( entity.toString(), "created", now() )
);
}
private String now() {
return new SimpleDateFormat().format( new Date() );
}
}
public static class BeanManagerImpl implements BeanManager {
private BeanManager delegate;
@Override
public Object getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx) {
return getDelegate().getReference( bean, beanType, ctx );
}
private BeanManager getDelegate() {
if ( delegate == null ) {
throw new RuntimeException( "Real BeanManager not yet known" );
}
return delegate;
}
@Override
public Object getInjectableReference(InjectionPoint ij, CreationalContext<?> ctx) {
return getDelegate().getInjectableReference( ij, ctx );
}
@Override
public <T> CreationalContext<T> createCreationalContext(Contextual<T> contextual) {
return getDelegate().createCreationalContext( contextual );
}
@Override
public Set<Bean<?>> getBeans(Type beanType, Annotation... qualifiers) {
return getDelegate().getBeans( beanType, qualifiers );
}
@Override
public Set<Bean<?>> getBeans(String name) {
return getDelegate().getBeans( name );
}
@Override
public Bean<?> getPassivationCapableBean(String id) {
return getDelegate().getPassivationCapableBean( id );
}
@Override
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans) {
return getDelegate().resolve( beans );
}
@Override
public void validate(InjectionPoint injectionPoint) {
getDelegate().validate( injectionPoint );
}
@Override
public void fireEvent(Object event, Annotation... qualifiers) {
getDelegate().fireEvent( event, qualifiers );
}
@Override
public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers) {
return getDelegate().resolveObserverMethods( event, qualifiers );
}
@Override
public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers) {
return getDelegate().resolveDecorators( types, qualifiers );
}
@Override
public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {
return getDelegate().resolveInterceptors( type, interceptorBindings );
}
@Override
public boolean isScope(Class<? extends Annotation> annotationType) {
return getDelegate().isScope( annotationType );
}
@Override
public boolean isNormalScope(Class<? extends Annotation> annotationType) {
return getDelegate().isNormalScope( annotationType );
}
@Override
public boolean isPassivatingScope(Class<? extends Annotation> annotationType) {
return getDelegate().isPassivatingScope( annotationType );
}
@Override
public boolean isQualifier(Class<? extends Annotation> annotationType) {
return getDelegate().isQualifier( annotationType );
}
@Override
public boolean isInterceptorBinding(Class<? extends Annotation> annotationType) {
return getDelegate().isInterceptorBinding( annotationType );
}
@Override
public boolean isStereotype(Class<? extends Annotation> annotationType) {
return getDelegate().isStereotype( annotationType );
}
@Override
public Set<Annotation> getInterceptorBindingDefinition(Class<? extends Annotation> bindingType) {
return getDelegate().getInterceptorBindingDefinition( bindingType );
}
@Override
public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype) {
return getDelegate().getStereotypeDefinition( stereotype );
}
@Override
public boolean areQualifiersEquivalent(Annotation qualifier1, Annotation qualifier2) {
return getDelegate().areQualifiersEquivalent( qualifier1, qualifier2 );
}
@Override
public boolean areInterceptorBindingsEquivalent(Annotation interceptorBinding1, Annotation interceptorBinding2) {
return getDelegate().areInterceptorBindingsEquivalent( interceptorBinding1, interceptorBinding2 );
}
@Override
public int getQualifierHashCode(Annotation qualifier) {
return getDelegate().getQualifierHashCode( qualifier );
}
@Override
public int getInterceptorBindingHashCode(Annotation interceptorBinding) {
return getDelegate().getInterceptorBindingHashCode( interceptorBinding );
}
@Override
public Context getContext(Class<? extends Annotation> scopeType) {
return getDelegate().getContext( scopeType );
}
@Override
public ELResolver getELResolver() {
return getDelegate().getELResolver();
}
@Override
public ExpressionFactory wrapExpressionFactory(ExpressionFactory expressionFactory) {
return getDelegate().wrapExpressionFactory( expressionFactory );
}
@Override
public <T> AnnotatedType<T> createAnnotatedType(Class<T> type) {
return getDelegate().createAnnotatedType( type );
}
@Override
public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type) {
return getDelegate().createInjectionTarget( type );
}
@Override
public <T> InjectionTargetFactory<T> getInjectionTargetFactory(AnnotatedType<T> annotatedType) {
return getDelegate().getInjectionTargetFactory( annotatedType );
}
@Override
public <X> ProducerFactory<X> getProducerFactory(AnnotatedField<? super X> field) {
return getDelegate().getProducerFactory( field );
}
@Override
public <X> ProducerFactory<X> getProducerFactory(AnnotatedMethod<? super X> method) {
return getDelegate().getProducerFactory( method );
}
@Override
public <T> BeanAttributes<T> createBeanAttributes(AnnotatedType<T> type) {
return getDelegate().createBeanAttributes( type );
}
@Override
public BeanAttributes<?> createBeanAttributes(AnnotatedMember<?> type) {
return getDelegate().createBeanAttributes( type );
}
@Override
public <T> Bean<T> createBean(BeanAttributes<T> attributes, Class<T> beanClass, InjectionTargetFactory<T> injectionTargetFactory) {
return getDelegate().createBean( attributes, beanClass, injectionTargetFactory );
}
@Override
public <T> Bean<T> createBean(BeanAttributes<T> attributes, Class<?> beanClass, ProducerFactory<T> producerFactory) {
return getDelegate().createBean( attributes, beanClass, producerFactory );
}
@Override
public InjectionPoint createInjectionPoint(AnnotatedField<?> field) {
return getDelegate().createInjectionPoint( field );
}
@Override
public InjectionPoint createInjectionPoint(AnnotatedParameter<?> parameter) {
return getDelegate().createInjectionPoint( parameter );
}
@Override
public <T extends Extension> T getExtension(Class<T> extensionClass) {
return getDelegate().getExtension( extensionClass );
}
}
}