HHH-11259 - Improved CDI support including support for other types of managed beans;

HHH-12133 - Create ManagedBeanRegistry and ManagedBean;
HHH-12134 - Convert entity listener CDI support to use ManagedBean/MenagedBeanRepository

Initial ManagedBeanRegistry and ManagedBean impl;
Conversion of JPA event Listeners to use ManagedBeanRegistry
This commit is contained in:
Steve Ebersole 2017-12-14 06:50:47 -06:00
parent b0c27562f4
commit 564ec55ca1
60 changed files with 1752 additions and 743 deletions

View File

@ -16,6 +16,7 @@ import org.hibernate.boot.registry.classloading.internal.TcclLookupPrecedence;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.JpaCompliance;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.resource.beans.spi.ExtendedBeanManager;
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.tool.schema.JdbcMetadaAccessStrategy;
@ -185,12 +186,22 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
*
* According to JPA, strictly, the BeanManager should be passed in
* at boot-time and be ready for use at that time. However not all
* environments can do this (WildFly for one). To accommodate such
* environments, Hibernate provides an SPI via
* {@link org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager} that
* can be used to provide delayed BeanManager access. Long story
* short, this setting could be typed as BeanManager or as
* {@link org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager}.
* environments can do this (WildFly e.g.). To accommodate such
* environments, Hibernate provides 2 options:
*
* * a proprietary CDI extension SPI (that we have proposed to
* the CDI spec group as a standard option) that can be used
* to provide delayed BeanManager access. To use this solution,
* the reference passed as the BeanManager during bootstrap
* should be typed as {@link ExtendedBeanManager}
* * delayed access to the BeanManager reference. Here, Hibernate
* will not access the reference passed as the BeanManager during
* bootstrap until it is first needed. Note however that this has
* the effect of delaying any deployement problems until after
* bootstrapping.
*
* This setting is used to configure Hibernate ORM's access to
* the BeanManager (either directly or via {@link ExtendedBeanManager}).
*/
String CDI_BEAN_MANAGER = "javax.persistence.bean.manager";

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.internal;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
@ -24,10 +24,10 @@ import org.hibernate.annotations.common.reflection.ClassLoadingException;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XMethod;
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.Callback;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.jboss.logging.Logger;
@ -40,11 +40,11 @@ import org.jboss.logging.Logger;
public class CallbackBuilderLegacyImpl implements CallbackBuilder {
private static final Logger log = Logger.getLogger( CallbackBuilderLegacyImpl.class );
private final ListenerFactory jpaListenerFactory;
private final ManagedBeanRegistry managedBeanRegistry;
private final ReflectionManager reflectionManager;
public CallbackBuilderLegacyImpl(ListenerFactory jpaListenerFactory, ReflectionManager reflectionManager) {
this.jpaListenerFactory = jpaListenerFactory;
public CallbackBuilderLegacyImpl(ManagedBeanRegistry managedBeanRegistry, ReflectionManager reflectionManager) {
this.managedBeanRegistry = managedBeanRegistry;
this.reflectionManager = reflectionManager;
}
@ -75,15 +75,10 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
}
}
@Override
public void release() {
// nothign to do
}
public Callback[] resolveCallbacks(XClass beanClass, CallbackType callbackType, ReflectionManager reflectionManager) {
List<Callback> callbacks = new ArrayList<Callback>();
List<String> callbacksMethodNames = new ArrayList<String>(); //used to track overridden methods
List<Class> orderedListeners = new ArrayList<Class>();
List<Callback> callbacks = new ArrayList<>();
List<String> callbacksMethodNames = new ArrayList<>();
List<Class> orderedListeners = new ArrayList<>();
XClass currentClazz = beanClass;
boolean stopListeners = false;
boolean stopDefaultListeners = false;
@ -157,7 +152,7 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
Callback callback = null;
if ( listener != null ) {
XClass xListener = reflectionManager.toXClass( listener );
callbacksMethodNames = new ArrayList<String>();
callbacksMethodNames = new ArrayList<>();
List<XMethod> methods = xListener.getDeclaredMethods();
for ( final XMethod xMethod : methods ) {
if ( xMethod.isAnnotationPresent( callbackType.getCallbackAnnotation() ) ) {
@ -167,7 +162,7 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
//overridden method, remove the superclass overridden method
if ( callback == null ) {
callback = new ListenerCallback(
jpaListenerFactory.buildListener( listener ),
managedBeanRegistry.getBean( listener ),
method,
callbackType
);
@ -245,4 +240,4 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
}
}
}
}
}

View File

