4 Replies Latest reply on Dec 14, 2006 2:10 PM by gavin.king

    Entity Manager Woes

    msduk

      Ok I have oficially downgraded myslef to n00b after a large amount of previous success with seam.

      Basically I am trying to use the entity manager from an external thread. I have the entity manager.

      EntityManager em = null;
      
       try {
       jndi = new InitialContext();
       //TODO get name from settings
       EntityManagerFactory emf = (EntityManagerFactory)
       jndi.lookup("java:/myEntityManagerFactory");
       em = emf.createEntityManager();
       NrgOrder nrgOrder = em.find(NrgOrder.class, 1);
       nrgOrder.setState(NrgOrder.SEND_ERR);
       em.persist(nrgOrder);
       log.debug(nrgOrder.getState());
       em.close();
       } catch (Exception e) {
       e.printStackTrace();
       } finally {
       try {
       if(jndi!=null) jndi.close();
       } catch (NamingException e) {
       e.printStackTrace();
       }
       }


      the myEntityManagerFactory is the same one as seam references (I think) as defined by the following...


      <persistence>
       <persistence-unit name="nrg2">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <jta-data-source>java:/myDatasource</jta-data-source>
       <properties>
       <!-- <property name="hibernate.hbm2ddl.auto" value="create"/> -->
       <property name="hibernate.cache.use_query_cache" value="true"/>
       <property name="hibernate.show_sql" value="true"/>
       <property name="jboss.entity.manager.factory.jndi.name" value="java:/myEntityManagerFactory"/>
       <property name="jboss.entity.manager.jndi.name" value="java:/entityManager"/>
       </properties>
       </persistence-unit>
      </persistence>
      
      
      and...
      
      <?xml version="1.0" encoding="utf-8"?>
      <components>
       <component name="org.jboss.seam.core.init">
       <property name="debug">true</property>
       <property name="myFacesLifecycleBug">true</property>
       <property name="jndiPattern">my/#{ejbName}/local</property>
       </component>
      
       <component name="entityManager" class="org.jboss.seam.core.ManagedPersistenceContext">
       <property name="persistenceUnitJndiName">java:/myEntityManagerFactory</property>
       </component>
      
       <component name="org.jboss.seam.core.manager">
       <property name="conversationTimeout">300000</property>
       </component>
      
       <component class="org.jboss.seam.core.Ejb" installed="false"/>
      </components>
      
      


      I am able to load using the above snippet but no updates are taking place.

      I am calling close() with no joy. I tried calling flush() but i get


      14:17:30,375 ERROR [STDERR] javax.persistence.TransactionRequiredException: no transaction is in progress
      14:17:30,375 ERROR [STDERR] at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:293)
      14:17:30,375 ERROR [STDERR] at halvor.schedulers.PendingOrderQuartzTarget.execute(PendingOrderQuartzTarget.java:95)
      14:17:30,375 ERROR [STDERR] at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
      14:17:30,375 ERROR [STDERR] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)


      If i try and use transaction EntityTransaction et = em.getTransaction();
      et.begin(); I get...



      14:19:00,156 ERROR [STDERR] java.lang.IllegalStateException: JTA EntityManager cannot access a transactions
      14:19:00,156 ERROR [STDERR] at org.hibernate.ejb.AbstractEntityManagerImpl.getTransaction(AbstractEntityManagerImpl.java:316)
      14:19:00,156 ERROR [STDERR] at halvor.schedulers.PendingOrderQuartzTarget.execute(PendingOrderQuartzTarget.java:91)
      14:19:00,156 ERROR [STDERR] at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
      14:19:00,156 ERROR [STDERR] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)


      I am clearly missing something obvious so can someone point it out to me plesae.

        • 1. Re: Entity Manager Woes

          What is an "external thread"? Another app on the same server? A thread that you start from outside Seam but from within your app?

          • 2. Re: Entity Manager Woes
            msduk

            I am using Quartz to invoke methods but I will have to admit to the inner working being 'magic' to me.

            I have just gone back to square one and tried a completely different approach as, since I last looked, quartz has EJB3 initilisation support.

            Ok I will not get the bijection capabilities I assume but will get a working EntityManager hopefully.

            Is this a far better approach?

            • 3. Re: Entity Manager Woes

              Yeah - sorry. It's kind of obvious from the stack trace where you are calling from.

              You really should be doing JPA stuff from an environment that manages transaction support. I don't know much about quartz or its EJB3 support, so perhaps there is some way to appropriately configure it. If you really need to manage the transaction yourself you can look up the javax.transaction.TransactionManager under java:/TransactionManager and manage it yourself. But I'd recommend using services that manage the tx for you.

              • 4. Re: Entity Manager Woes
                gavin.king

                Yeah, you got a problem because the Quartz threadpool is probably not really "kosher" in the container environment (it should really be using JCA to take advantage of a container threadpool). So I'm not sure if you will even be able to look up UserTransaction from that thread.

                I can see a couple of approaches:

                (1) like Norman says, try managing transactions using the TransactionManager (ugly!)
                (2) try using a non-JTA EntityManager, and a resource-local transaction on the EM

                JPA doesn't let you flush outside of a transaction.

                Note that this is not a Seam question, and the guys in the EJB3 forum might have better answers for this one that we do here.