HHH-6796 - Services retrieved after SessionFactoryServiceRegistry has started are not configured (Configurable)

This commit is contained in:
Steve Ebersole 2011-11-03 12:10:30 -05:00
parent 4739c5dc0c
commit 3c3482bd59
5 changed files with 90 additions and 58 deletions

View File

@ -51,15 +51,20 @@ import org.hibernate.service.spi.Stoppable;
/**
* @author Steve Ebersole
*/
public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImplementor, ServiceBinding.OwningRegistry {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, AbstractServiceRegistryImpl.class.getName() );
public abstract class AbstractServiceRegistryImpl
implements ServiceRegistryImplementor, ServiceBinding.ServiceLifecycleOwner {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
AbstractServiceRegistryImpl.class.getName()
);
private final ServiceRegistryImplementor parent;
private ConcurrentHashMap<Class,ServiceBinding> serviceBindingMap;
// IMPL NOTE : the list used for ordered destruction. Cannot used map above because we need to
// iterate it in reverse order which is only available through ListIterator
private List<Service> serviceList = new ArrayList<Service>();
private List<ServiceBinding> serviceBindingList = new ArrayList<ServiceBinding>();
@SuppressWarnings( {"UnusedDeclaration"})
protected AbstractServiceRegistryImpl() {
@ -75,7 +80,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
private void prepare() {
// assume 20 services for initial sizing
this.serviceBindingMap = CollectionHelper.concurrentMap( 20 );
this.serviceList = CollectionHelper.arrayList( 20 );
this.serviceBindingList = CollectionHelper.arrayList( 20 );
}
public AbstractServiceRegistryImpl(BootstrapServiceRegistry bootstrapServiceRegistry) {
@ -138,12 +143,8 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
}
protected <R extends Service> void registerService(ServiceBinding<R> serviceBinding, R service) {
R priorServiceInstance = serviceBinding.getService();
serviceBinding.setService( service );
if ( priorServiceInstance != null ) {
serviceList.remove( priorServiceInstance );
}
serviceList.add( service );
serviceBindingList.add( serviceBinding );
}
private <R extends Service> R initializeService(ServiceBinding<R> serviceBinding) {
@ -158,25 +159,18 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
}
// PHASE 2 : inject service (***potentially recursive***)
injectService( service );
serviceBinding.getLifecycleOwner().injectDependencies( serviceBinding );
// PHASE 3 : configure service
serviceBinding.getServiceRegistry().configureService( service );
serviceBinding.getLifecycleOwner().configureService( serviceBinding );
// PHASE 4 : Start service
serviceBinding.getLifecycleOwner().startService( serviceBinding );
startService( serviceBinding );
return service;
}
protected <T extends Service> void injectService(T service) {
applyInjections( service );
if ( ServiceRegistryAwareService.class.isInstance( service ) ) {
( (ServiceRegistryAwareService) service ).injectServices( this );
}
}
@SuppressWarnings( {"unchecked"})
protected <R extends Service> R createService(ServiceBinding<R> serviceBinding) {
final ServiceInitiator<R> serviceInitiator = serviceBinding.getServiceInitiator();
@ -186,7 +180,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
}
try {
R service = serviceBinding.getServiceRegistry().initiateService( serviceInitiator );
R service = serviceBinding.getLifecycleOwner().initiateService( serviceInitiator );
// IMPL NOTE : the register call here is important to avoid potential stack overflow issues
// from recursive calls through #configureService
registerService( serviceBinding, service );
@ -200,7 +194,18 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
}
}
protected <T extends Service> void applyInjections(T service) {
@Override
public <R extends Service> void injectDependencies(ServiceBinding<R> serviceBinding) {
final R service = serviceBinding.getService();
applyInjections( service );
if ( ServiceRegistryAwareService.class.isInstance( service ) ) {
( (ServiceRegistryAwareService) service ).injectServices( this );
}
}
private <R extends Service> void applyInjections(R service) {
try {
for ( Method method : service.getClass().getMethods() ) {
InjectService injectService = method.getAnnotation( InjectService.class );
@ -208,7 +213,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
continue;
}
applyInjection( service, method, injectService );
processInjection( service, method, injectService );
}
}
catch (NullPointerException e) {
@ -217,7 +222,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
}
@SuppressWarnings({ "unchecked" })
private <T extends Service> void applyInjection(T service, Method injectionMethod, InjectService injectService) {
private <T extends Service> void processInjection(T service, Method injectionMethod, InjectService injectService) {
if ( injectionMethod.getParameterTypes() == null || injectionMethod.getParameterTypes().length != 1 ) {
throw new ServiceDependencyException(
"Encountered @InjectService on method with unexpected number of parameters"
@ -249,8 +254,9 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
}
}
@Override
@SuppressWarnings({ "unchecked" })
protected <R extends Service> void startService(ServiceBinding<R> serviceBinding) {
public <R extends Service> void startService(ServiceBinding<R> serviceBinding) {
if ( Startable.class.isInstance( serviceBinding.getService() ) ) {
( (Startable) serviceBinding.getService() ).start();
}
@ -262,24 +268,31 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
);
}
}
@Override
@Override
@SuppressWarnings( {"unchecked"})
public void destroy() {
ListIterator<Service> serviceIterator = serviceList.listIterator( serviceList.size() );
while ( serviceIterator.hasPrevious() ) {
final Service service = serviceIterator.previous();
if ( Stoppable.class.isInstance( service ) ) {
try {
( (Stoppable) service ).stop();
}
catch ( Exception e ) {
LOG.unableToStopService( service.getClass(), e.toString() );
}
}
ListIterator<ServiceBinding> serviceBindingsIterator = serviceBindingList.listIterator( serviceBindingList.size() );
while ( serviceBindingsIterator.hasPrevious() ) {
final ServiceBinding serviceBinding = serviceBindingsIterator.previous();
serviceBinding.getLifecycleOwner().stopService( serviceBinding );
}
serviceList.clear();
serviceList = null;
serviceBindingList.clear();
serviceBindingList = null;
serviceBindingMap.clear();
serviceBindingMap = null;
}
@Override
public <R extends Service> void stopService(ServiceBinding<R> binding) {
final Service service = binding.getService();
if ( Stoppable.class.isInstance( service ) ) {
try {
( (Stoppable) service ).stop();
}
catch ( Exception e ) {
LOG.unableToStopService( service.getClass(), e.toString() );
}
}
}
}

View File

@ -47,7 +47,7 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
* @author Steve Ebersole
*/
public class BootstrapServiceRegistryImpl
implements ServiceRegistryImplementor, BootstrapServiceRegistry, ServiceBinding.OwningRegistry {
implements ServiceRegistryImplementor, BootstrapServiceRegistry, ServiceBinding.ServiceLifecycleOwner {
private static final LinkedHashSet<Integrator> NO_INTEGRATORS = new LinkedHashSet<Integrator>();
private final ServiceBinding<ClassLoaderService> classLoaderServiceBinding;
@ -112,13 +112,27 @@ public class BootstrapServiceRegistryImpl
@Override
public <R extends Service> R initiateService(ServiceInitiator<R> serviceInitiator) {
// the bootstrap registry should currently be made up of only directly built services.
throw new ServiceException( "Boot-strap registry should only contain directly built services" );
throw new ServiceException( "Boot-strap registry should only contain provided services" );
}
@Override
public <R extends Service> void configureService(R service) {
//nothing do to for bootstrap style services
public <R extends Service> void configureService(ServiceBinding<R> binding) {
throw new ServiceException( "Boot-strap registry should only contain provided services" );
}
@Override
public <R extends Service> void injectDependencies(ServiceBinding<R> binding) {
throw new ServiceException( "Boot-strap registry should only contain provided services" );
}
@Override
public <R extends Service> void startService(ServiceBinding<R> binding) {
throw new ServiceException( "Boot-strap registry should only contain provided services" );
}
@Override
public <R extends Service> void stopService(ServiceBinding<R> binding) {
throw new ServiceException( "Boot-strap registry should only contain provided services" );
}
}

View File

@ -27,8 +27,8 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.service.Service;
import org.hibernate.service.spi.ServiceBinding;
import org.hibernate.service.spi.ServiceInitiator;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
@ -96,7 +96,7 @@ public class SessionFactoryServiceRegistryImpl extends AbstractServiceRegistryIm
}
@Override
public <T extends Service> void configureService(T service) {
public <R extends Service> void configureService(ServiceBinding<R> serviceBinding) {
//TODO nothing to do here or should we inject SessionFactory properties?
}
}

View File

@ -31,8 +31,8 @@ import org.hibernate.service.Service;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.BasicServiceInitiator;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceBinding;
import org.hibernate.service.spi.ServiceInitiator;
import org.hibernate.service.spi.ServiceRegistryAwareService;
/**
* Hibernate implementation of the standard service registry.
@ -70,9 +70,9 @@ public class StandardServiceRegistryImpl extends AbstractServiceRegistryImpl imp
}
@Override
public <T extends Service> void configureService(T service) {
if ( Configurable.class.isInstance( service ) ) {
( (Configurable) service ).configure( configurationValues );
public <R extends Service> void configureService(ServiceBinding<R> serviceBinding) {
if ( Configurable.class.isInstance( serviceBinding.getService() ) ) {
( (Configurable) serviceBinding.getService() ).configure( configurationValues );
}
}

View File

@ -35,31 +35,36 @@ import org.hibernate.service.Service;
public final class ServiceBinding<R extends Service> {
private static final Logger log = Logger.getLogger( ServiceBinding.class );
public static interface OwningRegistry {
public static interface ServiceLifecycleOwner {
public <R extends Service> R initiateService(ServiceInitiator<R> serviceInitiator);
public <R extends Service> void configureService(R service);
public <R extends Service> void configureService(ServiceBinding<R> binding);
public <R extends Service> void injectDependencies(ServiceBinding<R> binding);
public <R extends Service> void startService(ServiceBinding<R> binding);
public <R extends Service> void stopService(ServiceBinding<R> binding);
}
private final OwningRegistry serviceRegistry;
private final ServiceLifecycleOwner lifecycleOwner;
private final Class<R> serviceRole;
private final ServiceInitiator<R> serviceInitiator;
private R service;
public ServiceBinding(OwningRegistry serviceRegistry, Class<R> serviceRole, R service) {
this.serviceRegistry = serviceRegistry;
public ServiceBinding(ServiceLifecycleOwner lifecycleOwner, Class<R> serviceRole, R service) {
this.lifecycleOwner = lifecycleOwner;
this.serviceRole = serviceRole;
this.serviceInitiator = null;
this.service = service;
}
public ServiceBinding(OwningRegistry serviceRegistry, ServiceInitiator<R> serviceInitiator) {
this.serviceRegistry = serviceRegistry;
public ServiceBinding(ServiceLifecycleOwner lifecycleOwner, ServiceInitiator<R> serviceInitiator) {
this.lifecycleOwner = lifecycleOwner;
this.serviceRole = serviceInitiator.getServiceInitiated();
this.serviceInitiator = serviceInitiator;
}
public OwningRegistry getServiceRegistry() {
return serviceRegistry;
public ServiceLifecycleOwner getLifecycleOwner() {
return lifecycleOwner;
}
public Class<R> getServiceRole() {