HHH-8923 - Reconsider closing of ServiceRegistry instances

Conflicts:
	hibernate-core/src/main/java/org/hibernate/boot/registry/BootstrapServiceRegistryBuilder.java
	hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java
	hibernate-core/src/main/java/org/hibernate/boot/registry/internal/BootstrapServiceRegistryImpl.java
	hibernate-core/src/main/java/org/hibernate/boot/registry/internal/StandardServiceRegistryImpl.java
	hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java
	hibernate-core/src/test/java/org/hibernate/connection/ConnectionCreatorTest.java
This commit is contained in:
Steve Ebersole 2014-03-26 11:04:58 -05:00 committed by Brett Meyer
parent f95dfddd8c
commit 601a293c0e
5 changed files with 125 additions and 12 deletions

View File

@ -45,6 +45,7 @@ public class BootstrapServiceRegistryBuilder {
private final LinkedHashSet<Integrator> providedIntegrators = new LinkedHashSet<Integrator>(); private final LinkedHashSet<Integrator> providedIntegrators = new LinkedHashSet<Integrator>();
private List<ClassLoader> providedClassLoaders; private List<ClassLoader> providedClassLoaders;
private ClassLoaderService providedClassLoaderService; private ClassLoaderService providedClassLoaderService;
private boolean autoCloseRegistry = true;
/** /**
* Add an {@link Integrator} to be applied to the bootstrap registry. * Add an {@link Integrator} to be applied to the bootstrap registry.
@ -141,6 +142,35 @@ public class BootstrapServiceRegistryBuilder {
public BootstrapServiceRegistryBuilder withEnvironmentClassLoader(ClassLoader classLoader) { public BootstrapServiceRegistryBuilder withEnvironmentClassLoader(ClassLoader classLoader) {
return with( classLoader ); return with( classLoader );
} }
/**
* By default, when a ServiceRegistry is no longer referenced by any other
* registries as a parent it will be closed.
* <p/>
* Some applications that explicitly build "shared registries" may want to
* circumvent that behavior.
* <p/>
* This method indicates that the registry being built should not be
* automatically closed. The caller agrees to take responsibility to
* close it themselves.
*
* @return this, for method chaining
*/
public BootstrapServiceRegistryBuilder disableAutoClose() {
this.autoCloseRegistry = false;
return this;
}
/**
* See the discussion on {@link #disableAutoClose}. This method enables
* the auto-closing.
*
* @return this, for method chaining
*/
public BootstrapServiceRegistryBuilder enableAutoClose() {
this.autoCloseRegistry = true;
return this;
}
/** /**
* Build the bootstrap registry. * Build the bootstrap registry.
@ -160,6 +190,6 @@ public class BootstrapServiceRegistryBuilder {
classLoaderService classLoaderService
); );
return new BootstrapServiceRegistryImpl( classLoaderService, integratorService ); return new BootstrapServiceRegistryImpl( autoCloseRegistry, classLoaderService, integratorService );
} }
} }

View File

@ -66,6 +66,8 @@ public class ServiceRegistryBuilder {
private final Map settings; private final Map settings;
private final List<BasicServiceInitiator> initiators = standardInitiatorList(); private final List<BasicServiceInitiator> initiators = standardInitiatorList();
private final List<ProvidedService> providedServices = new ArrayList<ProvidedService>(); private final List<ProvidedService> providedServices = new ArrayList<ProvidedService>();
private boolean autoCloseRegistry = true;
private final BootstrapServiceRegistry bootstrapServiceRegistry; private final BootstrapServiceRegistry bootstrapServiceRegistry;
@ -232,6 +234,34 @@ public class ServiceRegistryBuilder {
providedServices.add( new ProvidedService( serviceRole, service ) ); providedServices.add( new ProvidedService( serviceRole, service ) );
return this; return this;
} }
/**
* By default, when a ServiceRegistry is no longer referenced by any other
* registries as a parent it will be closed.
* <p/>
* Some applications that explicitly build "shared registries" may want to
* circumvent that behavior.
* <p/>
* This method indicates that the registry being built should not be
* automatically closed. The caller agrees to take responsibility to
* close it themselves.
*
* @return this, for method chaining
*/
public ServiceRegistryBuilder disableAutoClose() {
this.autoCloseRegistry = false;
return this;
}
/**
* See the discussion on {@link #disableAutoClose}. This method enables
* the auto-closing.
*
* @return this, for method chaining
*/
public ServiceRegistryBuilder enableAutoClose() {
this.autoCloseRegistry = true;
return this;
}
/** /**
* Build the service registry accounting for all settings and service initiators and services. * Build the service registry accounting for all settings and service initiators and services.
@ -250,7 +280,7 @@ public class ServiceRegistryBuilder {
} }
} }
return new StandardServiceRegistryImpl( bootstrapServiceRegistry, initiators, providedServices, settingsCopy ); return new StandardServiceRegistryImpl( autoCloseRegistry, bootstrapServiceRegistry, initiators, providedServices, settingsCopy );
} }
/** /**

View File

@ -67,6 +67,7 @@ public abstract class AbstractServiceRegistryImpl
// assume 20 services for initial sizing // assume 20 services for initial sizing
private final List<ServiceBinding> serviceBindingList = CollectionHelper.arrayList( 20 ); private final List<ServiceBinding> serviceBindingList = CollectionHelper.arrayList( 20 );
private boolean autoCloseRegistry;
private Set<ServiceRegistryImplementor> childRegistries; private Set<ServiceRegistryImplementor> childRegistries;
@SuppressWarnings( {"UnusedDeclaration"}) @SuppressWarnings( {"UnusedDeclaration"})
@ -74,16 +75,35 @@ public abstract class AbstractServiceRegistryImpl
this( (ServiceRegistryImplementor) null ); this( (ServiceRegistryImplementor) null );
} }
@SuppressWarnings( {"UnusedDeclaration"})
protected AbstractServiceRegistryImpl(boolean autoCloseRegistry) {
this( (ServiceRegistryImplementor) null, autoCloseRegistry );
}
protected AbstractServiceRegistryImpl(ServiceRegistryImplementor parent) { protected AbstractServiceRegistryImpl(ServiceRegistryImplementor parent) {
this( parent, true );
}
protected AbstractServiceRegistryImpl(
ServiceRegistryImplementor parent,
boolean autoCloseRegistry) {
this.parent = parent; this.parent = parent;
this.autoCloseRegistry = autoCloseRegistry;
this.parent.registerChild( this ); this.parent.registerChild( this );
} }
public AbstractServiceRegistryImpl(BootstrapServiceRegistry bootstrapServiceRegistry) { public AbstractServiceRegistryImpl(BootstrapServiceRegistry bootstrapServiceRegistry) {
this( bootstrapServiceRegistry, true );
}
public AbstractServiceRegistryImpl(
BootstrapServiceRegistry bootstrapServiceRegistry,
boolean autoCloseRegistry) {
if ( ! ServiceRegistryImplementor.class.isInstance( bootstrapServiceRegistry ) ) { if ( ! ServiceRegistryImplementor.class.isInstance( bootstrapServiceRegistry ) ) {
throw new IllegalArgumentException( "Boot-strap registry was not " ); throw new IllegalArgumentException( "Boot-strap registry was not " );
} }
this.parent = (ServiceRegistryImplementor) bootstrapServiceRegistry; this.parent = (ServiceRegistryImplementor) bootstrapServiceRegistry;
this.autoCloseRegistry = autoCloseRegistry;
this.parent.registerChild( this ); this.parent.registerChild( this );
} }
@ -332,11 +352,19 @@ public abstract class AbstractServiceRegistryImpl
} }
childRegistries.remove( child ); childRegistries.remove( child );
if ( childRegistries.isEmpty() ) { if ( childRegistries.isEmpty() ) {
LOG.debug( if ( autoCloseRegistry ) {
"Implicitly destroying ServiceRegistry on de-registration " + LOG.debug(
"of all child ServiceRegistries" "Implicitly destroying ServiceRegistry on de-registration " +
); "of all child ServiceRegistries"
destroy(); );
destroy();
}
else {
LOG.debug(
"Skipping implicitly destroying ServiceRegistry on de-registration " +
"of all child ServiceRegistries"
);
}
} }
} }
} }

View File

@ -61,6 +61,7 @@ public class BootstrapServiceRegistryImpl
private static final LinkedHashSet<Integrator> NO_INTEGRATORS = new LinkedHashSet<Integrator>(); private static final LinkedHashSet<Integrator> NO_INTEGRATORS = new LinkedHashSet<Integrator>();
private final boolean autoCloseRegistry;
private boolean active = true; private boolean active = true;
private final ServiceBinding<ClassLoaderService> classLoaderServiceBinding; private final ServiceBinding<ClassLoaderService> classLoaderServiceBinding;
@ -71,10 +72,19 @@ public class BootstrapServiceRegistryImpl
public BootstrapServiceRegistryImpl() { public BootstrapServiceRegistryImpl() {
this( new ClassLoaderServiceImpl(), NO_INTEGRATORS ); this( new ClassLoaderServiceImpl(), NO_INTEGRATORS );
} }
public BootstrapServiceRegistryImpl( public BootstrapServiceRegistryImpl(
ClassLoaderService classLoaderService, ClassLoaderService classLoaderService,
IntegratorService integratorService) { IntegratorService integratorService) {
this( true, classLoaderService, integratorService );
}
public BootstrapServiceRegistryImpl(
boolean autoCloseRegistry,
ClassLoaderService classLoaderService,
IntegratorService integratorService) {
this.autoCloseRegistry = autoCloseRegistry;
this.classLoaderServiceBinding = new ServiceBinding<ClassLoaderService>( this.classLoaderServiceBinding = new ServiceBinding<ClassLoaderService>(
this, this,
ClassLoaderService.class, ClassLoaderService.class,
@ -92,7 +102,7 @@ public class BootstrapServiceRegistryImpl
public BootstrapServiceRegistryImpl( public BootstrapServiceRegistryImpl(
ClassLoaderService classLoaderService, ClassLoaderService classLoaderService,
LinkedHashSet<Integrator> providedIntegrators) { LinkedHashSet<Integrator> providedIntegrators) {
this( classLoaderService, new IntegratorServiceImpl( providedIntegrators, classLoaderService ) ); this( true, classLoaderService, new IntegratorServiceImpl( providedIntegrators, classLoaderService ) );
} }
@ -189,8 +199,13 @@ public class BootstrapServiceRegistryImpl
} }
childRegistries.remove( child ); childRegistries.remove( child );
if ( childRegistries.isEmpty() ) { if ( childRegistries.isEmpty() ) {
LOG.debug( "Implicitly destroying Boot-strap registry on de-registration " + "of all child ServiceRegistries" ); if ( autoCloseRegistry ) {
destroy(); LOG.debug( "Implicitly destroying Boot-strap registry on de-registration " + "of all child ServiceRegistries" );
destroy();
}
else {
LOG.debug( "Skipping implicitly destroying Boot-strap registry on de-registration " + "of all child ServiceRegistries" );
}
} }
} }

View File

@ -48,7 +48,17 @@ public class StandardServiceRegistryImpl extends AbstractServiceRegistryImpl imp
List<BasicServiceInitiator> serviceInitiators, List<BasicServiceInitiator> serviceInitiators,
List<ProvidedService> providedServices, List<ProvidedService> providedServices,
Map<?, ?> configurationValues) { Map<?, ?> configurationValues) {
super( bootstrapServiceRegistry ); this( true, bootstrapServiceRegistry, serviceInitiators, providedServices, configurationValues );
}
@SuppressWarnings( {"unchecked"})
public StandardServiceRegistryImpl(
boolean autoCloseRegistry,
BootstrapServiceRegistry bootstrapServiceRegistry,
List<BasicServiceInitiator> serviceInitiators,
List<ProvidedService> providedServices,
Map<?, ?> configurationValues) {
super( bootstrapServiceRegistry, autoCloseRegistry );
this.configurationValues = configurationValues; this.configurationValues = configurationValues;