From ac49051add5d1f95bdbeb02dfe1ce40d4d09e6e0 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Tue, 3 Nov 2015 14:30:27 -0800 Subject: [PATCH] HHH-10202 : Delay resolving TypeScopeImpl#factory after deserialization until resolveFactory() is called. --- .../internal/SessionFactoryImpl.java | 32 ++++++----- .../java/org/hibernate/type/TypeFactory.java | 35 +++++++----- .../TypeFactorySerializationTest.java | 55 ++++++++++++++----- 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 6c54d722c6..f497f22a17 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -271,6 +271,15 @@ public final class SessionFactoryImpl this.observer.addObserver( observer ); } + // name and uuid must be initialized before scoping the TypeResolver to this object. + name = settings.getSessionFactoryName(); + try { + uuid = (String) UUID_GENERATOR.generate(null, null); + } + catch (Exception e) { + throw new AssertionFailure("Could not generate UUID"); + } + this.typeResolver = cfg.getTypeResolver().scope( this ); this.typeHelper = new TypeLocatorImpl( typeResolver ); @@ -474,13 +483,6 @@ public final class SessionFactoryImpl //JNDI + Serialization: - name = settings.getSessionFactoryName(); - try { - uuid = (String) UUID_GENERATOR.generate(null, null); - } - catch (Exception e) { - throw new AssertionFailure("Could not generate UUID"); - } SessionFactoryRegistry.INSTANCE.addSessionFactory( uuid, name, @@ -693,6 +695,15 @@ public final class SessionFactoryImpl this.observer.addObserver( observer ); } + // name and uuid must be initialized before scoping the TypeResolver to this object. + name = settings.getSessionFactoryName(); + try { + uuid = (String) UUID_GENERATOR.generate(null, null); + } + catch (Exception e) { + throw new AssertionFailure("Could not generate UUID"); + } + this.typeResolver = metadata.getTypeResolver().scope( this ); this.typeHelper = new TypeLocatorImpl( typeResolver ); @@ -883,13 +894,6 @@ public final class SessionFactoryImpl //JNDI + Serialization: - name = settings.getSessionFactoryName(); - try { - uuid = (String) UUID_GENERATOR.generate(null, null); - } - catch (Exception e) { - throw new AssertionFailure("Could not generate UUID"); - } SessionFactoryRegistry.INSTANCE.addSessionFactory( uuid, name, diff --git a/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java b/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java index ba25bf2938..d7f288e4ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/type/TypeFactory.java @@ -27,14 +27,16 @@ import java.io.Serializable; import java.util.Comparator; import java.util.Properties; +import javax.naming.NamingException; + import org.hibernate.HibernateException; import org.hibernate.MappingException; -import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService; import org.hibernate.classic.Lifecycle; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.SessionFactoryRegistry; import org.hibernate.internal.util.ReflectHelper; +import org.hibernate.internal.util.StringHelper; import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.ParameterizedType; @@ -73,26 +75,33 @@ public final class TypeFactory implements Serializable { } else { LOG.tracev( "Scoping types to session factory {0}", factory ); - sessionFactoryUuid = factory.getUuid(); - String sfName = factory.getSettings().getSessionFactoryName(); - if ( sfName == null ) { - final CfgXmlAccessService cfgXmlAccessService = factory.getServiceRegistry() - .getService( CfgXmlAccessService.class ); - if ( cfgXmlAccessService.getAggregatedConfig() != null ) { - sfName = cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName(); - } + try { + sessionFactoryUuid = (String) factory.getReference().get( "uuid" ).getContent() ; } - sessionFactoryName = sfName; + catch (NamingException ex) { + throw new HibernateException( + "Could not inject SessionFactory because UUID could not be determined.", + ex + ); + } + if ( sessionFactoryUuid == null ) { + throw new IllegalArgumentException( "SessionFactory has null uuid." ); + } + sessionFactoryName = factory.getSettings().getSessionFactoryName(); } this.factory = factory; } public SessionFactoryImplementor resolveFactory() { if ( factory == null ) { - factory = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory( - sessionFactoryUuid, - sessionFactoryName + factory = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.getSessionFactory( + sessionFactoryUuid ); + if ( factory == null && StringHelper.isNotEmpty( sessionFactoryName ) ) { + factory = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( + sessionFactoryName + ); + } if ( factory == null ) { throw new HibernateException( "Could not find a SessionFactory [uuid=" + sessionFactoryUuid + ",name=" + sessionFactoryName + "]" diff --git a/hibernate-core/src/test/java/org/hibernate/test/serialization/TypeFactorySerializationTest.java b/hibernate-core/src/test/java/org/hibernate/test/serialization/TypeFactorySerializationTest.java index 567036f5cd..b317dd9e2d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/serialization/TypeFactorySerializationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/serialization/TypeFactorySerializationTest.java @@ -6,14 +6,18 @@ */ package org.hibernate.test.serialization; +import javax.naming.NamingException; + import org.junit.Test; import org.hibernate.HibernateException; +import org.hibernate.SessionFactory; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.SessionFactoryRegistry; import org.hibernate.internal.util.SerializationHelper; +import org.hibernate.internal.util.StringHelper; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.type.TypeFactory; @@ -55,8 +59,8 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { assertSame( factory, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) ); // Remove the session factory from the registry - SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), NAME, false, null ); - assertNull( SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), NAME ) ); + SessionFactoryRegistry.INSTANCE.removeSessionFactory( getSessionFactoryUuid( factory ), NAME, false, null ); + assertNull( findSessionFactory( getSessionFactoryUuid( factory ), NAME ) ); TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory(); byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory ); @@ -71,7 +75,7 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { } // Re-register the same session factory. - SessionFactoryRegistry.INSTANCE.addSessionFactory( factory.getUuid(), NAME, false, factory, null ); + SessionFactoryRegistry.INSTANCE.addSessionFactory( getSessionFactoryUuid( factory ), NAME, false, factory, null ); // Session factory resolved from typeFactory should be the new session factory // (because it is resolved from SessionFactoryRegistry.INSTANCE) @@ -83,11 +87,11 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { public void testUnregisterSerializeRegisterSameSessionFactoryNoName() throws Exception { Configuration cfg = new Configuration(); SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory(); - assertSame( factory, SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), null ) ); + assertSame( factory, findSessionFactory( getSessionFactoryUuid( factory ), null ) ); // Remove the session factory from the registry - SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), null, false, null ); - assertNull( SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), null ) ); + SessionFactoryRegistry.INSTANCE.removeSessionFactory( getSessionFactoryUuid( factory ), null, false, null ); + assertNull( findSessionFactory( getSessionFactoryUuid( factory ), null ) ); TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory(); byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory ); @@ -102,7 +106,7 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { } // Re-register the same session factory. - SessionFactoryRegistry.INSTANCE.addSessionFactory( factory.getUuid(), null, false, factory, null ); + SessionFactoryRegistry.INSTANCE.addSessionFactory( getSessionFactoryUuid( factory), null, false, factory, null ); // Session factory resolved from typeFactory should be the new session factory // (because it is resolved from SessionFactoryRegistry.INSTANCE) @@ -119,8 +123,8 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { assertSame( factory, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) ); // Remove the session factory from the registry - SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), NAME, false, null ); - assertNull( SessionFactoryRegistry.INSTANCE.findSessionFactory( factory.getUuid(), NAME ) ); + SessionFactoryRegistry.INSTANCE.removeSessionFactory( getSessionFactoryUuid( factory ), NAME, false, null ); + assertNull( findSessionFactory( getSessionFactoryUuid( factory ), NAME ) ); TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory(); byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory ); @@ -137,7 +141,7 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { // Now create a new session factory with the same name; it will have a different UUID. SessionFactoryImplementor factoryWithSameName = (SessionFactoryImplementor) cfg.buildSessionFactory(); assertSame( factoryWithSameName, SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( NAME ) ); - assertFalse( factory.getUuid().equals( factoryWithSameName.getUuid() ) ); + assertFalse( getSessionFactoryUuid( factory ).equals( getSessionFactoryUuid( factoryWithSameName ) ) ); // Session factory resolved from typeFactory should be the new session factory // (because it is resolved from SessionFactoryRegistry.INSTANCE) @@ -151,11 +155,11 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { public void testUnregisterSerializeRegisterDiffSessionFactoryNoName() throws Exception { Configuration cfg = new Configuration(); SessionFactoryImplementor factory = (SessionFactoryImplementor) cfg.buildSessionFactory(); - assertSame( factory, SessionFactoryRegistry.INSTANCE.getSessionFactory( factory.getUuid() ) ); + assertSame( factory, SessionFactoryRegistry.INSTANCE.getSessionFactory( getSessionFactoryUuid( factory ) ) ); // Remove the session factory from the registry - SessionFactoryRegistry.INSTANCE.removeSessionFactory( factory.getUuid(), null, false, null ); - assertNull( SessionFactoryRegistry.INSTANCE.getSessionFactory( factory.getUuid() ) ); + SessionFactoryRegistry.INSTANCE.removeSessionFactory( getSessionFactoryUuid( factory ), null, false, null ); + assertNull( SessionFactoryRegistry.INSTANCE.getSessionFactory( getSessionFactoryUuid( factory ) ) ); TypeFactory typeFactory = factory.getTypeResolver().getTypeFactory(); byte[] typeFactoryBytes = SerializationHelper.serialize( typeFactory ); @@ -171,8 +175,8 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { // Now create a new session factory with the same name; it will have a different UUID. SessionFactoryImplementor factoryWithDiffUuid = (SessionFactoryImplementor) cfg.buildSessionFactory(); - assertSame( factoryWithDiffUuid, SessionFactoryRegistry.INSTANCE.getSessionFactory( factoryWithDiffUuid.getUuid() ) ); - assertFalse( factory.getUuid().equals( factoryWithDiffUuid.getUuid() ) ); + assertSame( factoryWithDiffUuid, SessionFactoryRegistry.INSTANCE.getSessionFactory( getSessionFactoryUuid( factoryWithDiffUuid ) ) ); + assertFalse( getSessionFactoryUuid( factory ).equals( getSessionFactoryUuid( factoryWithDiffUuid ) ) ); // It should not be possible to resolve the session factory with no name configured. try { @@ -186,4 +190,25 @@ public class TypeFactorySerializationTest extends BaseUnitTestCase { factory.close(); factoryWithDiffUuid.close(); } + + private static String getSessionFactoryUuid(SessionFactory sessionFactory) throws NamingException { + try { + return (String) sessionFactory.getReference().get( "uuid" ).getContent() ; + } + catch (NamingException ex) { + throw new HibernateException( + "Could not determine UUID.", + ex + ); + } + } + + private static SessionFactory findSessionFactory(String uuid, String name ) { + SessionFactory sessionFactory = SessionFactoryRegistry.INSTANCE.getSessionFactory( uuid ); + if ( sessionFactory == null && StringHelper.isNotEmpty( name ) ) { + sessionFactory = SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( name ); + } + return sessionFactory; + + } }