Author: athimel Date: 2014-04-03 14:48:19 +0200 (Thu, 03 Apr 2014) New Revision: 3036 Url: http://forge.nuiton.org/projects/topia/repository/revisions/3036 Log: fixes #2969 Fix Topia's Hibernate 4.3.x integration (fix the way *ServiceRegistry are used) fixes #3078 should be OK now with Hibernate 4.3.5.Final and #2969 fix Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaUtil.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java 2014-04-03 09:33:43 UTC (rev 3035) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/internal/HibernateProvider.java 2014-04-03 12:48:19 UTC (rev 3036) @@ -45,7 +45,7 @@ import org.hibernate.event.spi.EventType; import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; -import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.service.spi.Stoppable; import org.nuiton.topia.persistence.TopiaConfigurationConstants; import org.nuiton.topia.persistence.TopiaNotFoundException; @@ -174,9 +174,9 @@ } // sletellier 20110411 : http://www.nuiton.org/issues/show/1454 - // Add persistance classes in hibernate config - for (Class<?> persistanceClass : hibernatePersistanceClasses) { - hibernateConfiguration.addClass(persistanceClass); + // Add persistence classes in hibernate config + for (Class<?> persistenceClass : hibernatePersistanceClasses) { + hibernateConfiguration.addClass(persistenceClass); } Properties prop = new Properties(); @@ -206,6 +206,48 @@ } /** + * Method to extract from the given Hibernate SessionFactory a working instance of StandardServiceRegistry + * <p/> + * IMPORTANT : As much as possible, prefer using the + * {@link #getSessionFactoryServiceRegistry(org.hibernate.SessionFactory)} mthod instead of the current one because + * the SessionFactoryServiceRegistry is a child of the StandardServiceRegistry + * <p/> + * NB: This method is static to make sure it does not depend on the current instance + * + * @param sessionFactory the Hibernate's SessionFactory instance + * @return the StandardServiceRegistry instance used by the given SessionFactory + */ + protected static StandardServiceRegistry getStandardServiceRegistry(SessionFactory sessionFactory) { + + // AThimel 03/04/14 The next two lines are the good way to get the StandardServiceRegistry in Hibernate 4.3 + SessionFactory.SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions(); + StandardServiceRegistry result = sessionFactoryOptions.getServiceRegistry(); + + return result; + } + + /** + * Method to extract from the given Hibernate SessionFactory a working instance of SessionFactoryServiceRegistry + * <p/> + * IMPORTANT : If possible, prefer using this method instead of + * {@link #getStandardServiceRegistry(org.hibernate.SessionFactory)} because the SessionFactoryServiceRegistry is a + * child of the StandardServiceRegistry + * <p/> + * NB: This method is static to make sure it does not depend on the current instance + * + * @param sessionFactory the Hibernate's SessionFactory instance + * @return the SessionFactoryServiceRegistry instance used by the given SessionFactory + */ + protected static SessionFactoryServiceRegistry getSessionFactoryServiceRegistry(SessionFactory sessionFactory) { + + // AThimel 03/04/14 The next two lines are the good way to get the SessionFactoryServiceRegistry in Hibernate 4.3 + SessionFactoryImplementor sessionFactoryImplementor = (SessionFactoryImplementor) sessionFactory; + SessionFactoryServiceRegistry result = (SessionFactoryServiceRegistry)sessionFactoryImplementor.getServiceRegistry(); + + return result; + } + + /** * Method to get an Hibernate service instance from a given Hibernate SessionFactory * <p/> * NB: This method is static to make sure it does not depend on the current instance @@ -216,14 +258,11 @@ * @throws org.hibernate.service.UnknownServiceException Indicates the service was not known. * @see org.hibernate.service.ServiceRegistry#getService(Class) */ - protected static <S extends Service> S getHibernateService(SessionFactory sessionFactory, Class<S> serviceClass) { - // Hibernate 4.2.x - SessionFactoryImplementor sessionFactoryImplementor = (SessionFactoryImplementor) sessionFactory; - ServiceRegistryImplementor serviceRegistry = sessionFactoryImplementor.getServiceRegistry(); + public static <S extends Service> S getHibernateService(SessionFactory sessionFactory, Class<S> serviceClass) { -// // Hibernate 4.3.x -// SessionFactory.SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions(); -// StandardServiceRegistry serviceRegistry = sessionFactoryOptions.getServiceRegistry() + // Hibernate 4.3.x : prefer using the SessionFactoryServiceRegistry method instead of StandardServiceRegistry + // because SessionFactoryServiceRegistry is a child of the StandardServiceRegistry + ServiceRegistry serviceRegistry = getSessionFactoryServiceRegistry(sessionFactory); S result = serviceRegistry.getService(serviceClass); return result; @@ -249,22 +288,16 @@ Properties properties = getHibernateConfiguration().getProperties(); - // init service registry - // Hibernate 4.2.x -// ServiceRegistryBuilder builder = new ServiceRegistryBuilder().applySettings(properties); -// ServiceRegistry serviceRegistry = builder.buildServiceRegistry(); -// hibernateSessionFactory = getHibernateConfiguration().buildSessionFactory(serviceRegistry); + // Use the next 2 lines if bootstrap customization is needed (classloader, autoclose, ...) + // {@see org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl) +// BootstrapServiceRegistry bootstrap = new BootstrapServiceRegistryBuilder().build(); +// StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder(bootstrap); -// // Hibernate 4.3.x StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder(); StandardServiceRegistry standardServiceRegistry = builder.applySettings(properties).build(); hibernateSessionFactory = getHibernateConfiguration().buildSessionFactory(standardServiceRegistry); - // we can't reuse original serviceRegistry instance - // we must call getServiceRegistry on factory to get a working one - SessionFactoryImplementor sessionFactoryImplementor = (SessionFactoryImplementor) hibernateSessionFactory; - ServiceRegistry serviceRegistryInit = sessionFactoryImplementor.getServiceRegistry(); - EventListenerRegistry eventListenerRegistry = serviceRegistryInit.getService(EventListenerRegistry.class); + EventListenerRegistry eventListenerRegistry = getHibernateService(hibernateSessionFactory, EventListenerRegistry.class); TopiaHibernateEventListener listener = new TopiaHibernateEventListener(sessionRegistry); eventListenerRegistry.appendListeners(EventType.PRE_INSERT, listener); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaUtil.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaUtil.java 2014-04-03 09:33:43 UTC (rev 3035) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaUtil.java 2014-04-03 12:48:19 UTC (rev 3036) @@ -52,6 +52,7 @@ import org.nuiton.topia.persistence.TopiaConfigurationConstants; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaNotFoundException; +import org.nuiton.topia.persistence.internal.HibernateProvider; import org.nuiton.topia.persistence.support.TopiaHibernateSupport; import org.nuiton.util.RecursiveProperties; import org.nuiton.util.Resource; @@ -160,7 +161,7 @@ } /** - * Test si une entite donnee correspondant a une configuration existe en + * Test si une entité donnée correspondant a une configuration existe en * base. * * @param topiaHibernateSupport the Hibernate support required for this operation @@ -226,6 +227,13 @@ log.error("Cant connect to database", e); } + // close connectionProviderSupplier + try { + connectionProviderSupplier.close(); + } catch (IOException e) { + log.error("Cant close connection provider", e); + } + return exist; } @@ -318,8 +326,7 @@ try { - ConnectionProvider connectionProvider = - connectionProviderSupplier.get(); + ConnectionProvider connectionProvider = connectionProviderSupplier.get(); Dialect dialect = Dialect.getDialect(configuration.getProperties()); @@ -492,85 +499,56 @@ return properties; } -// /** -// * Hibernate 4.2.x compatible Supplier<ConnectionProvider> -// */ -// public static class ConnectionProviderSupplier implements Supplier<ConnectionProvider>, Closeable { -// -// protected ServiceRegistry serviceRegistry; -// -// protected ConnectionProvider connectionProvider; -// -// protected final boolean inlineRegistry; -// -// public ConnectionProviderSupplier(TopiaHibernateSupport topiaHibernateSupport) { -// inlineRegistry = false; -// SessionFactory sessionFactory = topiaHibernateSupport.getHibernateFactory(); -// SessionFactoryImplementor sessionFactoryImplementor = (SessionFactoryImplementor) sessionFactory; -// serviceRegistry = sessionFactoryImplementor.getServiceRegistry(); -// } -// -// public ConnectionProviderSupplier(Configuration configuration) { -// inlineRegistry = true; -// -// Properties properties = configuration.getProperties(); -// ServiceRegistryBuilder builder = new ServiceRegistryBuilder().applySettings(properties); -// this.serviceRegistry = builder.buildServiceRegistry(); -// } -// -// @Override -// public ConnectionProvider get() { -// if (connectionProvider == null) { -// connectionProvider = serviceRegistry.getService(ConnectionProvider.class); -// } -// return connectionProvider; -// } -// -// @Override -// public void close() throws IOException { -// if (inlineRegistry) { -// ServiceRegistryBuilder.destroy(serviceRegistry); -// } -// } -// } - /** - * Hibernate 4.3.x compatible Supplier<ConnectionProvider> + * Hibernate 4.3.x compatible Supplier<ConnectionProvider>. The provider will choose the best way to find the + * ConnectionProvider depending on the way is has been created. */ public static class ConnectionProviderSupplier implements Supplier<ConnectionProvider>, Closeable { + /** + * If provided, the SessionFactory will be used instead of the StandardServiceRegistry + */ + protected SessionFactory sessionFactory; + + /** + * StandardServiceRegistry will be used if no SessionFactory is provided + */ protected StandardServiceRegistry standardServiceRegistry; protected ConnectionProvider connectionProvider; - protected final boolean inlineRegistry; - public ConnectionProviderSupplier(TopiaHibernateSupport topiaHibernateSupport) { - inlineRegistry = false; - SessionFactory sessionFactory = topiaHibernateSupport.getHibernateFactory(); - SessionFactory.SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions(); - this.standardServiceRegistry = sessionFactoryOptions.getServiceRegistry(); + Preconditions.checkNotNull(topiaHibernateSupport); + sessionFactory = topiaHibernateSupport.getHibernateFactory(); } public ConnectionProviderSupplier(Configuration configuration) { - inlineRegistry = true; - - StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder(); Properties properties = configuration.getProperties(); + StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder(); this.standardServiceRegistry = builder.applySettings(properties).build(); } @Override public ConnectionProvider get() { if (connectionProvider == null) { - connectionProvider = standardServiceRegistry.getService(ConnectionProvider.class); + if (sessionFactory != null ) { + // If SessionFactory is provided, use the SessionFactoryServiceRegistry + connectionProvider = HibernateProvider.getHibernateService(sessionFactory, ConnectionProvider.class); + } else { + // otherwise use the StandardServiceRegistry + connectionProvider = standardServiceRegistry.getService(ConnectionProvider.class); + } } return connectionProvider; } @Override public void close() throws IOException { - if (inlineRegistry) { + // Do not close the SessionFactory, it is probably used somewhere else + + // On the over hand, if standardServiceRegistry is provided, that means the its has been created explicitly + // for the current instance, close it + if (standardServiceRegistry != null) { StandardServiceRegistryBuilder.destroy(standardServiceRegistry); } }