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
|
@ -22,24 +22,6 @@ public class Helper {
|
||||||
private 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")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> Bean<T> getNamedBean(String beanName, Class<T> beanContract, BeanManager beanManager) {
|
public <T> Bean<T> getNamedBean(String beanName, Class<T> beanContract, BeanManager beanManager) {
|
||||||
Set<Bean<?>> beans = beanManager.getBeans( beanContract, new NamedBeanQualifier( beanName ) );
|
Set<Bean<?>> beans = beanManager.getBeans( beanContract, new NamedBeanQualifier( beanName ) );
|
||||||
|
@ -57,4 +39,13 @@ public class Helper {
|
||||||
|
|
||||||
return (Bean<T>) beans.iterator().next();
|
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;
|
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 {
|
class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrategy {
|
||||||
|
|
||||||
static final JpaCdiLifecycleManagementStrategy INSTANCE = new JpaCdiLifecycleManagementStrategy();
|
static final JpaCdiLifecycleManagementStrategy INSTANCE = new JpaCdiLifecycleManagementStrategy();
|
||||||
|
@ -44,7 +56,7 @@ class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrateg
|
||||||
|
|
||||||
T beanInstance = bean.create( creationalContext );
|
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> {
|
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 static class NamedJpaManagedBeanImpl<T> implements ManagedBean<T> {
|
||||||
private final Class<T> beanClass;
|
private final Class<T> beanClass;
|
||||||
|
private final Bean<T> bean;
|
||||||
private final CreationalContext<T> creationContext;
|
private final CreationalContext<T> creationContext;
|
||||||
private final T beanInstance;
|
private final T beanInstance;
|
||||||
|
|
||||||
private NamedJpaManagedBeanImpl(
|
private NamedJpaManagedBeanImpl(
|
||||||
Class<T> beanClass,
|
Class<T> beanClass, Bean<T> bean, CreationalContext<T> creationContext, T beanInstance) {
|
||||||
CreationalContext<T> creationContext, T beanInstance) {
|
|
||||||
this.beanClass = beanClass;
|
this.beanClass = beanClass;
|
||||||
|
this.bean = bean;
|
||||||
this.creationContext = creationContext;
|
this.creationContext = creationContext;
|
||||||
this.beanInstance = beanInstance;
|
this.beanInstance = beanInstance;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +118,7 @@ class JpaCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrateg
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
creationContext.release();
|
bean.destroy( beanInstance, creationContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,15 @@ public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegist
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||||
return new LazilyInitializedManagedBeanImpl<>( beanClass, JpaCdiLifecycleManagementStrategy.INSTANCE );
|
return new LazilyInitializedManagedBeanImpl<>( beanClass,
|
||||||
|
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract, StandardCdiLifecycleManagementStrategy.INSTANCE );
|
return new LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract,
|
||||||
|
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,13 +39,15 @@ public class ManagedBeanRegistryCdiExtendedImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||||
return new LazilyInitializedManagedBeanImpl<>( beanClass, JpaCdiLifecycleManagementStrategy.INSTANCE );
|
return new LazilyInitializedManagedBeanImpl<>( beanClass,
|
||||||
|
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract, StandardCdiLifecycleManagementStrategy.INSTANCE );
|
return new LazilyInitializedNamedManagedBeanImpl<>( beanName, beanContract,
|
||||||
|
Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,12 +34,14 @@ class ManagedBeanRegistryCdiStandardImpl extends AbstractManagedBeanRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||||
return JpaCdiLifecycleManagementStrategy.INSTANCE.createBean( beanManager, beanClass );
|
return Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle )
|
||||||
|
.createBean( beanManager, beanClass );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||||
return StandardCdiLifecycleManagementStrategy.INSTANCE.createBean( beanManager, beanName, beanContract );
|
return Helper.INSTANCE.getLifecycleManagementStrategy( shouldRegistryManageLifecycle )
|
||||||
|
.createBean( beanManager, beanName, beanContract );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,15 @@ public class ManagedBeanRegistryDirectImpl extends AbstractManagedBeanRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
protected <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||||
return new DirectInstantiationManagedBeanImpl<>( beanClass );
|
return new DirectInstantiationManagedBeanImpl<>( beanClass );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 );
|
return new DirectInstantiationManagedBeanImpl<>( beanContract );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,21 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.resource.beans.internal;
|
package org.hibernate.resource.beans.internal;
|
||||||
|
|
||||||
import javax.enterprise.context.spi.CreationalContext;
|
import javax.enterprise.inject.Instance;
|
||||||
import javax.enterprise.inject.spi.Bean;
|
|
||||||
import javax.enterprise.inject.spi.BeanManager;
|
import javax.enterprise.inject.spi.BeanManager;
|
||||||
|
|
||||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
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 {
|
class StandardCdiLifecycleManagementStrategy implements CdiLifecycleManagementStrategy {
|
||||||
|
|
||||||
static final StandardCdiLifecycleManagementStrategy INSTANCE = new StandardCdiLifecycleManagementStrategy();
|
static final StandardCdiLifecycleManagementStrategy INSTANCE = new StandardCdiLifecycleManagementStrategy();
|
||||||
|
@ -22,38 +31,30 @@ class StandardCdiLifecycleManagementStrategy implements CdiLifecycleManagementSt
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ManagedBean<T> createBean(BeanManager beanManager, Class<T> beanClass) {
|
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
|
return new BeanManagerManagedBeanImpl<>( beanClass, instance, beanInstance );
|
||||||
CreationalContext<T> creationalContext = beanManager.createCreationalContext( bean );
|
|
||||||
|
|
||||||
T beanInstance = bean.create( creationalContext );
|
|
||||||
|
|
||||||
return new BeanManagerManagedBeanImpl<>( beanClass, creationalContext, beanInstance );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ManagedBean<T> createBean(BeanManager beanManager, String beanName, Class<T> beanClass) {
|
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
|
return new BeanManagerManagedBeanImpl<>( beanClass, instance, beanInstance );
|
||||||
CreationalContext<T> creationalContext = beanManager.createCreationalContext( bean );
|
|
||||||
|
|
||||||
T beanInstance = bean.create( creationalContext );
|
|
||||||
|
|
||||||
return new BeanManagerManagedBeanImpl<>( beanClass, creationalContext, beanInstance );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BeanManagerManagedBeanImpl<T> implements ManagedBean<T> {
|
private static class BeanManagerManagedBeanImpl<T> implements ManagedBean<T> {
|
||||||
private final Class<T> beanClass;
|
private final Class<T> beanClass;
|
||||||
private final CreationalContext<T> creationContext;
|
private final Instance<T> instance;
|
||||||
private final T beanInstance;
|
private final T beanInstance;
|
||||||
|
|
||||||
private BeanManagerManagedBeanImpl(
|
private BeanManagerManagedBeanImpl(
|
||||||
Class<T> beanClass,
|
Class<T> beanClass,
|
||||||
CreationalContext<T> creationContext, T beanInstance) {
|
Instance<T> instance, T beanInstance) {
|
||||||
this.beanClass = beanClass;
|
this.beanClass = beanClass;
|
||||||
this.creationContext = creationContext;
|
this.instance = instance;
|
||||||
this.beanInstance = beanInstance;
|
this.beanInstance = beanInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ class StandardCdiLifecycleManagementStrategy implements CdiLifecycleManagementSt
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
creationContext.release();
|
instance.destroy( beanInstance );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
||||||
return getCacheableBean( beanClass );
|
return getCacheableBean( beanClass );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createBean( beanClass );
|
return createBean( beanClass, shouldRegistryManageLifecycle );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,13 +39,13 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ManagedBean<T> bean = createBean( beanClass );
|
final ManagedBean<T> bean = createBean( beanClass, true );
|
||||||
registrations.put( beanName, bean );
|
registrations.put( beanName, bean );
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected abstract <T> ManagedBean<T> createBean(Class<T> beanClass);
|
protected abstract <T> ManagedBean<T> createBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ManagedBean<T> getBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
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 );
|
return getCacheableBean( beanName, beanContract );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createBean( beanName, beanContract );
|
return createBean( beanName, beanContract, shouldRegistryManageLifecycle );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +64,13 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ManagedBean<T> bean = createBean( beanName, beanContract );
|
final ManagedBean<T> bean = createBean( beanName, beanContract, false );
|
||||||
registrations.put( beanName, bean );
|
registrations.put( beanName, bean );
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@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")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected void forEachBean(Consumer<ManagedBean<?>> consumer) {
|
protected void forEachBean(Consumer<ManagedBean<?>> consumer) {
|
||||||
|
|
Loading…
Reference in New Issue