@ -1,18 +1,18 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.internal;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.jpa.event.spi.CallbackBuilder;
/**
* Keep track of all lifecycle callbacks and listeners for a given persistence unit

View File

@ -1,16 +1,16 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.AbstractCallback;
import org.hibernate.jpa.event.spi.CallbackType;
/**
* Represents a JPA callback on the entity itself
@ -18,9 +18,10 @@ import org.hibernate.jpa.event.spi.jpa.CallbackType;
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole
*/
public class EntityCallback extends AbstractCallback implements Callback {
public class EntityCallback extends AbstractCallback {
private final Method callbackMethod;
@SuppressWarnings("WeakerAccess")
public EntityCallback(Method callbackMethod, CallbackType callbackType) {
super( callbackType );
this.callbackMethod = callbackMethod;

View File

@ -1,17 +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>.
* 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;
package org.hibernate.jpa.event.internal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.hibernate.jpa.event.spi.jpa.Callback;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.jpa.Listener;
import org.hibernate.jpa.event.spi.AbstractCallback;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.resource.beans.spi.ManagedBean;
/**
* Represents a JPA callback using a dedicated listener
@ -19,20 +19,21 @@ import org.hibernate.jpa.event.spi.jpa.Listener;
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole
*/
public class ListenerCallback extends AbstractCallback implements Callback {
public class ListenerCallback extends AbstractCallback {
private final Method callbackMethod;
private final Listener listenerInstance;
private final ManagedBean listenerManagedBean;
public ListenerCallback(Listener listenerInstance, Method callbackMethod, CallbackType callbackType) {
@SuppressWarnings("WeakerAccess")
public ListenerCallback(ManagedBean listenerManagedBean, Method callbackMethod, CallbackType callbackType) {
super( callbackType );
this.listenerInstance = listenerInstance;
this.listenerManagedBean = listenerManagedBean;
this.callbackMethod = callbackMethod;
}
@Override
public boolean performCallback(Object entity) {
try {
callbackMethod.invoke( listenerInstance.getListener(), entity );
callbackMethod.invoke( listenerManagedBean.getBeanInstance(), entity );
return true;
}
catch (InvocationTargetException e) {
@ -44,8 +45,11 @@ public class ListenerCallback extends AbstractCallback implements Callback {
throw new RuntimeException( e.getTargetException() );
}
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException( e );
}
}
}
}

View File

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

View File

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

View File

@ -10,8 +10,8 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultMergeEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation

View File

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

View File

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

View File

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

View File

@ -8,8 +8,8 @@ package org.hibernate.jpa.event.internal.core;
import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>

View File

@ -17,9 +17,9 @@ import org.hibernate.event.spi.PostCollectionUpdateEvent;
import org.hibernate.event.spi.PostCollectionUpdateEventListener;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.jpa.CallbackType;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.persister.entity.EntityPersister;
/**

View File

@ -10,8 +10,8 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultSaveEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation

View File

@ -10,8 +10,8 @@ import java.io.Serializable;
import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.jpa.event.spi.CallbackRegistry;
/**
* Overrides the LifeCycle OnSave call to call the PrePersist operation

View File

@ -1,126 +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.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.
*
* @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 JpaIntegrator, 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
*/
@SuppressWarnings("unused")
public static ListenerFactoryBeanManagerDelayedImpl fromBeanManagerReference(Object reference) {
if ( !BeanManager.class.isInstance( reference ) ) {
throw new IllegalArgumentException(
"Expecting BeanManager reference that implements CDI BeanManager contract : " +
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

@ -1,130 +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.HibernateException;
import org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager;
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. Further, this
* implementation leverages the ExtendedBeanManager contract to delay CDI calls.
*
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
public class ListenerFactoryBeanManagerExtendedImpl implements ListenerFactory, ExtendedBeanManager.LifecycleListener {
private static final Logger log = Logger.getLogger( ListenerFactoryBeanManagerExtendedImpl.class );
private final Map<Class,ListenerImpl> listenerMap = new ConcurrentHashMap<Class, ListenerImpl>();
/**
* Used via reflection from JpaIntegrator, 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
*/
@SuppressWarnings("unused")
public static ListenerFactoryBeanManagerExtendedImpl fromBeanManagerReference(Object reference) {
if ( !ExtendedBeanManager.class.isInstance( reference ) ) {
throw new IllegalArgumentException(
"Expecting BeanManager reference that implements optional ExtendedBeanManager contract : " +
reference
);
}
return new ListenerFactoryBeanManagerExtendedImpl( (ExtendedBeanManager) reference );
}
public ListenerFactoryBeanManagerExtendedImpl(ExtendedBeanManager beanManager) {
beanManager.registerLifecycleListener( this );
log.debugf( "ExtendedBeanManager 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();
}
@Override
public void beanManagerInitialized(BeanManager beanManager) {
for ( ListenerImpl listenerImpl : listenerMap.values() ) {
listenerImpl.initialize( beanManager );
}
}
private static 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;
}
public void initialize(BeanManager beanManager) {
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 ) {
throw new HibernateException( "CDI not initialized as expected" );
}
return listenerInstance;
}
public void release() {
if ( !initialized ) {
// log
return;
}
injectionTarget.preDestroy( listenerInstance );
injectionTarget.dispose( listenerInstance );
creationalContext.release();
}
}
}

View File

@ -1,109 +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.Listener;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.jboss.logging.Logger;
/**
* CDI-based implementation of the ListenerFactory contract. This CDI-based
* implementation works in the JPA standard prescribed manner.
* <p/>
* See {@link ListenerFactoryBeanManagerExtendedImpl} for an alt implementation that
* is still JPA compliant, but that works based on delayed CDI calls. Works
* on a non-CDI-defined CDI extension; we plan to propose this extension to the
* CDI expert group for the next CDI iteration
*
* @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 JpaIntegrator, 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
*/
@SuppressWarnings("unused")
public static ListenerFactoryBeanManagerStandardImpl fromBeanManagerReference(Object reference) {
if ( !BeanManager.class.isInstance( reference ) ) {
throw new IllegalArgumentException(
"Expecting BeanManager reference that implements CDI BeanManager contract : " +
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

@ -1,66 +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.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,11 +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;
/**
* Classes for integrating with JPA event callbacks
*/

View File

@ -1,29 +1,24 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.spi;
/**
* Abstract support for Callback implementations
*
* @author Steve Ebersole
*/
public abstract class AbstractCallback implements Callback {
private final CallbackType callbackType;
@SuppressWarnings("WeakerAccess")
public AbstractCallback(CallbackType callbackType) {
this.callbackType = callbackType;
}
@Override
public boolean isActive() {
return true;
}
@Override
public CallbackType getCallbackType() {
return callbackType;

View File

@ -1,35 +1,27 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.spi;
import java.io.Serializable;
/**
* 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.
* or an annotated method on a separate "listener" class. This contract presents
* a unified abstraction for both cases
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
* @author Steve Ebersole
*/
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 :)
* The type of callback (pre-update, pre-persist, etc) handled
*/
@Deprecated
boolean isActive();
CallbackType getCallbackType();
/**

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.spi;
/**
* Contract for walking an entity hierarchy and building a list of JPA callbacks
@ -27,6 +27,4 @@ public interface CallbackBuilder {
}
void buildCallbacksForEntity(String entityName, CallbackRegistrar callbackRegistrar);
void release();
}

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.spi;
import java.io.Serializable;

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.spi;
import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener;

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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;
package org.hibernate.jpa.event.spi;
import java.lang.annotation.Annotation;
import javax.persistence.PostLoad;

View File

@ -25,6 +25,8 @@ import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.event.internal.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.internal.CallbackRegistryImpl;
import org.hibernate.jpa.event.internal.core.HibernateEntityManagerEventListener;
import org.hibernate.jpa.event.internal.core.JpaAutoFlushEventListener;
import org.hibernate.jpa.event.internal.core.JpaDeleteEventListener;
@ -39,13 +41,8 @@ import org.hibernate.jpa.event.internal.core.JpaPostLoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostUpdateEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveEventListener;
import org.hibernate.jpa.event.internal.core.JpaSaveOrUpdateEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.spi.jpa.CallbackRegistryConsumer;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.hibernate.jpa.event.spi.jpa.ListenerFactoryBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
@ -55,8 +52,6 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistry;
* @author Steve Ebersole
*/
public class JpaIntegrator implements Integrator {
private ListenerFactory jpaListenerFactory;
private CallbackBuilder callbackBuilder;
private CallbackRegistryImpl callbackRegistry;
private CascadeStyle oldPersistCascadeStyle;
@ -132,8 +127,9 @@ public class JpaIntegrator implements Integrator {
.getReflectionManager();
this.callbackRegistry = new CallbackRegistryImpl();
this.jpaListenerFactory = ListenerFactoryBuilder.buildListenerFactory( sessionFactory.getSessionFactoryOptions() );
this.callbackBuilder = new CallbackBuilderLegacyImpl( jpaListenerFactory, reflectionManager );
final CallbackBuilder callbackBuilder = new CallbackBuilderLegacyImpl( serviceRegistry.getService( ManagedBeanRegistry.class ), reflectionManager );
for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have non java class persisted by hibernate
@ -168,12 +164,6 @@ public class JpaIntegrator implements Integrator {
if ( callbackRegistry != null ) {
callbackRegistry.release();
}
if ( callbackBuilder != null ) {
callbackBuilder.release();
}
if ( jpaListenerFactory != null ) {
jpaListenerFactory.release();
}
}
private Object instantiate(String listenerImpl, ServiceRegistryImplementor serviceRegistry) {

View File

@ -6,32 +6,9 @@
*/
package org.hibernate.jpa.event.spi.jpa;
import javax.enterprise.inject.spi.BeanManager;
/**
* This contract and the nested LifecycleListener contract represent the changes
* we'd like to propose to the CDI spec. The idea being simply to allow contextual
* registration of BeanManager lifecycle callbacks
*
* @author Steve Ebersole
* @deprecated Use {@link org.hibernate.resource.beans.spi.ExtendedBeanManager} instead
*/
public interface ExtendedBeanManager {
/**
* Register a BeanManager LifecycleListener
*
* @param lifecycleListener The listener to register
*/
void registerLifecycleListener(LifecycleListener lifecycleListener);
/**
* Contract for things interested in receiving notifications of
* BeanManager lifecycle events.
* <p/>
* A "beanManagerDestroyed" notifications would probably also be generally
* useful, although we do not need it here and not sure WildFly can really
* tell us that reliably.
*/
interface LifecycleListener {
void beanManagerInitialized(BeanManager beanManager);
}
@Deprecated
public interface ExtendedBeanManager extends org.hibernate.resource.beans.spi.ExtendedBeanManager {
}

View File

@ -1,22 +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.spi.jpa;
/**
* 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
*/
public interface ListenerFactory {
<T> Listener<T> buildListener(Class<T> listenerClass);
void release();
}

View File

@ -1,102 +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.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 if ( ExtendedBeanManager.class.isInstance( beanManagerRef ) ) {
return buildExtendedBeanManagerListenerFactory( beanManagerRef );
}
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_EXTENDED_CLASS = "org.hibernate.jpa.event.internal.jpa.ListenerFactoryBeanManagerExtendedImpl";
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 buildExtendedBeanManagerListenerFactory(Object beanManagerRef) {
return buildBeanManagerListenerFactory( beanManagerRef, CDI_LISTENER_FACTORY_EXTENDED_CLASS );
}
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,11 +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.spi.jpa;
/**
* SPI classes for integrating with JPA event callbacks
*/

View File

@ -0,0 +1,57 @@
/*
* 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.resource.beans.internal;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;
import org.jboss.logging.annotations.ValidIdRange;
import static org.jboss.logging.Logger.Level.INFO;
import static org.jboss.logging.Logger.Level.WARN;
/**
* @author Steve Ebersole
*/
@MessageLogger( projectCode = "HHH" )
@ValidIdRange( min = 10005001, max = 10010000 )
public interface BeansMessageLogger {
/**
* *The* BeansMessageLogger instance
*/
BeansMessageLogger CDI_LOGGER = Logger.getMessageLogger(
BeansMessageLogger.class,
"org.hibernate.orm.beans"
);
@LogMessage( level = WARN )
@Message(
id = 10005001,
value = "An explicit CDI BeanManager reference [%s] was passed to Hibernate, " +
"but CDI is not available on the Hibernate ClassLoader. This is likely " +
"going to lead to exceptions later on in bootstrap"
)
void beanManagerButCdiNotAvailable(Object cdiBeanManagerReference);
@LogMessage( level = INFO )
@Message(
id = 10005002,
value = "No explicit CDI BeanManager reference was passed to Hibernate, " +
"but CDI is available on the Hibernate ClassLoader."
)
void noBeanManagerButCdiAvailable();
@LogMessage( level = INFO )
@Message(
id = 10005003,
value = "Stopping ManagedBeanRegistry : %s"
)
void stoppingManagedBeanRegistry(ManagedBeanRegistry registry);
}

View File

@ -0,0 +1,61 @@
/*
* 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.resource.beans.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
/**
* A ManagedBeanRegistry implementation that can delegate to multiple
* other ManagedBeanRegistry instances, until one can handle the given call.
*
* @author Steve Ebersole
*/
public class CompositeManagedBeanRegistry implements ManagedBeanRegistry {
private List<ManagedBeanRegistry> delegates;
public void addDelegate(ManagedBeanRegistry beanRegistry) {
if ( delegates == null ) {
delegates = new ArrayList<>();
}
delegates.add( beanRegistry );
}
@Override
public <T> ManagedBean<T> getBean(Class<T> beanClass) {
return tryEachRegistry( registry -> registry.getBean( beanClass ) );
}
@Override
public <T> ManagedBean<T> getBean(String beanName, Class<T> contract) {
return tryEachRegistry( registry -> registry.getBean( beanName, contract ) );
}
private <T> ManagedBean<T> tryEachRegistry(Function<ManagedBeanRegistry, ManagedBean<T>> delegateAction) {
if ( delegates != null ) {
for ( ManagedBeanRegistry delegate : delegates ) {
ManagedBean<T> bean = null;
try {
bean = delegateAction.apply( delegate );
}
catch (Exception ignore) {
}
if ( bean != null ) {
return bean;
}
}
}
return delegateAction.apply( ManagedBeanRegistryDirectImpl.INSTANCE );
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.resource.beans.internal;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.resource.beans.spi.ExtendedBeanManager;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ManagedBeanRegistryInitiator;
import org.hibernate.service.ServiceRegistry;
/**
* Utility class for helping deal with the reflection calls relating to CDI.
*
* @author Steve Ebersole
*/
public class ManagedBeanRegistryCdiBuilder {
private static final String REGISTRY_FQN_STANDARD = "org.hibernate.resource.beans.internal.ManagedBeanRegistryCdiStandardImpl";
private static final String REGISTRY_FQN_DELAYED = "org.hibernate.resource.beans.internal.ManagedBeanRegistryCdiDelayedImpl";
private static final String REGISTRY_FQN_EXTENDED = "org.hibernate.resource.beans.internal.ManagedBeanRegistryCdiExtendedImpl";
@SuppressWarnings("unchecked")
public static ManagedBeanRegistry fromBeanManagerReference(
Object beanManagerRef,
ServiceRegistry serviceRegistry) {
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
final Class beanManagerClass = ManagedBeanRegistryInitiator.cdiBeanManagerClass( classLoaderService );
final Class<? extends ManagedBeanRegistry> registryClass;
final Class ctorArgType;
if ( ExtendedBeanManager.class.isInstance( beanManagerRef ) ) {
registryClass = getHibernateClass( REGISTRY_FQN_EXTENDED );
ctorArgType = ExtendedBeanManager.class;
}
else {
ctorArgType = beanManagerClass;
final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
final boolean delayAccessToCdi = cfgService.getSetting( AvailableSettings.DELAY_CDI_ACCESS, StandardConverters.BOOLEAN, false );
if ( delayAccessToCdi ) {
registryClass = getHibernateClass( REGISTRY_FQN_DELAYED );
}
else {
registryClass = getHibernateClass( REGISTRY_FQN_STANDARD );
}
}
try {
final Constructor<? extends ManagedBeanRegistry> ctor = registryClass.getDeclaredConstructor( ctorArgType );
try {
ctor.setAccessible( true );
return ctor.newInstance( ctorArgType.cast( beanManagerRef ) );
}
catch (InvocationTargetException e) {
throw new HibernateException( "Problem building " + registryClass.getName(), e.getCause() );
}
catch (Exception e) {
throw new HibernateException( "Problem building " + registryClass.getName(), e );
}
}
catch (NoSuchMethodException e) {
throw new HibernateException(
String.format(
Locale.ENGLISH,
"Could not locate proper %s constructor",
registryClass.getName()
),
e
);
}
}
@SuppressWarnings("unchecked")
private static <T> Class<T> getHibernateClass(String fqn) {
// we use this Class's ClassLoader...
try {
return (Class<T>) Class.forName(
fqn,
true,
ManagedBeanRegistryCdiBuilder.class.getClassLoader()
);
}
catch (ClassNotFoundException e) {
throw new HibernateException( "Unable to locate Hibernate class by name via reflection : " + fqn, e );
}
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.resource.beans.internal;
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.resource.beans.spi.AbstractManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.jboss.logging.Logger;
/**
* A CDI-based ManagedBeanRegistry for Hibernate delaying access to the
* BeanManager until first need.
*
* @see ManagedBeanRegistryCdiExtendedImpl
* @see ManagedBeanRegistryCdiStandardImpl
*
* @author Steve Ebersole
*/
public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegistry {
private static final Logger log = Logger.getLogger( ManagedBeanRegistryCdiDelayedImpl.class );
private final BeanManager beanManager;
private ManagedBeanRegistryCdiDelayedImpl(BeanManager beanManager) {
this.beanManager = beanManager;
log.debugf( "Delayed access requested to CDI BeanManager : " + beanManager );
}
@Override
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
return new ManagedBeanImpl<>( beanContract );
}
private class ManagedBeanImpl<T> implements ManagedBean<T> {
private final Class<T> beanClass;
private boolean initialized = false;
private InjectionTarget<T> injectionTarget;
private CreationalContext<T> creationalContext;
private T beanInstance;
public ManagedBeanImpl(Class<T> beanClass) {
this.beanClass = beanClass;
}
@Override
public Class<T> getBeanClass() {
return beanClass;
}
@Override
public T getBeanInstance() {
if ( !initialized ) {
initialize();
}
return beanInstance;
}
private void initialize() {
log.debug( "Delayed initialization of CDI bean on first use : " + beanClass );
final AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( beanClass );
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
this.creationalContext = beanManager.createCreationalContext( null );
this.beanInstance = injectionTarget.produce( creationalContext );
injectionTarget.inject( this.beanInstance, creationalContext );
injectionTarget.postConstruct( this.beanInstance );
this.initialized = true;
}
@Override
public void release() {
if ( !initialized ) {
log.debug( "Skipping release for delayed CDI bean [" + beanClass + "] as it was not initialized" );
return;
}
log.debug( "Releasing CDI listener : " + beanClass );
injectionTarget.preDestroy( beanInstance );
injectionTarget.dispose( beanInstance );
creationalContext.release();
}
}
}

View File

@ -0,0 +1,116 @@
/*
* 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.resource.beans.internal;
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.resource.beans.spi.AbstractManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ExtendedBeanManager;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.jboss.logging.Logger;
/**
* A CDI-based ManagedBeanRegistry for Hibernate leveraging a proposed extension to CDI.
* Specifically the extension is meant to tell us when the CDI BeanManager is usable.
* So it is a delayed strategy, but delayed until a specific event : namely when our
* {@link ExtendedBeanManager.LifecycleListener} callbacks occur.
*
* @see ManagedBeanRegistryCdiStandardImpl
* @see ManagedBeanRegistryCdiDelayedImpl
*
* @author Steve Ebersole
*/
public class ManagedBeanRegistryCdiExtendedImpl
extends AbstractManagedBeanRegistry
implements ExtendedBeanManager.LifecycleListener {
private static final Logger log = Logger.getLogger( ManagedBeanRegistryCdiStandardImpl.class );
private BeanManager usableBeanManager;
private ManagedBeanRegistryCdiExtendedImpl(ExtendedBeanManager beanManager) {
beanManager.registerLifecycleListener( this );
log.debugf( "Extended access requested to CDI BeanManager : " + beanManager );
}
@Override
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
return new ManagedBeanImpl<>( beanContract );
}
@Override
public void beanManagerInitialized(BeanManager beanManager) {
this.usableBeanManager = beanManager;
// force each bean to initialize
forEachBean( ManagedBean::getBeanInstance );
}
private BeanManager getUsableBeanManager() {
if ( usableBeanManager == null ) {
throw new IllegalStateException( "ExtendedBeanManager.LifecycleListener callback not yet called: CDI not (yet) usable" );
}
return usableBeanManager;
}
private class ManagedBeanImpl<T> implements ManagedBean<T> {
private final Class<T> beanClass;
private boolean initialized = false;
private InjectionTarget<T> injectionTarget;
private CreationalContext<T> creationalContext;
private T beanInstance;
private ManagedBeanImpl(Class<T> beanClass) {
this.beanClass = beanClass;
}
public void initialize() {
final BeanManager beanManager = getUsableBeanManager();
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( beanClass );
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
this.creationalContext = beanManager.createCreationalContext( null );
this.beanInstance = injectionTarget.produce( creationalContext );
injectionTarget.inject( this.beanInstance, creationalContext );
injectionTarget.postConstruct( this.beanInstance );
this.initialized = true;
}
@Override
public Class<T> getBeanClass() {
return beanClass;
}
@Override
public T getBeanInstance() {
if ( !initialized ) {
initialize();
}
return beanInstance;
}
public void release() {
if ( !initialized ) {
// log
return;
}
injectionTarget.preDestroy( beanInstance );
injectionTarget.dispose( beanInstance );
creationalContext.release();
}
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.resource.beans.internal;
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.resource.beans.spi.AbstractManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.jboss.logging.Logger;
/**
* A CDI-based ManagedBeanRegistry for Hibernate following the JPA standard
* prescribed manner... namely assuming immediate access to the BeanManager is
* allowed.
*
* @see ManagedBeanRegistryCdiExtendedImpl
* @see ManagedBeanRegistryCdiDelayedImpl
*
* @author Steve Ebersole
*/
class ManagedBeanRegistryCdiStandardImpl extends AbstractManagedBeanRegistry {
private static final Logger log = Logger.getLogger( ManagedBeanRegistryCdiStandardImpl.class );
private final BeanManager beanManager;
private ManagedBeanRegistryCdiStandardImpl(BeanManager beanManager) {
this.beanManager = beanManager;
log.debugf( "Standard access requested to CDI BeanManager : " + beanManager );
}
@Override
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
return new ManagedBeanImpl<>( beanContract );
}
private class ManagedBeanImpl<T> implements ManagedBean<T> {
private final Class<T> beanClass;
private final InjectionTarget<T> injectionTarget;
private final CreationalContext<T> creationalContext;
private final T beanInstance;
public ManagedBeanImpl(Class<T> beanClass) {
this.beanClass = beanClass;
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( beanClass );
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
this.creationalContext = beanManager.createCreationalContext( null );
this.beanInstance = injectionTarget.produce( creationalContext );
injectionTarget.inject( this.beanInstance, creationalContext );
injectionTarget.postConstruct( this.beanInstance );
}
@Override
public Class<T> getBeanClass() {
return beanClass;
}
@Override
public T getBeanInstance() {
return beanInstance;
}
@Override
public void release() {
injectionTarget.preDestroy( beanInstance );
injectionTarget.dispose( beanInstance );
creationalContext.release();
}
}
}

View File

@ -0,0 +1,69 @@
/*
* 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.resource.beans.internal;
import org.hibernate.InstantiationException;
import org.hibernate.resource.beans.spi.AbstractManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.jboss.logging.Logger;
/**
* ManagedBeanRegistry implementation using direct instantiation of the beans. Used
* when there is no backing "injection framework" in use as well as the fallback
* for {@link CompositeManagedBeanRegistry}
*
* @author Steve Ebersole
*/
public class ManagedBeanRegistryDirectImpl extends AbstractManagedBeanRegistry {
private static final Logger log = Logger.getLogger( ManagedBeanRegistryDirectImpl.class );
/**
* Singleton access
*/
public static final ManagedBeanRegistryDirectImpl INSTANCE = new ManagedBeanRegistryDirectImpl();
private ManagedBeanRegistryDirectImpl() {
}
@Override
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
return new ManagedBeanImpl<>( beanContract );
}
private class ManagedBeanImpl<T> implements ManagedBean<T> {
private final Class<T> beanClass;
private final T bean;
private ManagedBeanImpl(Class<T> beanClass) {
log.debugf( "Creating ManagedBean[%s] using direct instantiation", beanClass.getName() );
this.beanClass = beanClass;
try {
this.bean = beanClass.newInstance();
}
catch (Exception e) {
throw new InstantiationException( "Could not instantiate managed bean directly", beanClass, e );
}
}
@Override
public Class<T> getBeanClass() {
return beanClass;
}
@Override
public T getBeanInstance() {
return bean;
}
@Override
public void release() {
// nothing to do
}
}
}

View File

@ -0,0 +1,16 @@
/*
* 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>.
*/
/**
* Defines Hibernate's integration with CDI. Because CDI may or may not be available
* a lot of this support is directed toward abstracting/encapsulating CDI. The
* central contracts here from a consumption point-of-view are
* {@link org.hibernate.resource.beans.spi.ManagedBean} and
* {@link org.hibernate.resource.beans.spi.ManagedBeanRegistry} which may or may not
* really be backed by CDI.
*/
package org.hibernate.resource.beans;

View File

@ -0,0 +1,51 @@
/*
* 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.resource.beans.spi;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import org.hibernate.resource.beans.internal.BeansMessageLogger;
import org.hibernate.service.spi.Stoppable;
/**
* Abstract support (template pattern) for ManagedBeanRegistry implementations
*
* @author Steve Ebersole
*/
public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry, Stoppable {
private Map<String,ManagedBean<?>> registrations = new HashMap<>();
@Override
@SuppressWarnings("unchecked")
public <T> ManagedBean<T> getBean(String beanName, Class<T> beanContract) {
final ManagedBean<T> existing = (ManagedBean<T>) registrations.get( beanName );
if ( existing != null ) {
return existing;
}
final ManagedBean<T> bean = createBean( beanName, beanContract );
registrations.put( beanName, bean );
return bean;
}
@SuppressWarnings("WeakerAccess")
protected abstract <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract);
@SuppressWarnings("WeakerAccess")
protected void forEachBean(Consumer<ManagedBean<?>> consumer) {
registrations.values().forEach( consumer );
}
@Override
public void stop() {
BeansMessageLogger.CDI_LOGGER.stoppingManagedBeanRegistry( this );
forEachBean( ManagedBean::release );
registrations.clear();
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.resource.beans.spi;
import javax.enterprise.inject.spi.BeanManager;
/**
* This contract and the nested LifecycleListener contract represent the changes
* we'd like to propose to the CDI spec. The idea being simply to allow contextual
* registration of BeanManager lifecycle callbacks
*
* @author Steve Ebersole
*/
public interface ExtendedBeanManager {
/**
* Register a BeanManager LifecycleListener
*
* @param lifecycleListener The listener to register
*/
void registerLifecycleListener(LifecycleListener lifecycleListener);
/**
* Contract for things interested in receiving notifications of
* BeanManager lifecycle events.
* <p/>
* A "beanManagerDestroyed" notifications would probably also be generally
* useful, although we do not need it here and not sure WildFly can really
* tell us that reliably.
*/
interface LifecycleListener {
void beanManagerInitialized(BeanManager beanManager);
}
}

View File

@ -4,14 +4,15 @@
* 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;
package org.hibernate.resource.beans.spi;
/**
* Encapsulates access to the listener instance for listener callbacks
* ({@link javax.persistence.EntityListeners}).
* Generalized contract for a CDI ManagedBean as seen by Hibernate
*
* @author Steve Ebersole
*/
public interface Listener<T> {
T getListener();
}
public interface ManagedBean<T> {
Class<T> getBeanClass();
T getBeanInstance();
void release();
}

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.resource.beans.spi;
import org.hibernate.service.Service;
/**
* A registry for ManagedBean instances. Responsible for managing the lifecycle.
* <p/>
* Access to the beans and usage of them are only valid between the time
* the registry is initialized and released (however those events are recognized).
*
* @author Steve Ebersole
*/
public interface ManagedBeanRegistry extends Service {
/**
* Get a bean reference, by class. By default, calls
* {@link #getBean(String, Class)} using the beanClass's name
*/
default <T> ManagedBean<T> getBean(Class<T> beanClass) {
return getBean( beanClass.getName(), beanClass );
}
/**
* Get a bean reference by name, typed as the given bean contract.
*/
<T> ManagedBean<T> getBean(String beanName, Class<T> contract);
}

View File

@ -0,0 +1,82 @@
/*
* 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.resource.beans.spi;
import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.resource.beans.internal.BeansMessageLogger;
import org.hibernate.resource.beans.internal.CompositeManagedBeanRegistry;
import org.hibernate.resource.beans.internal.ManagedBeanRegistryCdiBuilder;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* Hibernate's standard initializer for the ManagedBeanRegistry service.
*
* Produces a {@link CompositeManagedBeanRegistry}
*
* @author Steve Ebersole
*/
public class ManagedBeanRegistryInitiator implements StandardServiceInitiator<ManagedBeanRegistry> {
/**
* Singleton access
*/
public static final ManagedBeanRegistryInitiator INSTANCE = new ManagedBeanRegistryInitiator();
@Override
public Class<ManagedBeanRegistry> getServiceInitiated() {
return ManagedBeanRegistry.class;
}
@Override
public ManagedBeanRegistry initiateService(
Map configurationValues,
ServiceRegistryImplementor serviceRegistry) {
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
final ConfigurationService cfgSvc = serviceRegistry.getService( ConfigurationService.class );
final CompositeManagedBeanRegistry beanRegistry = new CompositeManagedBeanRegistry();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// apply CDI support
final boolean isCdiAvailable = isCdiAvailable( classLoaderService );
final Object beanManagerRef = cfgSvc.getSettings().get( AvailableSettings.CDI_BEAN_MANAGER );
if ( beanManagerRef != null ) {
if ( !isCdiAvailable ) {
BeansMessageLogger.CDI_LOGGER.beanManagerButCdiNotAvailable( beanManagerRef );
}
beanRegistry.addDelegate(
ManagedBeanRegistryCdiBuilder.fromBeanManagerReference( beanManagerRef, serviceRegistry )
);
}
return beanRegistry;
}
private static boolean isCdiAvailable(ClassLoaderService classLoaderService) {
// is CDI available on our ClassLoader?
try {
cdiBeanManagerClass( classLoaderService );
return true;
}
catch (ClassLoadingException e) {
return false;
}
}
public static Class cdiBeanManagerClass(ClassLoaderService classLoaderService) throws ClassLoadingException {
return classLoaderService.classForName( "javax.enterprise.inject.spi.BeanManager" );
}
}

View File

@ -31,6 +31,7 @@ import org.hibernate.jmx.internal.JmxServiceInitiator;
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
import org.hibernate.persister.internal.PersisterFactoryInitiator;
import org.hibernate.property.access.internal.PropertyAccessStrategyResolverInitiator;
import org.hibernate.resource.beans.spi.ManagedBeanRegistryInitiator;
import org.hibernate.resource.transaction.internal.TransactionCoordinatorBuilderInitiator;
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator;
@ -84,6 +85,8 @@ public final class StandardServiceInitiators {
serviceInitiators.add( TransactionCoordinatorBuilderInitiator.INSTANCE );
serviceInitiators.add( ManagedBeanRegistryInitiator.INSTANCE );
return Collections.unmodifiableList( serviceInitiators );
}
}

View File

@ -44,7 +44,7 @@ public class ConversationalPersistenceContextExtendedTest {
private static PersistenceDescriptor persistenceXml() {
return Descriptors.create( PersistenceDescriptor.class )
.createPersistenceUnit().name( "pu-cdi-basic" )
.createPersistenceUnit().name( "pu-beans-basic" )
.clazz( Event.class.getName() )
.excludeUnlistedClasses( true )
.nonJtaDataSource( "java:jboss/datasources/ExampleDS" )

View File

@ -45,7 +45,7 @@ public class ManualFlushConversationalPersistenceContextExtendedTest {
private static PersistenceDescriptor persistenceXml() {
return Descriptors.create( PersistenceDescriptor.class )
.createPersistenceUnit().name( "pu-cdi-basic" )
.createPersistenceUnit().name( "pu-beans-basic" )
.clazz( Event.class.getName() )
.excludeUnlistedClasses( true )
.nonJtaDataSource( "java:jboss/datasources/ExampleDS" )

View File

@ -44,7 +44,7 @@ public class NonConversationalPersistenceContextExtendedTest {
private static PersistenceDescriptor persistenceXml() {
return Descriptors.create( PersistenceDescriptor.class )
.createPersistenceUnit().name( "pu-cdi-basic" )
.createPersistenceUnit().name( "pu-beans-basic" )
.clazz( Event.class.getName() )
.excludeUnlistedClasses( true )
.nonJtaDataSource( "java:jboss/datasources/ExampleDS" )

View File

@ -0,0 +1,12 @@
/*
* 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 for testing Hibernate's support for integrating
* with CDI for JPA attribute converters
*/
package org.hibernate.test.cdi.converters;

View File

@ -0,0 +1,38 @@
/*
* 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.test.cdi.events;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Steve Ebersole
*/
public class Monitor {
private static final AtomicInteger count = new AtomicInteger( 0 );
private static boolean instantiated;
public Monitor() {
instantiated = true;
}
public static void reset() {
instantiated = false;
count.set( 0 );
}
public static boolean wasInstantiated() {
return instantiated;
}
public static int currentCount() {
return count.get();
}
public void entitySaved() {
count.getAndIncrement();
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.test.cdi.events;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Steve Ebersole
*/
@Entity
@Table( name = "the_entity")
@EntityListeners( TheListener.class )
public class TheEntity {
private Integer id;
private String name;
public TheEntity() {
}
public TheEntity(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;
}
}

View File

@ -0,0 +1,26 @@
/*
* 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.test.cdi.events;
import javax.persistence.PrePersist;
/**
* @author Steve Ebersole
*/
public class TheListener {
private final Monitor monitor;
@javax.inject.Inject
public TheListener(Monitor monitor) {
this.monitor = monitor;
}
@PrePersist
public void onCreate(Object entity) {
monitor.entitySaved();
}
}

View File

@ -0,0 +1,107 @@
/*
* 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.test.cdi.events.delayed;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.hibernate.test.cdi.events.TheEntity;
import org.hibernate.test.cdi.events.TheListener;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Tests support for CDI delaying access to the CDI container until
* first needed
*
* @author Steve Ebersole
*/
public class DelayedCdiSupportTest extends BaseUnitTestCase {
@Test
public void testIt() {
Monitor.reset();
final SeContainerInitializer cdiInitializer = SeContainerInitializer.newInstance()
.disableDiscovery()
.addBeanClasses( Monitor.class, TheListener.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.applySetting( AvailableSettings.CDI_BEAN_MANAGER, cdiContainer.getBeanManager() )
.applySetting( AvailableSettings.DELAY_CDI_ACCESS, "true" )
.build();
final SessionFactoryImplementor sessionFactory;
try {
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata()
.getSessionFactoryBuilder()
.build();
}
catch ( Exception e ) {
StandardServiceRegistryBuilder.destroy( ssr );
throw e;
}
// The CDI bean should not be built immediately...
assertFalse( Monitor.wasInstantiated() );
assertEquals( 0, Monitor.currentCount() );
try {
inTransaction(
sessionFactory,
session -> session.persist( new TheEntity( 1 ) )
);
// The CDI bean should have been built on first use
assertTrue( Monitor.wasInstantiated() );
assertEquals( 1, Monitor.currentCount() );
inTransaction(
sessionFactory,
session -> {
TheEntity it = session.find( TheEntity.class, 1 );
assertNotNull( it );
}
);
}
finally {
inTransaction(
sessionFactory,
session -> {
session.createQuery( "delete TheEntity" ).executeUpdate();
}
);
sessionFactory.close();
}
}
}
}

View File

@ -0,0 +1,106 @@
/*
* 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.test.cdi.events.extended;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.resource.beans.spi.ExtendedBeanManager;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.hibernate.test.cdi.events.TheEntity;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
/**
* Tests support for CDI delaying access to the CDI container until
* first needed
*
* @author Steve Ebersole
*/
public class InvalidExtendedCdiSupportTest extends BaseUnitTestCase {
@Test
public void testIt() {
Monitor.reset();
final ExtendedBeanManagerImpl standIn = new ExtendedBeanManagerImpl();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.applySetting( AvailableSettings.CDI_BEAN_MANAGER, standIn )
.build();
final SessionFactoryImplementor sessionFactory;
try {
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata()
.getSessionFactoryBuilder()
.build();
}
catch ( Exception e ) {
StandardServiceRegistryBuilder.destroy( ssr );
throw e;
}
try {
// The CDI bean should not be built immediately...
assertFalse( Monitor.wasInstantiated() );
assertEquals( 0, Monitor.currentCount() );
// this time (compared to the valid test) lets not build the CDI
// container and just let Hibernate try to use the uninitialized
// ExtendedBeanManager reference
try {
inTransaction(
sessionFactory,
session -> session.persist( new TheEntity( 1 ) )
);
inTransaction(
sessionFactory,
session -> {
session.createQuery( "delete TheEntity" ).executeUpdate();
}
);
fail( "Expecting failure" );
}
catch (IllegalStateException expected) {
}
}
finally {
sessionFactory.close();
}
}
public static class ExtendedBeanManagerImpl implements ExtendedBeanManager {
@Override
public void registerLifecycleListener(LifecycleListener lifecycleListener) {
}
}
}

View File

@ -0,0 +1,135 @@
/*
* 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.test.cdi.events.extended;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import javax.enterprise.inject.spi.BeanManager;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.resource.beans.spi.ExtendedBeanManager;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.hibernate.test.cdi.events.TheEntity;
import org.hibernate.test.cdi.events.TheListener;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Tests support for CDI delaying access to the CDI container until
* first needed
*
* @author Steve Ebersole
*/
public class ValidExtendedCdiSupportTest extends BaseUnitTestCase {
@Test
public void testIt() {
Monitor.reset();
final ExtendedBeanManagerImpl standIn = new ExtendedBeanManagerImpl();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.applySetting( AvailableSettings.CDI_BEAN_MANAGER, standIn )
.build();
final SessionFactoryImplementor sessionFactory;
try {
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata()
.getSessionFactoryBuilder()
.build();
}
catch ( Exception e ) {
StandardServiceRegistryBuilder.destroy( ssr );
throw e;
}
try {
// The CDI bean should not be built immediately...
assertFalse( Monitor.wasInstantiated() );
assertEquals( 0, Monitor.currentCount() );
// But now lets initialize CDI and do the callback
final SeContainerInitializer cdiInitializer = SeContainerInitializer.newInstance()
.disableDiscovery()
.addBeanClasses( Monitor.class, TheListener.class );
try (final SeContainer cdiContainer = cdiInitializer.initialize()) {
standIn.beanManagerReady( cdiContainer.getBeanManager() );
// at this point the bean should have been accessed
assertTrue( Monitor.wasInstantiated() );
assertEquals( 0, Monitor.currentCount() );
try {
inTransaction(
sessionFactory,
session -> session.persist( new TheEntity( 1 ) )
);
inTransaction(
sessionFactory,
session -> {
TheEntity it = session.find( TheEntity.class, 1 );
assertNotNull( it );
}
);
}
finally {
inTransaction(
sessionFactory,
session -> {
session.createQuery( "delete TheEntity" ).executeUpdate();
}
);
}
}
}
finally {
sessionFactory.close();
}
}
public static class ExtendedBeanManagerImpl implements ExtendedBeanManager {
private LifecycleListener callback;
@Override
public void registerLifecycleListener(LifecycleListener lifecycleListener) {
this.callback = lifecycleListener;
}
public void beanManagerReady(BeanManager beanManager) {
callback.beanManagerInitialized( beanManager );
}
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.test.cdi.events.nocdi;
import org.hibernate.InstantiationException;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.hibernate.test.cdi.events.TheEntity;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* Attempt to use CDI injection when no CDI is available
*
* @author Steve Ebersole
*/
public class InvalidNoCdiSupportTest extends BaseUnitTestCase {
@Test
public void testIt() {
Monitor.reset();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.build();
final SessionFactoryImplementor sessionFactory;
try {
// because there is no CDI available, building the SF should immediately
// try to build the ManagedBeans which should fail here
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata()
.getSessionFactoryBuilder()
.build();
sessionFactory.close();
fail( "Expecting failure" );
}
catch ( Exception e ) {
StandardServiceRegistryBuilder.destroy( ssr );
assertThat( e, instanceOf( InstantiationException.class ) );
}
}
}

View File

@ -0,0 +1,159 @@
/*
* 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.test.cdi.events.nocdi;
import java.util.concurrent.atomic.AtomicInteger;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Tests valid use of ManagedBeanRegistry when CDI is not available -
* meaning injection is not requested.
*
* @author Steve Ebersole
*/
public class ValidNoCdiSupportTest extends BaseUnitTestCase {
@Test
public void testIt() {
AnotherListener.reset();
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.build();
final SessionFactoryImplementor sessionFactory;
try {
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
.addAnnotatedClass( AnotherEntity.class )
.buildMetadata()
.getSessionFactoryBuilder()
.build();
}
catch ( Exception e ) {
StandardServiceRegistryBuilder.destroy( ssr );
throw e;
}
// The CDI bean should have been built immediately...
assertTrue( AnotherListener.wasInstantiated() );
assertEquals( 0, AnotherListener.currentCount() );
try {
inTransaction(
sessionFactory,
session -> session.persist( new AnotherEntity( 1 ) )
);
assertEquals( 1, AnotherListener.currentCount() );
inTransaction(
sessionFactory,
session -> {
AnotherEntity it = session.find( AnotherEntity.class, 1 );
assertNotNull( it );
}
);
}
finally {
inTransaction(
sessionFactory,
session -> {
session.createQuery( "delete AnotherEntity" ).executeUpdate();
}
);
sessionFactory.close();
}
}
@Entity( name = "AnotherEntity" )
@Table( name = "another_entity")
@EntityListeners( AnotherListener.class )
public static class AnotherEntity {
private Integer id;
private String name;
public AnotherEntity() {
}
public AnotherEntity(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 AnotherListener {
private static final AtomicInteger count = new AtomicInteger( 0 );
private static boolean instantiated;
public AnotherListener() {
instantiated = true;
}
public static void reset() {
count.set( 0 );
instantiated = false;
}
public static boolean wasInstantiated() {
return instantiated;
}
public static int currentCount() {
return count.get();
}
@PrePersist
public void onCreate(Object entity) {
count.getAndIncrement();
}
}
}

View File

@ -0,0 +1,12 @@
/*
* 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 for testing Hibernate's support for integrating
* with CDI for JPA event listeners
*/
package org.hibernate.test.cdi.events;

View File

@ -0,0 +1,103 @@
/*
* 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.test.cdi.events.standard;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.event.spi.JpaIntegrator;
import org.hibernate.tool.schema.Action;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.cdi.events.Monitor;
import org.hibernate.test.cdi.events.TheEntity;
import org.hibernate.test.cdi.events.TheListener;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Tests support for CDI as (implicitly) defined by JPA in terms of
* immediate availability
*
* @author Steve Ebersole
*/
public class StandardCdiSupportTest extends BaseUnitTestCase {
@Test
public void testIt() {
Monitor.reset();
final SeContainerInitializer cdiInitializer = SeContainerInitializer.newInstance()
.disableDiscovery()
.addBeanClasses( Monitor.class, TheListener.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder()
.applyIntegrator( new JpaIntegrator() )
.build();
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr )
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.applySetting( AvailableSettings.CDI_BEAN_MANAGER, cdiContainer.getBeanManager() )
.build();
final SessionFactoryImplementor sessionFactory;
try {
sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
.addAnnotatedClass( TheEntity.class )
.buildMetadata()
.getSessionFactoryBuilder()
.build();
}
catch ( Exception e ) {
StandardServiceRegistryBuilder.destroy( ssr );
throw e;
}
// The CDI bean should have been built immediately...
assertTrue( Monitor.wasInstantiated() );
assertEquals( 0, Monitor.currentCount() );
try {
inTransaction(
sessionFactory,
session -> session.persist( new TheEntity( 1 ) )
);
assertEquals( 1, Monitor.currentCount() );
inTransaction(
sessionFactory,
session -> {
TheEntity it = session.find( TheEntity.class, 1 );
assertNotNull( it );
}
);
}
finally {
inTransaction(
sessionFactory,
session -> {
session.createQuery( "delete TheEntity" ).executeUpdate();
}
);
sessionFactory.close();
}
}
}
}

View File

@ -0,0 +1,11 @@
/*
* 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
*/
/**
* Base package for testing Hibernate's CDI integration
*/
package org.hibernate.test.cdi;