HHH-10427 - Fix ServiceRegistry creates multiple service instances and returns uninitialized services

This commit is contained in:
Gail Badner 2016-05-31 16:46:30 -07:00 committed by Steve Ebersole
parent c1fde98aee
commit 9ecc646df2
1 changed files with 15 additions and 1 deletions

View File

@ -49,6 +49,9 @@ public abstract class AbstractServiceRegistryImpl
private final ConcurrentServiceBinding<Class,ServiceBinding> serviceBindingMap = new ConcurrentServiceBinding<Class,ServiceBinding>(); private final ConcurrentServiceBinding<Class,ServiceBinding> serviceBindingMap = new ConcurrentServiceBinding<Class,ServiceBinding>();
private ConcurrentServiceBinding<Class,Class> roleXref; private ConcurrentServiceBinding<Class,Class> roleXref;
// The services stored in initializedServiceByRole are completely initialized
// (i.e., configured, dependencies injected, and started)
private final ConcurrentServiceBinding<Class,Service> initializedServiceByRole = new ConcurrentServiceBinding<Class, Service>();
// 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
@ -179,14 +182,22 @@ public abstract class AbstractServiceRegistryImpl
@Override @Override
public <R extends Service> R getService(Class<R> serviceRole) { public <R extends Service> R getService(Class<R> serviceRole) {
// TODO: should an exception be thrown if active == false???
R service = serviceRole.cast( initializedServiceByRole.get( serviceRole ) );
if ( service != null ) {
return service;
}
final ServiceBinding<R> serviceBinding = locateServiceBinding( serviceRole ); final ServiceBinding<R> serviceBinding = locateServiceBinding( serviceRole );
if ( serviceBinding == null ) { if ( serviceBinding == null ) {
throw new UnknownServiceException( serviceRole ); throw new UnknownServiceException( serviceRole );
} }
synchronized (this) { synchronized (this) {
R service = serviceBinding.getService(); service = serviceBinding.getService();
if ( service == null ) { if ( service == null ) {
service = initializeService( serviceBinding ); service = initializeService( serviceBinding );
// add the service only after it is completely initialized
initializedServiceByRole.put( serviceRole, service );
} }
return service; return service;
@ -347,6 +358,7 @@ public abstract class AbstractServiceRegistryImpl
serviceBindingList.clear(); serviceBindingList.clear();
} }
serviceBindingMap.clear(); serviceBindingMap.clear();
initializedServiceByRole.clear();
} }
finally { finally {
parent.deRegisterChild( this ); parent.deRegisterChild( this );
@ -356,6 +368,8 @@ public abstract class AbstractServiceRegistryImpl
@Override @Override
public <R extends Service> void stopService(ServiceBinding<R> binding) { public <R extends Service> void stopService(ServiceBinding<R> binding) {
final Service service = binding.getService(); final Service service = binding.getService();
// TODO: it would be nice to remove service from initializedServiceByRole,
// but ConcurrentServiceBinding does not allow removing an entry.
if ( Stoppable.class.isInstance( service ) ) { if ( Stoppable.class.isInstance( service ) ) {
try { try {
( (Stoppable) service ).stop(); ( (Stoppable) service ).stop();