From 9ecc646df2128de0143b235c855a74f3c986dc84 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Tue, 31 May 2016 16:46:30 -0700 Subject: [PATCH] HHH-10427 - Fix ServiceRegistry creates multiple service instances and returns uninitialized services --- .../internal/AbstractServiceRegistryImpl.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java index 2cb7cd0387..c896731a43 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java @@ -49,6 +49,9 @@ public abstract class AbstractServiceRegistryImpl private final ConcurrentServiceBinding serviceBindingMap = new ConcurrentServiceBinding(); private ConcurrentServiceBinding roleXref; + // The services stored in initializedServiceByRole are completely initialized + // (i.e., configured, dependencies injected, and started) + private final ConcurrentServiceBinding initializedServiceByRole = new ConcurrentServiceBinding(); // 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 @@ -179,14 +182,22 @@ public abstract class AbstractServiceRegistryImpl @Override public R getService(Class serviceRole) { + // TODO: should an exception be thrown if active == false??? + R service = serviceRole.cast( initializedServiceByRole.get( serviceRole ) ); + if ( service != null ) { + return service; + } + final ServiceBinding serviceBinding = locateServiceBinding( serviceRole ); if ( serviceBinding == null ) { throw new UnknownServiceException( serviceRole ); } synchronized (this) { - R service = serviceBinding.getService(); + service = serviceBinding.getService(); if ( service == null ) { service = initializeService( serviceBinding ); + // add the service only after it is completely initialized + initializedServiceByRole.put( serviceRole, service ); } return service; @@ -347,6 +358,7 @@ public abstract class AbstractServiceRegistryImpl serviceBindingList.clear(); } serviceBindingMap.clear(); + initializedServiceByRole.clear(); } finally { parent.deRegisterChild( this ); @@ -356,6 +368,8 @@ public abstract class AbstractServiceRegistryImpl @Override public void stopService(ServiceBinding binding) { 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 ) ) { try { ( (Stoppable) service ).stop();