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 support for named CDI beans and the option to not cache bean references
This commit is contained in:
parent
9f50157a60
commit
ddc1f03abc
|
@ -755,10 +755,20 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
|
||||
settings.getMultiTableBulkIdStrategy().release( serviceRegistry.getService( JdbcServices.class ), buildLocalConnectionAccess() );
|
||||
|
||||
cacheAccess.close();
|
||||
metamodel.close();
|
||||
// NOTE : the null checks below handle cases where close is called from
|
||||
// a failed attempt to create the SessionFactory
|
||||
|
||||
queryPlanCache.cleanup();
|
||||
if ( cacheAccess != null ) {
|
||||
cacheAccess.close();
|
||||
}
|
||||
|
||||
if ( metamodel != null ) {
|
||||
metamodel.close();
|
||||
}
|
||||
|
||||
if ( queryPlanCache != null ) {
|
||||
queryPlanCache.cleanup();
|
||||
}
|
||||
|
||||
if ( delayedDropAction != null ) {
|
||||
delayedDropAction.perform( serviceRegistry );
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
|
|||
import org.hibernate.jmx.spi.JmxService;
|
||||
import org.hibernate.service.Service;
|
||||
import org.hibernate.service.spi.Manageable;
|
||||
import org.hibernate.service.spi.OptionallyManageable;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
|
||||
/**
|
||||
|
@ -106,6 +107,13 @@ public class JmxServiceImpl implements JmxService, Stoppable {
|
|||
|
||||
@Override
|
||||
public void registerService(Manageable service, Class<? extends Service> serviceRole) {
|
||||
if ( OptionallyManageable.class.isInstance( service ) ) {
|
||||
for ( Manageable realManageable : ( (OptionallyManageable) service ).getRealManageables() ) {
|
||||
registerService( realManageable,serviceRole );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String domain = service.getManagementDomain() == null
|
||||
? AvailableSettings.JMX_DEFAULT_OBJ_NAME_DOMAIN
|
||||
: service.getManagementDomain();
|
||||
|
|
|
@ -23,7 +23,7 @@ public interface JmxService extends Service {
|
|||
* @param service The manageable service
|
||||
* @param serviceRole The service's role.
|
||||
*/
|
||||
public void registerService(Manageable service, Class<? extends Service> serviceRole);
|
||||
void registerService(Manageable service, Class<? extends Service> serviceRole);
|
||||
|
||||
/**
|
||||
* Registers the given {@code mBean} under the given {@code objectName}
|
||||
|
@ -31,5 +31,5 @@ public interface JmxService extends Service {
|
|||
* @param objectName The name under which to register the MBean
|
||||
* @param mBean The MBean to register
|
||||
*/
|
||||
public void registerMBean(ObjectName objectName, Object mBean);
|
||||
void registerMBean(ObjectName objectName, Object mBean);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "WeakerAccess"})
|
||||
public Callback[] resolveCallbacks(XClass beanClass, CallbackType callbackType, ReflectionManager reflectionManager) {
|
||||
List<Callback> callbacks = new ArrayList<>();
|
||||
List<String> callbacksMethodNames = new ArrayList<>();
|
||||
|
@ -162,7 +163,7 @@ public class CallbackBuilderLegacyImpl implements CallbackBuilder {
|
|||
//overridden method, remove the superclass overridden method
|
||||
if ( callback == null ) {
|
||||
callback = new ListenerCallback(
|
||||
managedBeanRegistry.getBean( listener ),
|
||||
managedBeanRegistry.getBean( listener, true ),
|
||||
method,
|
||||
callbackType
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ public interface BeansMessageLogger {
|
|||
/**
|
||||
* *The* BeansMessageLogger instance
|
||||
*/
|
||||
BeansMessageLogger CDI_LOGGER = Logger.getMessageLogger(
|
||||
BeansMessageLogger BEANS_LOGGER = Logger.getMessageLogger(
|
||||
BeansMessageLogger.class,
|
||||
"org.hibernate.orm.beans"
|
||||
);
|
||||
|
|
|
@ -6,56 +6,142 @@
|
|||
*/
|
||||
package org.hibernate.resource.beans.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.service.spi.Configurable;
|
||||
import org.hibernate.service.spi.Manageable;
|
||||
import org.hibernate.service.spi.OptionallyManageable;
|
||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.Startable;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* A ManagedBeanRegistry implementation that can delegate to multiple
|
||||
* other ManagedBeanRegistry instances, until one can handle the given call.
|
||||
* A ManagedBeanRegistry that supports a single primary ManagedBeanRegistry
|
||||
* delegate falling back to {@link ManagedBeanRegistryDirectImpl} for direct
|
||||
* instantiation (no DI).
|
||||
*
|
||||
* Note too that it supports all of the optional Service contracts and delegates
|
||||
* them to the primary if the primary also implements that particular contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositeManagedBeanRegistry implements ManagedBeanRegistry {
|
||||
public class CompositeManagedBeanRegistry
|
||||
implements ManagedBeanRegistry, Startable, Stoppable, Configurable, ServiceRegistryAwareService, OptionallyManageable {
|
||||
private static final Logger log = Logger.getLogger( CompositeManagedBeanRegistry.class );
|
||||
|
||||
private List<ManagedBeanRegistry> delegates;
|
||||
private final ManagedBeanRegistry primaryRegistry;
|
||||
private final ManagedBeanRegistryDirectImpl fallback = new ManagedBeanRegistryDirectImpl();
|
||||
|
||||
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 ) );
|
||||
public CompositeManagedBeanRegistry(ManagedBeanRegistry primaryRegistry) {
|
||||
this.primaryRegistry = primaryRegistry;
|
||||
}
|
||||
|
||||
@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) {
|
||||
}
|
||||
|
||||
public <T> ManagedBean<T> getBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||
if ( primaryRegistry != null ) {
|
||||
try {
|
||||
final ManagedBean<T> bean = primaryRegistry.getBean( beanClass, shouldRegistryManageLifecycle );
|
||||
if ( bean != null ) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
log.debugf(
|
||||
"Error obtaining ManagedBean [%s] from registry [%s] - using fallback registry",
|
||||
beanClass.getName(),
|
||||
primaryRegistry
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return delegateAction.apply( ManagedBeanRegistryDirectImpl.INSTANCE );
|
||||
return fallback.getBean( beanClass, shouldRegistryManageLifecycle );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ManagedBean<T> getBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||
if ( primaryRegistry != null ) {
|
||||
try {
|
||||
final ManagedBean<T> bean = primaryRegistry.getBean( beanName, beanContract,shouldRegistryManageLifecycle );
|
||||
if ( bean != null ) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
log.debugf(
|
||||
"Error obtaining ManagedBean [%s : %s] from registry [%s] - using fallback registry",
|
||||
beanName,
|
||||
beanContract.getName(),
|
||||
primaryRegistry
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return fallback.getBean( beanName, beanContract,shouldRegistryManageLifecycle );
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Optional delegation
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if ( primaryRegistry == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Startable.class.isInstance( primaryRegistry ) ) {
|
||||
Startable.class.cast( primaryRegistry ).start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Map configurationValues) {
|
||||
if ( primaryRegistry == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Configurable.class.isInstance( primaryRegistry ) ) {
|
||||
Configurable.class.cast( primaryRegistry ).configure( configurationValues );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||
if ( primaryRegistry == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ServiceRegistryAwareService.class.isInstance( primaryRegistry ) ) {
|
||||
ServiceRegistryAwareService.class.cast( primaryRegistry ).injectServices( serviceRegistry );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Manageable> getRealManageables() {
|
||||
if ( primaryRegistry != null ) {
|
||||
if ( Manageable.class.isInstance( primaryRegistry ) ) {
|
||||
return Collections.singletonList( (Manageable) primaryRegistry );
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if ( primaryRegistry == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Stoppable.class.isInstance( primaryRegistry ) ) {
|
||||
Stoppable.class.cast( primaryRegistry ).stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.Set;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Helper {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final Helper INSTANCE = new Helper();
|
||||
|
||||
private Helper() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Bean<T> getNamedBean(String beanName, Class<T> beanContract, BeanManager beanManager) {
|
||||
Set<Bean<?>> beans = beanManager.getBeans( beanContract, new NamedBeanQualifier( beanName ) );
|
||||
|
||||
if ( beans.isEmpty() ) {
|
||||
throw new IllegalArgumentException(
|
||||
"BeanManager returned no matching beans: name = " + beanName + "; contract = " + beanContract.getName()
|
||||
);
|
||||
}
|
||||
if ( beans.size() > 1 ) {
|
||||
throw new IllegalArgumentException(
|
||||
"BeanManager returned multiple matching beans: name = " + beanName + "; contract = " + beanContract.getName()
|
||||
);
|
||||
}
|
||||
|
||||
return (Bean<T>) beans.iterator().next();
|
||||
}
|
||||
}
|
|
@ -23,6 +23,9 @@ import org.hibernate.service.ServiceRegistry;
|
|||
/**
|
||||
* Utility class for helping deal with the reflection calls relating to CDI.
|
||||
*
|
||||
* We need to to avoid statically linking CDI classed into the ClassLoader which
|
||||
* would lead to errors if CDI is not available on the classpath.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ManagedBeanRegistryCdiBuilder {
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.resource.beans.internal;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.AnnotatedType;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.InjectionTarget;
|
||||
|
||||
|
@ -32,12 +34,17 @@ public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegist
|
|||
|
||||
private ManagedBeanRegistryCdiDelayedImpl(BeanManager beanManager) {
|
||||
this.beanManager = beanManager;
|
||||
log.debugf( "Delayed access requested to CDI BeanManager : " + beanManager );
|
||||
log.debugf( "Delayed access requested to CDI BeanManager" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return new ManagedBeanImpl<>( beanClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
return new ManagedBeanImpl<>( beanContract );
|
||||
return new NamedManagedBeanImpl<>( beanName, beanContract );
|
||||
}
|
||||
|
||||
private class ManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
|
@ -46,10 +53,10 @@ public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegist
|
|||
private boolean initialized = false;
|
||||
|
||||
private InjectionTarget<T> injectionTarget;
|
||||
private CreationalContext<T> creationalContext;
|
||||
private CreationalContext<T> creationContext;
|
||||
private T beanInstance;
|
||||
|
||||
public ManagedBeanImpl(Class<T> beanClass) {
|
||||
ManagedBeanImpl(Class<T> beanClass) {
|
||||
this.beanClass = beanClass;
|
||||
}
|
||||
|
||||
|
@ -71,10 +78,10 @@ public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegist
|
|||
|
||||
final AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( beanClass );
|
||||
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
|
||||
this.creationalContext = beanManager.createCreationalContext( null );
|
||||
this.creationContext = beanManager.createCreationalContext( null );
|
||||
|
||||
this.beanInstance = injectionTarget.produce( creationalContext );
|
||||
injectionTarget.inject( this.beanInstance, creationalContext );
|
||||
this.beanInstance = injectionTarget.produce( creationContext );
|
||||
injectionTarget.inject( this.beanInstance, creationContext );
|
||||
|
||||
injectionTarget.postConstruct( this.beanInstance );
|
||||
|
||||
|
@ -84,15 +91,69 @@ public class ManagedBeanRegistryCdiDelayedImpl extends AbstractManagedBeanRegist
|
|||
@Override
|
||||
public void release() {
|
||||
if ( !initialized ) {
|
||||
log.debug( "Skipping release for delayed CDI bean [" + beanClass + "] as it was not initialized" );
|
||||
log.debug( "Skipping release for (delayed) CDI bean [" + beanClass + "] as it was not initialized" );
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug( "Releasing CDI listener : " + beanClass );
|
||||
log.debug( "Releasing (delayed) CDI bean : " + beanClass );
|
||||
|
||||
injectionTarget.preDestroy( beanInstance );
|
||||
injectionTarget.dispose( beanInstance );
|
||||
creationalContext.release();
|
||||
creationContext.release();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
private class NamedManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
private final String beanName;
|
||||
private final Class<T> beanContract;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private CreationalContext<T> creationContext;
|
||||
private T beanInstance;
|
||||
|
||||
NamedManagedBeanImpl(String beanName, Class<T> beanContract) {
|
||||
this.beanName = beanName;
|
||||
this.beanContract = beanContract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getBeanClass() {
|
||||
return beanContract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getBeanInstance() {
|
||||
if ( !initialized ) {
|
||||
initialize();
|
||||
}
|
||||
return beanInstance;
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
final Bean<T> bean = Helper.INSTANCE.getNamedBean( beanName, beanContract, beanManager );
|
||||
|
||||
this.creationContext = beanManager.createCreationalContext( bean );
|
||||
this.beanInstance = beanContract.cast( beanManager.getReference( bean, beanContract, creationContext ) );
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if ( !initialized ) {
|
||||
log.debugf( "Skipping release for (delayed) CDI bean [%s : %s] as it was not initialized", beanName, beanContract.getName() );
|
||||
return;
|
||||
}
|
||||
|
||||
log.debugf( "Releasing (delayed) CDI bean [%s : %s]", beanName, beanContract.getName() );
|
||||
|
||||
creationContext.release();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ package org.hibernate.resource.beans.internal;
|
|||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.AnnotatedType;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.InjectionTarget;
|
||||
|
||||
|
@ -41,9 +42,14 @@ public class ManagedBeanRegistryCdiExtendedImpl
|
|||
log.debugf( "Extended access requested to CDI BeanManager : " + beanManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return new ManagedBeanImpl<>( beanClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
return new ManagedBeanImpl<>( beanContract );
|
||||
return new NamedManagedBeanImpl<>( beanName, beanContract );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,27 +73,13 @@ public class ManagedBeanRegistryCdiExtendedImpl
|
|||
private boolean initialized = false;
|
||||
|
||||
private InjectionTarget<T> injectionTarget;
|
||||
private CreationalContext<T> creationalContext;
|
||||
private CreationalContext<T> creationContext;
|
||||
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;
|
||||
|
@ -101,16 +93,86 @@ public class ManagedBeanRegistryCdiExtendedImpl
|
|||
return beanInstance;
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
final BeanManager beanManager = getUsableBeanManager();
|
||||
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( beanClass );
|
||||
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
|
||||
this.creationContext = beanManager.createCreationalContext( null );
|
||||
|
||||
this.beanInstance = injectionTarget.produce( creationContext );
|
||||
injectionTarget.inject( this.beanInstance, creationContext );
|
||||
|
||||
injectionTarget.postConstruct( this.beanInstance );
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if ( !initialized ) {
|
||||
// log
|
||||
log.debugf( "Skipping release for (extended) CDI bean [%s] as it was not initialized", beanClass.getName() );
|
||||
return;
|
||||
}
|
||||
|
||||
log.debugf( "Releasing (extended) CDI bean [%s]", beanClass.getName() );
|
||||
|
||||
injectionTarget.preDestroy( beanInstance );
|
||||
injectionTarget.dispose( beanInstance );
|
||||
creationalContext.release();
|
||||
creationContext.release();
|
||||
}
|
||||
}
|
||||
|
||||
private class NamedManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
private final String beanName;
|
||||
private final Class<T> beanContract;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private CreationalContext<T> creationContext;
|
||||
private T beanInstance;
|
||||
|
||||
public NamedManagedBeanImpl(
|
||||
String beanName,
|
||||
Class<T> beanContract) {
|
||||
this.beanName = beanName;
|
||||
this.beanContract = beanContract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getBeanClass() {
|
||||
return beanContract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getBeanInstance() {
|
||||
if ( !initialized ) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
return beanInstance;
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
final BeanManager beanManager = getUsableBeanManager();
|
||||
final Bean<T> bean = Helper.INSTANCE.getNamedBean( beanName, beanContract, beanManager );
|
||||
|
||||
this.creationContext = beanManager.createCreationalContext( bean );
|
||||
this.beanInstance = beanContract.cast( beanManager.getReference( bean, beanContract, creationContext ) );
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if ( !initialized ) {
|
||||
log.debugf( "Skipping release for (extended) CDI bean [%s : %s] as it was not initialized", beanName, beanContract.getName() );
|
||||
return;
|
||||
}
|
||||
|
||||
log.debugf( "Releasing (extended) CDI bean [%s : %s]", beanName, beanContract.getName() );
|
||||
|
||||
creationContext.release();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ package org.hibernate.resource.beans.internal;
|
|||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.AnnotatedType;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.InjectionTarget;
|
||||
|
||||
|
@ -36,15 +37,23 @@ class ManagedBeanRegistryCdiStandardImpl extends AbstractManagedBeanRegistry {
|
|||
log.debugf( "Standard access requested to CDI BeanManager : " + beanManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return new ManagedBeanImpl<>( beanClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(String beanName, Class<T> beanContract) {
|
||||
return new ManagedBeanImpl<>( beanContract );
|
||||
return new NamedManagedBeanImpl<>( beanName, beanContract );
|
||||
}
|
||||
|
||||
private class ManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
private final Class<T> beanClass;
|
||||
private final InjectionTarget<T> injectionTarget;
|
||||
private final CreationalContext<T> creationalContext;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private final CreationalContext<T> creationContext;
|
||||
private final T beanInstance;
|
||||
|
||||
public ManagedBeanImpl(Class<T> beanClass) {
|
||||
|
@ -52,10 +61,10 @@ class ManagedBeanRegistryCdiStandardImpl extends AbstractManagedBeanRegistry {
|
|||
|
||||
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType( beanClass );
|
||||
this.injectionTarget = beanManager.createInjectionTarget( annotatedType );
|
||||
this.creationalContext = beanManager.createCreationalContext( null );
|
||||
this.creationContext = beanManager.createCreationalContext( null );
|
||||
|
||||
this.beanInstance = injectionTarget.produce( creationalContext );
|
||||
injectionTarget.inject( this.beanInstance, creationalContext );
|
||||
this.beanInstance = injectionTarget.produce( creationContext );
|
||||
injectionTarget.inject( this.beanInstance, creationContext );
|
||||
|
||||
injectionTarget.postConstruct( this.beanInstance );
|
||||
}
|
||||
|
@ -72,9 +81,61 @@ class ManagedBeanRegistryCdiStandardImpl extends AbstractManagedBeanRegistry {
|
|||
|
||||
@Override
|
||||
public void release() {
|
||||
if ( !initialized ) {
|
||||
log.debugf( "Skipping release for (standard) CDI bean [%s] as it was not initialized", beanClass.getName() );
|
||||
return;
|
||||
}
|
||||
|
||||
log.debugf( "Releasing (standard) CDI bean [%s]", beanClass.getName() );
|
||||
|
||||
injectionTarget.preDestroy( beanInstance );
|
||||
injectionTarget.dispose( beanInstance );
|
||||
creationalContext.release();
|
||||
creationContext.release();
|
||||
}
|
||||
}
|
||||
|
||||
private class NamedManagedBeanImpl<T> implements ManagedBean<T> {
|
||||
private final String beanName;
|
||||
private final Class<T> beanContract;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private CreationalContext<T> creationContext;
|
||||
private T beanInstance;
|
||||
|
||||
private NamedManagedBeanImpl(String beanName, Class<T> beanContract) {
|
||||
this.beanName = beanName;
|
||||
this.beanContract = beanContract;
|
||||
|
||||
final Bean<T> bean = Helper.INSTANCE.getNamedBean( beanName, beanContract, beanManager );
|
||||
|
||||
this.creationContext = beanManager.createCreationalContext( bean );
|
||||
this.beanInstance = beanContract.cast( beanManager.getReference( bean, beanContract, creationContext ) );
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
@Override
|
||||
public Class<T> getBeanClass() {
|
||||
return beanContract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getBeanInstance() {
|
||||
return beanInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if ( !initialized ) {
|
||||
log.debugf( "Skipping release for (standard) CDI bean [%s : %s] as it was not initialized", beanName, beanContract.getName() );
|
||||
return;
|
||||
}
|
||||
|
||||
log.debugf( "Releasing (standard) CDI bean [%s : %s]", beanName, beanContract.getName() );
|
||||
|
||||
creationContext.release();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,12 +23,13 @@ public class ManagedBeanRegistryDirectImpl extends AbstractManagedBeanRegistry {
|
|||
|
||||
private static final Logger log = Logger.getLogger( ManagedBeanRegistryDirectImpl.class );
|
||||
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final ManagedBeanRegistryDirectImpl INSTANCE = new ManagedBeanRegistryDirectImpl();
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public ManagedBeanRegistryDirectImpl() {
|
||||
}
|
||||
|
||||
private ManagedBeanRegistryDirectImpl() {
|
||||
@Override
|
||||
protected <T> ManagedBean<T> createBean(Class<T> beanClass) {
|
||||
return new ManagedBeanImpl<>( beanClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.inject.Named;
|
||||
|
||||
/**
|
||||
* Used to locate named CDI beans.
|
||||
*
|
||||
* @author Yoann Rodière
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
class NamedBeanQualifier extends javax.enterprise.util.AnnotationLiteral<Named> implements Named {
|
||||
private final String name;
|
||||
|
||||
NamedBeanQualifier(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String value() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -22,9 +22,44 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
|||
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 );
|
||||
public <T> ManagedBean<T> getBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle) {
|
||||
if ( shouldRegistryManageLifecycle ) {
|
||||
return getCacheableBean( beanClass );
|
||||
}
|
||||
else {
|
||||
return createBean( beanClass );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unchecked"})
|
||||
protected <T> ManagedBean<T> getCacheableBean(Class<T> beanClass) {
|
||||
final String beanName = beanClass.getName();
|
||||
final ManagedBean existing = registrations.get( beanName );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final ManagedBean<T> bean = createBean( beanClass );
|
||||
registrations.put( beanName, bean );
|
||||
return bean;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected abstract <T> ManagedBean<T> createBean(Class<T> beanClass);
|
||||
|
||||
@Override
|
||||
public <T> ManagedBean<T> getBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle) {
|
||||
if ( shouldRegistryManageLifecycle ) {
|
||||
return getCacheableBean( beanName, beanContract );
|
||||
}
|
||||
else {
|
||||
return createBean( beanName, beanContract );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unchecked"})
|
||||
protected <T> ManagedBean<T> getCacheableBean(String beanName, Class<T> beanContract) {
|
||||
final ManagedBean existing = registrations.get( beanName );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
@ -44,7 +79,7 @@ public abstract class AbstractManagedBeanRegistry implements ManagedBeanRegistry
|
|||
|
||||
@Override
|
||||
public void stop() {
|
||||
BeansMessageLogger.CDI_LOGGER.stoppingManagedBeanRegistry( this );
|
||||
BeansMessageLogger.BEANS_LOGGER.stoppingManagedBeanRegistry( this );
|
||||
forEachBean( ManagedBean::release );
|
||||
registrations.clear();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,18 @@ package org.hibernate.resource.beans.spi;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ManagedBean<T> {
|
||||
/**
|
||||
* The bean Java type
|
||||
*/
|
||||
Class<T> getBeanClass();
|
||||
|
||||
/**
|
||||
* The bean reference
|
||||
*/
|
||||
T getBeanInstance();
|
||||
|
||||
/**
|
||||
* Release any resources
|
||||
*/
|
||||
void release();
|
||||
}
|
|
@ -18,15 +18,32 @@ import org.hibernate.service.Service;
|
|||
*/
|
||||
public interface ManagedBeanRegistry extends Service {
|
||||
/**
|
||||
* Get a bean reference, by class. By default, calls
|
||||
* {@link #getBean(String, Class)} using the beanClass's name
|
||||
* Get a bean reference, by class.
|
||||
*
|
||||
* @apiNote `shouldRegistryManageLifecycle` has multiple implications that are
|
||||
* important to understand. First it indicates whether the registry should
|
||||
* handle releasing (end lifecycle) the bean or whether the caller will handle
|
||||
* that. It also indicates whether cached references will be returned, or whether
|
||||
* new references will be returned each time. `true` means that cached references
|
||||
* can be returned and the registry will handle releasing when the registry is itself
|
||||
* released (generally when the SessionFactory is closed). `false` means that
|
||||
* new references should be returned for every call and the caller will handle
|
||||
* the release calls itself.
|
||||
*/
|
||||
default <T> ManagedBean<T> getBean(Class<T> beanClass) {
|
||||
return getBean( beanClass.getName(), beanClass );
|
||||
}
|
||||
<T> ManagedBean<T> getBean(Class<T> beanClass, boolean shouldRegistryManageLifecycle);
|
||||
|
||||
/**
|
||||
* Get a bean reference by name, typed as the given bean contract.
|
||||
* Get a bean reference by name and contract.
|
||||
*
|
||||
* @apiNote `shouldRegistryManageLifecycle` has multiple implications that are
|
||||
* important to understand. First it indicates whether the registry should
|
||||
* handle releasing (end lifecycle) the bean or whether the caller will handle
|
||||
* that. It also indicates whether cached references will be returned, or whether
|
||||
* new references will be returned each time. `true` means that cached references
|
||||
* can be returned and the registry will handle releasing when the registry is itself
|
||||
* released (generally when the SessionFactory is closed). `false` means that
|
||||
* new references should be returned for every call and the caller will handle
|
||||
* the release calls itself.
|
||||
*/
|
||||
<T> ManagedBean<T> getBean(String beanName, Class<T> contract);
|
||||
<T> ManagedBean<T> getBean(String beanName, Class<T> beanContract, boolean shouldRegistryManageLifecycle);
|
||||
}
|
|
@ -43,8 +43,7 @@ public class ManagedBeanRegistryInitiator implements StandardServiceInitiator<Ma
|
|||
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
final ConfigurationService cfgSvc = serviceRegistry.getService( ConfigurationService.class );
|
||||
|
||||
final CompositeManagedBeanRegistry beanRegistry = new CompositeManagedBeanRegistry();
|
||||
|
||||
ManagedBeanRegistry primaryCdiBasedRegistry = null;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// apply CDI support
|
||||
|
@ -53,15 +52,18 @@ public class ManagedBeanRegistryInitiator implements StandardServiceInitiator<Ma
|
|||
final Object beanManagerRef = cfgSvc.getSettings().get( AvailableSettings.CDI_BEAN_MANAGER );
|
||||
if ( beanManagerRef != null ) {
|
||||
if ( !isCdiAvailable ) {
|
||||
BeansMessageLogger.CDI_LOGGER.beanManagerButCdiNotAvailable( beanManagerRef );
|
||||
BeansMessageLogger.BEANS_LOGGER.beanManagerButCdiNotAvailable( beanManagerRef );
|
||||
}
|
||||
|
||||
beanRegistry.addDelegate(
|
||||
ManagedBeanRegistryCdiBuilder.fromBeanManagerReference( beanManagerRef, serviceRegistry )
|
||||
);
|
||||
primaryCdiBasedRegistry = ManagedBeanRegistryCdiBuilder.fromBeanManagerReference( beanManagerRef, serviceRegistry );
|
||||
}
|
||||
else {
|
||||
if ( isCdiAvailable ) {
|
||||
BeansMessageLogger.BEANS_LOGGER.noBeanManagerButCdiAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
return beanRegistry;
|
||||
return new CompositeManagedBeanRegistry( primaryCdiBasedRegistry );
|
||||
}
|
||||
|
||||
private static boolean isCdiAvailable(ClassLoaderService classLoaderService) {
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.util.Set;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistry;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.service.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extension to Manageable for things that are optionally Manageable depending
|
||||
* on some internal state. E.g. services that wrap other services wanting to
|
||||
* delegate manageablity if the wrapped service is Manageable.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface OptionallyManageable extends Manageable {
|
||||
/**
|
||||
* Any wrapped services that are Manageable. Never return `null`; an empty
|
||||
* List should be returned instead.
|
||||
*/
|
||||
List<Manageable> getRealManageables();
|
||||
|
||||
@Override
|
||||
default String getManagementDomain() {
|
||||
// Generally the wrapper is not Manageable itself
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getManagementServiceType() {
|
||||
// Generally the wrapper is not Manageable itself
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
default Object getManagementBean() {
|
||||
// Generally the wrapper is not Manageable itself
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue