HHH-12133 Comply with API docs with respect to lifecycle management depending on the 'shouldRegistryManageLifecycle' parameter
The registry should not manage the bean lifecycle when 'shouldRegistryManageLifecycle' is false. The easiest way to do so is to use BeanManager.createInstance to retrieve beans in the Standard CDI lifecycle strategy: it correctly retrieves singletons from the CDI context instead of instantiating them again. Also, fix javax.enterprise.inject.spi.Bean-based instance destructions: we used to only request destruction to the creational context, which is wrong because it may skip the execution of @PostDestroy methods in particular.
This commit is contained in:
parent
b3ac2feddf
commit
edc0039afc
hibernate-core/src/main/java/org/hibernate/resource/beans
|
@ -22,24 +22,6 @@ public class Helper {
|
|||
private Helper() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Bean<T> getBean(Class<T> beanContract, BeanManager beanManager) {
|
||||
Set<Bean<?>> beans = beanManager.getBeans( beanContract );
|
||||
|
||||
if ( beans.isEmpty() ) {
|
||||
throw new IllegalArgumentException(
|
||||
"BeanManager returned no matching beans: contract = " + beanContract.getName()
|
||||
);
|
||||
}
|
||||
if ( beans.size() > 1 ) {
|
||||
throw new IllegalArgumentException(
|
||||
"BeanManager returned multiple matching beans: contract = " + beanContract.getName()
|
||||
);
|
||||
}
|
||||
|
||||
return (Bean<T>) beans.iterator().next();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Bean<T> getNamedBean(String beanName, Class<T> beanContract, BeanManager beanManager) {
|
||||
Set<Bean<?>> beans = beanManager.getBeans( beanContract, new NamedBeanQualifier( beanName ) );
|
||||
|
@ -57,4 +39,13 @@ public class Helper {
|
|||
|
||||
return (Bean<T>) beans.iterator().next();
|
||||
}
|
||||
|
||||
public CdiLifecycleManagementStrategy getLifecycleManagementStrategy(boolean shouldRegistryManageLifecycle) {
|
||||
if ( shouldRegistryManageLifecycle ) {
|
||||
return JpaCdiLifecycleManagementStrategy.INSTANCE;
|
||||
}
|
||||
else {
|
||||
return StandardCdiLifecycleManagementStrategy.INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,18 @@ import javax.enterprise.inject.spi.InjectionTarget;
|
|||
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
|
||||
/**
|
||||
* A {@link CdiLifecycleManagementStrategy} to use when JPA compliance is required
|
||||
* (i.e. when the bean lifecycle is to be managed by the JPA runtime, not the CDI runtime).
|
||||
*
|
||||
* The main characteristic of this strategy is that each requested bean is instantiated directly
|
||||
* and guaranteed to not be shared in the CDI context.
|
||||
*
|
||||
* In particular, @Singleton-scoped or @ApplicationScoped beans are instantiated directly by this strategy,
|
||||
* even if there is already an instance in the CDI context.
|
||||
* This means singletons are not really singletons, but this seems to be the behavior required by
|
||||
* the JPA 2.2 spec.
|
||||
*/
|
||||
class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrategy {
|
||||
|
||||
static final JpaCdiLifecycleManagementStrategy INSTANCE = new JpaCdiLifecycleManagementStrategy();
|
||||
|
@ -44,7 +56,7 @@ class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrateg
|
|||
|
||||
T beanInstance = bean.create( creationalContext );
|
||||
|
||||
return new NamedJpaManagedBeanImpl<>( beanClass, creationalContext, beanInstance );
|
||||
return new NamedJpaManagedBeanImpl<>( beanClass, bean, creationalContext, beanInstance );
|
||||
}
|
||||
|
||||
private static class JpaManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
|
@ -82,13 +94,14 @@ class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrateg
|
|||
|
||||
private static class NamedJpaManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
private final Class<T> beanClass;
|
||||
private final Bean<T> bean;
|
||||
private final CreationalContext<T> creationContext;
|
||||
private final T beanInstance;
|
||||
|
||||
private NamedJpaManagedBeanImpl(
|
||||
Class<T> beanClass,
|
||||
CreationalContext<T> creationContext, T beanInstance) {
|
||||
Class<T> beanClass, Bean<T> bean, CreationalContext<T> creationContext, T beanInstance) {
|
||||
this.beanClass = beanClass;
|
||||
this.bean = bean;
|
||||
this.creationContext = creationContext;
|
||||
this.beanInstance = beanInstance;
|
||||
}
|
||||
|
@ -105,7 +118,7 @@ class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrateg
|
|||
|
||||
@Override
|
||||
public void release() {
|
||||
creationContext.release();
|
||||
bean.destroy( beanInstance, creationContext );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,13 +33,15 @@ public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegist
|
|||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return new LazilyInitializedManagedBeanImpl<>( beanClass, JpaCdiLifecycleManagementStrategy.INSTANCE );
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||
return new LazilyInitializedManagedBeanImpl<>( beanClass,
|
||||
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
return new LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract, StandardCdiLifecycleManagementStrategy.INSTANCE );
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||
return new LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract,
|
||||
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,13 +39,15 @@ public class ManagedBeanRegistryCdiExtendedImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return new LazilyInitializedManagedBeanImpl<>( beanClass, JpaCdiLifecycleManagementStrategy.INSTANCE );
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||
return new LazilyInitializedManagedBeanImpl<>( beanClass,
|
||||
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
return new LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract, StandardCdiLifecycleManagementStrategy.INSTANCE );
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||
return new LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract,
|
||||
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,12 +34,14 @@ class ManagedBeanRegistryCdiStandardImpl extends AbstractManagedBeanRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return JpaCdiLifecycleManagementStrategy.INSTANCE.createBean( beanManager, beanClass );
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||
return Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle )
|
||||
.createBean( beanManager, beanClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
return StandardCdiLifecycleManagementStrategy.INSTANCE.createBean( beanManager, beanName, beanContract );
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||
return Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle )
|
||||
.createBean( beanManager, beanName, beanContract );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,15 @@ public class ManagedBeanRegistryDirectImpl extends AbstractManagedBeanRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||
return new DirectInstantiationManagedBeanImpl<>( beanClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
protected <T> ManagedBean<T> createBean(
|
||||
String beanName,
|
||||
Class<T> beanContract,
|
||||
boolean shouldRegistryManageLifecycle) {
|
||||
return new DirectInstantiationManagedBeanImpl<>( beanContract );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,21 @@
|
|||
*/
|
||||
package org.hibernate.resource.beans.internal;
|
||||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
|
||||
/**
|
||||
* A {@link CdiLifecycleManagementStrategy} to use when CDI compliance is required
|
||||
* (i.e. when the bean lifecycle is to be managed by the CDI runtime, not the JPA runtime).
|
||||
*
|
||||
* The main characteristic of this strategy is that every create/destroy operation is delegated
|
||||
* to the CDI runtime.
|
||||
*
|
||||
* In particular, @Singleton-scoped or @ApplicationScoped beans are retrieved from the CDI context,
|
||||
* and are not duplicated, in contrast to {@link JpaCdiLifecycleManagementStrategy}.
|
||||
*/
|
||||
class StandardCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrategy {
|
||||
|
||||
static final StandardCdiLifecycleManagementStrategy INSTANCE = new StandardCdiLifecycleManagementStrategy();
|
||||
|
@ -22,38 +31,30 @@ class StandardCdiLifecycleManagementStrategy implements CdiLifecycleManagementSt
|
|||
|
||||
@Override
|
||||
public <T> ManagedBean<T> createBean(BeanManager beanManager, Class<T> beanClass) {
|
||||
Bean<T> bean = Helper.INSTANCE.getBean( beanClass, beanManager );
|
||||
Instance<T> instance = beanManager.createInstance().select( beanClass );
|
||||
T beanInstance = instance.get();
|
||||
|
||||
// Pass the bean to createCreationalContext here so that an existing instance can be returned
|
||||
CreationalContext<T> creationalContext = beanManager.createCreationalContext( bean );
|
||||
|
||||
T beanInstance = bean.create( creationalContext );
|
||||
|
||||
return new BeanManagerManagedBeanImpl<>( beanClass, creationalContext, beanInstance );
|
||||
return new BeanManagerManagedBeanImpl<>( beanClass, instance, beanInstance );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ManagedBean<T> createBean(BeanManager beanManager, String beanName, Class<T> beanClass) {
|
||||
Bean<T> bean = Helper.INSTANCE.getNamedBean( beanName, beanClass, beanManager );
|
||||
Instance<T> instance = beanManager.createInstance().select( beanClass, new NamedBeanQualifier( beanName ) );
|
||||
T beanInstance = instance.get();
|
||||
|
||||
// Pass the bean to createCreationalContext here so that an existing instance can be returned
|
||||
CreationalContext<T> creationalContext = beanManager.createCreationalContext( bean );
|
||||
|
||||
T beanInstance = bean.create( creationalContext );
|
||||
|
||||
return new BeanManagerManagedBeanImpl<>( beanClass, creationalContext, beanInstance );
|
||||
return new BeanManagerManagedBeanImpl<>( beanClass, instance, beanInstance );
|
||||
}
|
||||
|
||||
private static class BeanManagerManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
private final Class<T> beanClass;
|
||||
private final CreationalContext<T> creationContext;
|
||||
private final Instance<T> instance;
|
||||
private final T beanInstance;
|
||||
|
||||
private BeanManagerManagedBeanImpl(
|
||||
Class<T> beanClass,
|
||||
CreationalContext<T> creationContext, T beanInstance) {
|
||||
Instance<T> instance, T beanInstance) {
|
||||
this.beanClass = beanClass;
|
||||
this.creationContext = creationContext;
|
||||
this.instance = instance;
|
||||
this.beanInstance = beanInstance;
|
||||
}
|
||||
|
||||
|
@ -69,7 +70,7 @@ class StandardCdiLifecycleManagementStrategy implements CdiLifecycleManagementSt
|
|||
|
||||
@Override
|
||||
public void release() {
|
||||
creationContext.release();
|
||||
instance.destroy( beanInstance );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
|||
return getCacheableBean( beanClass );
|
||||
}
|
||||
else {
|
||||
return createBean( beanClass );
|
||||
return createBean( beanClass, shouldRegistryManageLifecycle );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,13 +39,13 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
|||
return existing;
|
||||
}
|
||||
|
||||
final ManagedBean<T> bean = createBean( beanClass );
|
||||
final ManagedBean<T> bean = createBean( beanClass, true );
|
||||
registrations.put( beanName, bean );
|
||||
return bean;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected abstract <T> ManagedBean<T> createBean(Class<T> beanClass);
|
||||
protected abstract <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle);
|
||||
|
||||
@Override
|
||||
public <T> ManagedBean<T> getBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||
|
@ -53,7 +53,7 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
|||
return getCacheableBean( beanName, beanContract );
|
||||
}
|
||||
else {
|
||||
return createBean( beanName, beanContract );
|
||||
return createBean( beanName, beanContract, shouldRegistryManageLifecycle );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,13 +64,13 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
|||
return existing;
|
||||
}
|
||||
|
||||
final ManagedBean<T> bean = createBean( beanName, beanContract );
|
||||
final ManagedBean<T> bean = createBean( beanName, beanContract, false );
|
||||
registrations.put( beanName, bean );
|
||||
return bean;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected abstract <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract);
|
||||
protected abstract <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle);
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected void forEachBean(Consumer<ManagedBean<?>> consumer) {
|
||||
|
|
Loading…
Reference in New Issue