diff --git a/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java index fedc863b18..abd77f22c3 100644 --- a/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java @@ -99,7 +99,6 @@ import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.query.QueryPlanCache; import org.hibernate.engine.query.sql.NativeSQLQuerySpecification; import org.hibernate.engine.transaction.spi.TransactionEnvironment; -import org.hibernate.event.EventListeners; import org.hibernate.exception.SQLExceptionConverter; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.UUIDGenerator; @@ -183,7 +182,7 @@ public final class SessionFactoryImpl private final transient Map fetchProfiles; private final transient Map imports; private final transient Interceptor interceptor; - private final transient ServiceRegistryImplementor serviceRegistry; + private final transient SessionFactoryServiceRegistry serviceRegistry; private final transient Settings settings; private final transient Properties properties; private transient SchemaExport schemaExport; diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java index 446a2a71ae..b3aec976e4 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryFactoryImpl.java @@ -23,10 +23,13 @@ */ package org.hibernate.service.internal; +import java.util.List; + import org.hibernate.cfg.Configuration; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.service.Service; import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.SessionFactoryServiceInitiator; import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; /** diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java index 50c3a99286..73283d55d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/SessionFactoryServiceRegistryImpl.java @@ -23,10 +23,23 @@ */ package org.hibernate.service.internal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.HibernateLogger; import org.hibernate.cfg.Configuration; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.service.Service; +import org.hibernate.service.StandardSessionFactoryServiceInitiators; +import org.hibernate.service.UnknownServiceException; +import org.hibernate.service.spi.BasicServiceInitiator; +import org.hibernate.service.spi.ServiceException; +import org.hibernate.service.spi.ServiceRegistryAwareService; import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.SessionFactoryServiceInitiator; import org.hibernate.service.spi.SessionFactoryServiceRegistry; /** @@ -36,27 +49,84 @@ public class SessionFactoryServiceRegistryImpl extends AbstractServiceRegistryImpl implements SessionFactoryServiceRegistry { - private final SessionFactoryImplementor sessionFactory; - private Configuration configuration; + private static final HibernateLogger LOG = Logger.getMessageLogger( HibernateLogger.class, SessionFactoryServiceRegistryImpl.class.getName() ); + + private final Map serviceInitiatorMap; // for now we need to hold on to the Configuration... :( + private Configuration configuration; + private final SessionFactoryImplementor sessionFactory; + @SuppressWarnings( {"unchecked"}) public SessionFactoryServiceRegistryImpl( ServiceRegistryImplementor parent, SessionFactoryImplementor sessionFactory, Configuration configuration) { super( parent ); + // for now, just use the standard initiator list + this.serviceInitiatorMap = toMap( StandardSessionFactoryServiceInitiators.LIST ); + this.sessionFactory = sessionFactory; this.configuration = configuration; + + for ( SessionFactoryServiceInitiator initiator : serviceInitiatorMap.values() ) { + // create the bindings up front to help identify to which registry services belong + createServiceBinding( initiator.getServiceInitiated() ); + } + } + + private static Map toMap(List serviceInitiators) { + final Map result = new HashMap(); + for ( SessionFactoryServiceInitiator initiator : serviceInitiators ) { + result.put( initiator.getServiceInitiated(), initiator ); + } + return result; } @Override + @SuppressWarnings( {"unchecked"}) + public void registerServiceInitiator(SessionFactoryServiceInitiator initiator) { + ServiceBinding serviceBinding = locateServiceBinding( initiator.getServiceInitiated(), false ); + if ( serviceBinding != null ) { + serviceBinding.setTarget( null ); + } + else { + createServiceBinding( initiator.getServiceInitiated() ); + } + final Object previous = serviceInitiatorMap.put( initiator.getServiceInitiated(), initiator ); + if ( previous != null ) { + LOG.debugf( "Over-wrote existing service initiator [role=%s]", initiator.getServiceInitiated().getName() ); + } + } + + @Override + @SuppressWarnings({ "unchecked" }) protected T createService(Class serviceRole) { - return null; // todo : implement method body + SessionFactoryServiceInitiator initiator = serviceInitiatorMap.get( serviceRole ); + if ( initiator == null ) { + throw new UnknownServiceException( serviceRole ); + } + try { + T service = initiator.initiateService( sessionFactory, configuration, this ); + // IMPL NOTE : the register call here is important to avoid potential stack overflow issues + // from recursive calls through #configureService + registerService( serviceRole, service ); + return service; + } + catch ( ServiceException e ) { + throw e; + } + catch ( Exception e ) { + throw new ServiceException( "Unable to create requested service [" + serviceRole.getName() + "]", e ); + } } @Override protected void configureService(T service) { - // todo : implement method body + applyInjections( service ); + + if ( ServiceRegistryAwareService.class.isInstance( service ) ) { + ( (ServiceRegistryAwareService) service ).injectServices( this ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistry.java b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistry.java index 78e2fbb00f..32ebfe2dd1 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistry.java @@ -30,5 +30,5 @@ package org.hibernate.service.spi; * @author Steve Ebersole */ public interface SessionFactoryServiceRegistry extends ServiceRegistryImplementor { - // todo : add regsitration of service initiator + public void registerServiceInitiator(SessionFactoryServiceInitiator initiator); } diff --git a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java index 8d5106ee5d..121bd487cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/service/spi/SessionFactoryServiceRegistryFactory.java @@ -23,6 +23,8 @@ */ package org.hibernate.service.spi; +import java.util.List; + import org.hibernate.cfg.Configuration; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.service.Service; diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java index 2cbae5d96d..47cf0a92f9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/events/CallbackTest.java @@ -22,6 +22,7 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.test.events; +import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; @@ -31,8 +32,10 @@ import org.hibernate.cfg.Configuration; import org.hibernate.event.DeleteEvent; import org.hibernate.event.DeleteEventListener; import org.hibernate.event.Destructible; +import org.hibernate.event.EventListenerRegistration; import org.hibernate.event.EventType; import org.hibernate.event.Initializable; +import org.hibernate.service.StandardServiceInitiators; import org.hibernate.service.event.spi.EventListenerRegistry; import org.hibernate.service.internal.BasicServiceRegistryImpl; import org.hibernate.service.spi.ServiceRegistryImplementor; @@ -65,7 +68,17 @@ public class CallbackTest extends BaseCoreFunctionalTestCase { @Override protected void applyServices(BasicServiceRegistryImpl serviceRegistry) { super.applyServices( serviceRegistry ); - serviceRegistry.getService( EventListenerRegistry.class ).setListeners( EventType.DELETE, listener ); + serviceRegistry.getService( StandardServiceInitiators.EventListenerRegistrationService.class ).attachEventListenerRegistration( + new EventListenerRegistration() { + @Override + public void apply( + ServiceRegistryImplementor serviceRegistry, + Configuration configuration, + Map configValues) { + serviceRegistry.getService( EventListenerRegistry.class ).setListeners( EventType.DELETE, listener ); + } + } + ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java b/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java index d06544e1a6..c861279a7f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/jpa/AbstractJPATest.java @@ -25,11 +25,13 @@ package org.hibernate.test.jpa; import javax.persistence.EntityNotFoundException; import java.io.Serializable; +import java.util.Map; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.engine.CascadingAction; import org.hibernate.event.AutoFlushEventListener; +import org.hibernate.event.EventListenerRegistration; import org.hibernate.event.EventType; import org.hibernate.event.FlushEntityEventListener; import org.hibernate.event.FlushEventListener; @@ -40,8 +42,10 @@ import org.hibernate.event.def.DefaultFlushEventListener; import org.hibernate.event.def.DefaultPersistEventListener; import org.hibernate.internal.util.collections.IdentityMap; import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.service.StandardServiceInitiators; import org.hibernate.service.event.spi.EventListenerRegistry; import org.hibernate.service.internal.BasicServiceRegistryImpl; +import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -67,13 +71,22 @@ public abstract class AbstractJPATest extends BaseCoreFunctionalTestCase { @Override protected void applyServices(BasicServiceRegistryImpl serviceRegistry) { super.applyServices( serviceRegistry ); - - EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); - eventListenerRegistry.setListeners( EventType.PERSIST, buildPersistEventListeners() ); - eventListenerRegistry.setListeners( EventType.PERSIST_ONFLUSH, buildPersisOnFlushEventListeners() ); - eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, buildAutoFlushEventListeners() ); - eventListenerRegistry.setListeners( EventType.FLUSH, buildFlushEventListeners() ); - eventListenerRegistry.setListeners( EventType.FLUSH_ENTITY, buildFlushEntityEventListeners() ); + serviceRegistry.getService( StandardServiceInitiators.EventListenerRegistrationService.class ).attachEventListenerRegistration( + new EventListenerRegistration() { + @Override + public void apply( + ServiceRegistryImplementor serviceRegistry, + Configuration configuration, + Map configValues) { + EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); + eventListenerRegistry.setListeners( EventType.PERSIST, buildPersistEventListeners() ); + eventListenerRegistry.setListeners( EventType.PERSIST_ONFLUSH, buildPersisOnFlushEventListeners() ); + eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, buildAutoFlushEventListeners() ); + eventListenerRegistry.setListeners( EventType.FLUSH, buildFlushEventListeners() ); + eventListenerRegistry.setListeners( EventType.FLUSH_ENTITY, buildFlushEntityEventListeners() ); + } + } + ); } @Override