1 Reply Latest reply on Feb 3, 2009 8:02 AM by bdaw

    Injecting existing HibernateSession/SessionFactory

    bdaw

      We had a discussion with TomB about JBPM needs and one of the important requirements is to inject existing Hibernate Session/SessionFactory.

      At the moment design looks as follows:
      1) The bootstrap method in IdentityStore creates HibernateEntityManagerFactory during initialization of the store.

      protected HibernateEntityManagerFactory bootstrapHibernateEntityManager(IdentityStoreConfigurationMetaData configurationMD) throws IdentityException
       {
      
       String persistenceUnit = configurationMD.getOptionSingleValue(PERSISTENCE_UNIT);
      
       if (persistenceUnit == null)
       {
       throw new IdentityException("Persistence Unit not defined for IdentityStore: " + getId());
       }
      
       return (HibernateEntityManagerFactory)Persistence.createEntityManagerFactory(persistenceUnit);
      
       }
      


      Single instance of the IdentityStore (that reflect to one configuration piece) can be utilized by different repositories/realms so...
      2) Each time the new IdentitySession is created it calls IdentityStore.createIdentityStoreSession() to get new IdentityStoreSession connected with the store. Then every time different realm call the same IdentityStore instance, IdentityStoreSession is passed to the IdentityStore methods inside IdentityStoreInvocation object. The actuall HibernateEntityManager object is there and HibernateIdentityStoreImpl retreives it from IdentityStoreSession context:

      protected HibernateEntityManager getHibernateEntityManager(IdentityStoreInvocationContext ctx) throws IdentityException
       {
       try
       {
       return (HibernateEntityManager)ctx.getIdentityStoreSession().getSessionContext();
       }
       catch (IdentityException e)
       {
       throw new IdentityException("Cannot obtain HibernateEntityManager", e);
       }
       }
      


      Currently there is no direct way to pass the existing EntityManager. Direct workaround for now is to extend HibernateIdentityStoreImpl and override the bootstrapHibernateEntityManager method. It could be also possible to change IdentitySessionImpl and inject Hibernate Session object there.

      Such possibility should be enabled by default so other possibilities I see are:

      - Use JNDI to grab HibernateEntityManagerFactory.
      - Enable other ways to bootstrap the whole framework - like MC. Then it should be easier to inject different components

      One other problem is that currently HibernateIdentityStoreImpl uses both JPA and Hibernate annotations and therefore requires HibernateEntityManager. For projects that use plain hibernate (SessionFactory) it may rise a problem to provide HibernateEntityManager/Factory object. I see that hibernate EntityManagerFactoryImpl has a constructor that could be used:
      http://www.hibernate.org/hib_docs/entitymanager/api/org/hibernate/ejb/EntityManagerFactoryImpl.html

      EntityManagerFactoryImpl(org.hibernate.SessionFactory sessionFactory, javax.persistence.spi.PersistenceUnitTransactionType transactionType, boolean discardOnClose, Class sessionInterceptorClass)
      

      I cannot confirm it is allowed/suggested/possible way of doing the conversion.

      Probably the best way to go will be to just change HibernateIdentityStoreImpl to use plain hibernate without JPA annotations or classes.

        • 1. Re: Injecting existing HibernateSession/SessionFactory
          bdaw

          I changed HibernateIdentityStoreImpl to use hibernate SessionFactory instead of HibernateEntityManagerFactory. So previous IdentityStore.bootstrapHibernateEntityManager method is now bootstrapHibernateSessionFactory. There is also one additional way to provide store with SessionFactory - using JNDI:

          so possible configuration is:

          <option>
           <name>persistenceUnit</name>
           <value>jboss-identity-model1</value>
          </option>


          or

          <option>
           <name>hibernateSessionFactoryJNDIName</name>
           <value>jndi/path/to/hibernate/SessionFactory/object/here</value>
          </option>