5 Replies Latest reply on Jun 20, 2006 7:02 AM by abl

    Problems with EntityManagerFactory

    qualitha

      Hello,

      I am currently trying to override the settings in the persistence.xml dynamically with my own hashmap. The background is, that I want to change the datasource dynamically depending on where to persist the Entity.

      Unfortunatley the factory does not seem to care for any values, that I am trying to override. Did I miss anything?

      My current code is as follows:

      @Stateless
      public class EJB3CampaignDAO extends EJB3BaseDAO implements CampaignDAO {
      
       @PersistenceUnit(unitName="testPersdb")
       EntityManagerFactory emf;
      
      .....
      
       public datacontainer.Campaign findSingleCampaign ( int id) {
      
       java.util.Map configOverride = new HashMap();
       configOverride.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
       configOverride.put("javax.persistence.transactionType", "JTA");
       configOverride.put("javax.persistence.jtaDataSource", "anotherDatasource_ccDS");
      
       EntityManager manager = emf.createEntityManager(configOverride);
      


      And my persistence.xml looks like this

      <?xml version="1.0" encoding="UTF-8"?>
      
      <persistence>
       <persistence-unit name="testPersdb" transaction-type="JTA">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <jta-data-source>java:/aDatasource_ccDS</jta-data-source>
       <class>persistence.ejb3.entity.EJB3Campaign</class>
       </persistence-unit>
      </persistence>
      


      If I´m trying to override the setting while creating the EntityManagerFactory I get a very unexpected ClassCastException. So this way does not seem to work either

      @Stateless
      public class EJB3CampaignDAO extends EJB3BaseDAO implements CampaignDAO {
      
       @PersistenceContext(unitName="testPersdb")
       private EntityManager manager;
       public datacontainer.Campaign findSingleCampaign ( int id) {
       System.out.println("findSingleCampaign " + id);
      
       java.util.Map configOverride = new HashMap();
       configOverride.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
       configOverride.put("javax.persistence.transactionType", "JTA");
       configOverride.put("javax.persistence.jtaDataSource", "anotherDatasource_ccDS");
       EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPersdb", configOverride);
       emf = Persistence.createEntityManagerFactory("testPersdb", configOverride);
      
       manager = emf.createEntityManager();
      


      This is how the Exception looks like
      javax.ejb.EJBTransactionRolledbackException: javax.persistence.PersistenceException: java.lang.ClassCastException: java.lang.String; nested exception is: javax.persistence.PersistenceException: java.lang.ClassCastException: java.lang.String
      javax.persistence.PersistenceException: java.lang.ClassCastException: java.lang.String
       at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:188)
       at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:110)
       at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:37)
      


      Is there anything wrong in the code or am I thinking totally wrong? Or is this just a bug in the JBOSS EJB3-Implementation?

      Any help is greatly appriciated

      THank you

        • 1. Re: Problems with EntityManagerFactory
          epbernard

          these properties are not overridable at all, where did you see that it's possible?

          • 2. Re: Problems with EntityManagerFactory
            qualitha

            There were a few examples in the inet that used this override method.
            But if this isn´t possible, is there a way to change the datasource dynamically and therefor use the same entities for different datasources or is this not an issue in ejb3?

            Thank you for your help

            Thomas

            • 3. Re: Problems with EntityManagerFactory
              abl

              Hi Thomas,

              I'm working on the same issue for a while - asking this many times here without a clear answer or solution. What I have found out so far, you can do (assuming you have a PU "default" in your persistence.xml):

              Map<String,String> map = new HashMap<String,String>();
              map.put( "hibernate.hbm2ddl.auto", "update");
              map.put( "hibernate.dialect", "org.hibernate.dialect.Oracle9Dialect");
              map.put( "hibernate.connection.provider_class", "org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider");
              map.put( "hibernate.cache.provider_class", "org.jboss.ejb3.entity.TreeCacheProviderHook");
              map.put( "hibernate.treecache.mbean.object_name", "jboss.cache:service=EJB3EntityTreeCache");
              
              // ignored - set explicit below
              // map.put( "javax.persistence.jtaDataSource", "java:/anotherDS");
              
              InitialContext jndi = new InitialContext();
              DataSource ds = (DataSource) jndi.lookup( "java:/anotherDS");
              
              Ejb3Configuration cfg = new Ejb3Configuration();
              cfg.setDataSource( ds);
              
              // this works ! tables in db are created.
              // but using returned em later result in a "no transaction" exception.
              EntityManagerFactory emf = cfg.createEntityManagerFactory( "default", map);
              
              
              EntityManager em = emf.createEntityManager();
              // error !
              em.persist( ...);
              


              as far as I understand, with this you can only get an application managed em (non JTA), where you have to begin and commit your tx yourselve. It is not an container managed em.

              so I guess this requierement is not covered in ejb3 yet, although it is imho usual and important.

              andy

              • 4. Re: Problems with EntityManagerFactory
                qualitha

                Andy,

                thank you for this help so far. Unfortunately the transaction-managament is not an unimportant issue in my application I would like to let EJB3 do the work.

                This is what I found in another thread. This is, what Bill Burke recommends in such a situation.

                deploy your entities as you would but assign them a JNDI name(see docs). In your EJB interceptor pick the appropriate JNDI name of the EntityManager you want to access. Either inject the ENtityManager into the field of your bean using a custom annotation, or stuff the chosen entity manager into a java.lang.ThreadLocal. This way you still get the automatic session management that the EJB/Java Persistence integration gives you. Following me?


                Did you try this way as well? I don´t see if this could be a real solution to this problem.

                Thank you
                Thomas



                • 5. Re: Problems with EntityManagerFactory
                  abl

                  Hi Thomas,

                  please see: http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3951914

                  The hint from Bill doesn't solve your (and mine) initial problem: programmatic creation of ems, that can be used like the ones deployed through persistence.xml. It is only a way for dynamic selection of a em at runtime.

                  It seems everyone is using a workaround at the moment. I will further investigate this, if I have the time, or maybe someone else comes up with a solution.