HHH-6796 - Services retrieved after SessionFactoryServiceRegistry has started are not configured (Configurable)
This commit is contained in:
parent
4739c5dc0c
commit
3c3482bd59
|
@ -51,15 +51,20 @@ import org.hibernate.service.spi.Stoppable;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImplementor, ServiceBinding.OwningRegistry {
|
public abstract class AbstractServiceRegistryImpl
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, AbstractServiceRegistryImpl.class.getName() );
|
implements ServiceRegistryImplementor, ServiceBinding.ServiceLifecycleOwner {
|
||||||
|
|
||||||
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
CoreMessageLogger.class,
|
||||||
|
AbstractServiceRegistryImpl.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
private final ServiceRegistryImplementor parent;
|
private final ServiceRegistryImplementor parent;
|
||||||
|
|
||||||
private ConcurrentHashMap<Class,ServiceBinding> serviceBindingMap;
|
private ConcurrentHashMap<Class,ServiceBinding> serviceBindingMap;
|
||||||
// IMPL NOTE : the list used for ordered destruction. Cannot used map above because we need to
|
// 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
|
// 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"})
|
@SuppressWarnings( {"UnusedDeclaration"})
|
||||||
protected AbstractServiceRegistryImpl() {
|
protected AbstractServiceRegistryImpl() {
|
||||||
|
@ -75,7 +80,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
private void prepare() {
|
private void prepare() {
|
||||||
// assume 20 services for initial sizing
|
// assume 20 services for initial sizing
|
||||||
this.serviceBindingMap = CollectionHelper.concurrentMap( 20 );
|
this.serviceBindingMap = CollectionHelper.concurrentMap( 20 );
|
||||||
this.serviceList = CollectionHelper.arrayList( 20 );
|
this.serviceBindingList = CollectionHelper.arrayList( 20 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractServiceRegistryImpl(BootstrapServiceRegistry bootstrapServiceRegistry) {
|
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) {
|
protected <R extends Service> void registerService(ServiceBinding<R> serviceBinding, R service) {
|
||||||
R priorServiceInstance = serviceBinding.getService();
|
|
||||||
serviceBinding.setService( service );
|
serviceBinding.setService( service );
|
||||||
if ( priorServiceInstance != null ) {
|
serviceBindingList.add( serviceBinding );
|
||||||
serviceList.remove( priorServiceInstance );
|
|
||||||
}
|
|
||||||
serviceList.add( service );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R extends Service> R initializeService(ServiceBinding<R> 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***)
|
// PHASE 2 : inject service (***potentially recursive***)
|
||||||
injectService( service );
|
serviceBinding.getLifecycleOwner().injectDependencies( serviceBinding );
|
||||||
|
|
||||||
// PHASE 3 : configure service
|
// PHASE 3 : configure service
|
||||||
serviceBinding.getServiceRegistry().configureService( service );
|
serviceBinding.getLifecycleOwner().configureService( serviceBinding );
|
||||||
|
|
||||||
// PHASE 4 : Start service
|
// PHASE 4 : Start service
|
||||||
|
serviceBinding.getLifecycleOwner().startService( serviceBinding );
|
||||||
startService( serviceBinding );
|
startService( serviceBinding );
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T extends Service> void injectService(T service) {
|
|
||||||
applyInjections( service );
|
|
||||||
|
|
||||||
if ( ServiceRegistryAwareService.class.isInstance( service ) ) {
|
|
||||||
( (ServiceRegistryAwareService) service ).injectServices( this );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings( {"unchecked"})
|
@SuppressWarnings( {"unchecked"})
|
||||||
protected <R extends Service> R createService(ServiceBinding<R> serviceBinding) {
|
protected <R extends Service> R createService(ServiceBinding<R> serviceBinding) {
|
||||||
final ServiceInitiator<R> serviceInitiator = serviceBinding.getServiceInitiator();
|
final ServiceInitiator<R> serviceInitiator = serviceBinding.getServiceInitiator();
|
||||||
|
@ -186,7 +180,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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
|
// IMPL NOTE : the register call here is important to avoid potential stack overflow issues
|
||||||
// from recursive calls through #configureService
|
// from recursive calls through #configureService
|
||||||
registerService( serviceBinding, service );
|
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 {
|
try {
|
||||||
for ( Method method : service.getClass().getMethods() ) {
|
for ( Method method : service.getClass().getMethods() ) {
|
||||||
InjectService injectService = method.getAnnotation( InjectService.class );
|
InjectService injectService = method.getAnnotation( InjectService.class );
|
||||||
|
@ -208,7 +213,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyInjection( service, method, injectService );
|
processInjection( service, method, injectService );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NullPointerException e) {
|
catch (NullPointerException e) {
|
||||||
|
@ -217,7 +222,7 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked" })
|
@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 ) {
|
if ( injectionMethod.getParameterTypes() == null || injectionMethod.getParameterTypes().length != 1 ) {
|
||||||
throw new ServiceDependencyException(
|
throw new ServiceDependencyException(
|
||||||
"Encountered @InjectService on method with unexpected number of parameters"
|
"Encountered @InjectService on method with unexpected number of parameters"
|
||||||
|
@ -249,8 +254,9 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings({ "unchecked" })
|
@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() ) ) {
|
if ( Startable.class.isInstance( serviceBinding.getService() ) ) {
|
||||||
( (Startable) serviceBinding.getService() ).start();
|
( (Startable) serviceBinding.getService() ).start();
|
||||||
}
|
}
|
||||||
|
@ -262,11 +268,24 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings( {"unchecked"})
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
ListIterator<Service> serviceIterator = serviceList.listIterator( serviceList.size() );
|
ListIterator<ServiceBinding> serviceBindingsIterator = serviceBindingList.listIterator( serviceBindingList.size() );
|
||||||
while ( serviceIterator.hasPrevious() ) {
|
while ( serviceBindingsIterator.hasPrevious() ) {
|
||||||
final Service service = serviceIterator.previous();
|
final ServiceBinding serviceBinding = serviceBindingsIterator.previous();
|
||||||
|
serviceBinding.getLifecycleOwner().stopService( serviceBinding );
|
||||||
|
}
|
||||||
|
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 ) ) {
|
if ( Stoppable.class.isInstance( service ) ) {
|
||||||
try {
|
try {
|
||||||
( (Stoppable) service ).stop();
|
( (Stoppable) service ).stop();
|
||||||
|
@ -276,10 +295,4 @@ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serviceList.clear();
|
|
||||||
serviceList = null;
|
|
||||||
serviceBindingMap.clear();
|
|
||||||
serviceBindingMap = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class BootstrapServiceRegistryImpl
|
public class BootstrapServiceRegistryImpl
|
||||||
implements ServiceRegistryImplementor, BootstrapServiceRegistry, ServiceBinding.OwningRegistry {
|
implements ServiceRegistryImplementor, BootstrapServiceRegistry, ServiceBinding.ServiceLifecycleOwner {
|
||||||
private static final LinkedHashSet<Integrator> NO_INTEGRATORS = new LinkedHashSet<Integrator>();
|
private static final LinkedHashSet<Integrator> NO_INTEGRATORS = new LinkedHashSet<Integrator>();
|
||||||
|
|
||||||
private final ServiceBinding<ClassLoaderService> classLoaderServiceBinding;
|
private final ServiceBinding<ClassLoaderService> classLoaderServiceBinding;
|
||||||
|
@ -112,13 +112,27 @@ public class BootstrapServiceRegistryImpl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R extends Service> R initiateService(ServiceInitiator<R> serviceInitiator) {
|
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 provided services" );
|
||||||
throw new ServiceException( "Boot-strap registry should only contain directly built services" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R extends Service> void configureService(R service) {
|
public <R extends Service> void configureService(ServiceBinding<R> binding) {
|
||||||
//nothing do to for bootstrap style services
|
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" );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.metamodel.source.MetadataImplementor;
|
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||||
import org.hibernate.service.Service;
|
import org.hibernate.service.Service;
|
||||||
|
import org.hibernate.service.spi.ServiceBinding;
|
||||||
import org.hibernate.service.spi.ServiceInitiator;
|
import org.hibernate.service.spi.ServiceInitiator;
|
||||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||||
|
@ -96,7 +96,7 @@ public class SessionFactoryServiceRegistryImpl extends AbstractServiceRegistryIm
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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?
|
//TODO nothing to do here or should we inject SessionFactory properties?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ import org.hibernate.service.Service;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.service.spi.BasicServiceInitiator;
|
import org.hibernate.service.spi.BasicServiceInitiator;
|
||||||
import org.hibernate.service.spi.Configurable;
|
import org.hibernate.service.spi.Configurable;
|
||||||
|
import org.hibernate.service.spi.ServiceBinding;
|
||||||
import org.hibernate.service.spi.ServiceInitiator;
|
import org.hibernate.service.spi.ServiceInitiator;
|
||||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hibernate implementation of the standard service registry.
|
* Hibernate implementation of the standard service registry.
|
||||||
|
@ -70,9 +70,9 @@ public class StandardServiceRegistryImpl extends AbstractServiceRegistryImpl imp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Service> void configureService(T service) {
|
public <R extends Service> void configureService(ServiceBinding<R> serviceBinding) {
|
||||||
if ( Configurable.class.isInstance( service ) ) {
|
if ( Configurable.class.isInstance( serviceBinding.getService() ) ) {
|
||||||
( (Configurable) service ).configure( configurationValues );
|
( (Configurable) serviceBinding.getService() ).configure( configurationValues );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,31 +35,36 @@ import org.hibernate.service.Service;
|
||||||
public final class ServiceBinding<R extends Service> {
|
public final class ServiceBinding<R extends Service> {
|
||||||
private static final Logger log = Logger.getLogger( ServiceBinding.class );
|
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> 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 Class<R> serviceRole;
|
||||||
private final ServiceInitiator<R> serviceInitiator;
|
private final ServiceInitiator<R> serviceInitiator;
|
||||||
private R service;
|
private R service;
|
||||||
|
|
||||||
public ServiceBinding(OwningRegistry serviceRegistry, Class<R> serviceRole, R service) {
|
public ServiceBinding(ServiceLifecycleOwner lifecycleOwner, Class<R> serviceRole, R service) {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.lifecycleOwner = lifecycleOwner;
|
||||||
this.serviceRole = serviceRole;
|
this.serviceRole = serviceRole;
|
||||||
this.serviceInitiator = null;
|
this.serviceInitiator = null;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceBinding(OwningRegistry serviceRegistry, ServiceInitiator<R> serviceInitiator) {
|
public ServiceBinding(ServiceLifecycleOwner lifecycleOwner, ServiceInitiator<R> serviceInitiator) {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.lifecycleOwner = lifecycleOwner;
|
||||||
this.serviceRole = serviceInitiator.getServiceInitiated();
|
this.serviceRole = serviceInitiator.getServiceInitiated();
|
||||||
this.serviceInitiator = serviceInitiator;
|
this.serviceInitiator = serviceInitiator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OwningRegistry getServiceRegistry() {
|
public ServiceLifecycleOwner getLifecycleOwner() {
|
||||||
return serviceRegistry;
|
return lifecycleOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<R> getServiceRole() {
|
public Class<R> getServiceRole() {
|
||||||
|
|
Loading…
Reference in New Issue