9 Replies Latest reply on Aug 18, 2011 10:51 AM by benkirby

    Null entityManagerFactory on PersistenceUnitService

    benkirby

      Hi,

       

      I'm currently writing backend services for JBoss AS7 using CDI, and have run into issues concerning opening transactions; when an entityManager is created for the call, it always has a null entityManagerFactory. This is the case on both for 7.0.0.Final and 7.1.0.Alpha1-SNAPSHOT. The same code regarding use of Transactional annotation and @PersistenceContext worked in AS6.

       

      Here's the stacktrace, background info is below.

       

      {code}

      11:50:49,578 ERROR [uk.co.myService.service.MyService] (http--193.131.98.84-8080-1) Error in startCDIJob: java.lang.NullPointerException

          at org.jboss.as.jpa.container.EntityManagerUtil.createEntityManager(EntityManagerUtil.java:43) [jboss-as-jpa-7.1.0.Alpha1-SNAPSHOT.jar:7.1.0.Alpha1-SNAPSHOT]

          at org.jboss.as.jpa.transaction.TransactionUtil.getOrCreateTransactionScopedEntityManager(TransactionUtil.java:131) [jboss-as-jpa-7.1.0.Alpha1-SNAPSHOT.jar:7.1.0.Alpha1-SNAPSHOT]

          at org.jboss.as.jpa.container.TransactionScopedEntityManager.getEntityManager(TransactionScopedEntityManager.java:85) [jboss-as-jpa-7.1.0.Alpha1-SNAPSHOT.jar:7.1.0.Alpha1-SNAPSHOT]

          at org.jboss.as.jpa.container.AbstractEntityManager.joinTransaction(AbstractEntityManager.java:531) [jboss-as-jpa-7.1.0.Alpha1-SNAPSHOT.jar:7.1.0.Alpha1-SNAPSHOT]

          at uk.co.core.dao.SliceDAO.findBigJobFlag(SliceDAO.java:206) [core-jar-2011.1.2-SNAPSHOT.jar:]

          at uk.co.core.util.ServiceUtil.getSliceBigJobStatus(ServiceUtil.java:31) [core-jar-2011.1.2-SNAPSHOT.jar:]

          at uk.co.core.util.-1702230783$Proxy$_$$_WeldSubclass.getSliceBigJobStatus(-1702230783$Proxy$_$$_WeldSubclass.java) [core-jar-2011.1.2-SNAPSHOT.jar:]

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]

          at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]

          at org.jboss.interceptor.proxy.SimpleInterceptionChain.invokeNextInterceptor(SimpleInterceptionChain.java:112) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]

          at org.jboss.interceptor.proxy.InterceptorInvocationContext.proceed(InterceptorInvocationContext.java:119) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]

          at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:194) [seam-persistence-3.0.0.Final.jar:]

          at org.jboss.seam.transaction.Work.workInTransaction(Work.java:54) [seam-persistence-3.0.0.Final.jar:]

          at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:188) [seam-persistence-3.0.0.Final.jar:]

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]

          at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]

          at org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation.invoke(InterceptorInvocation.java:72) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]

          at org.jboss.interceptor.proxy.SimpleInterceptionChain.invokeNextInterceptor(SimpleInterceptionChain.java:82) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]

          at org.jboss.interceptor.proxy.InterceptorMethodHandler.executeInterception(InterceptorMethodHandler.java:133) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]

          at org.jboss.interceptor.proxy.InterceptorMethodHandler.invoke(InterceptorMethodHandler.java:112) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]

          at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:65) [weld-core-1.1.2.Final.jar:2011-07-26 15:02]

          at uk.co.core.util.-1702230783$Proxy$_$$_WeldSubclass.getSliceBigJobStatus(-1702230783$Proxy$_$$_WeldSubclass.java) [core-jar-2011.1.2-SNAPSHOT.jar:]

          at uk.co.core.service.Service.putJobOnCriticalQueue(Service.java:161) [core-jar-2011.1.2-SNAPSHOT.jar:]

          at uk.co.myService.service.MyService.startCDIJob(MyService.java:92) [myService-sar-2011.1.2-SNAPSHOT.jar:]

      {code}

       

      The background: the code is packaged in an EAR, as follows:

       

      {code}

          myService.ear --- lib

                                         --- core-jar.jar

                                         --- {seam solder, persistence, etc}

                                  --- myService-jar.jar

      {code}  

       

      myService-jar references some classes in core-jar. core-jar specifies a persistence.xml file, containing the CorePU persistence unit. As of AS7, the unit no longer specifies the following properties, as I understand they're no longer needed:

       

      {code}

      <property name="jboss.entity.manager.factory.jndi.name" value="java:/jpa/coreEMF"/>

      <property name="hibernate.session_factory_name" value="java:/hibernate/CoreSessionFactory"/>

      <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>

      {code}

       

      Both my JARs in the EAR have a beans.xml with a TransactionInterceptor defined. You can see from the stacktrace that this is being invoked

       

      The class ServiceUtil (see stacktrace) is a CDI managed bean and is annotated with org.jboss.seam.transaction.Transactional and injects an instance of SliceDAO, then calls findBigJobFlag() on it, that's in the following code:

       

       

      {code}

      public class SliceDAO {

       

          @PersistenceContext(unitName="CorePU")

          protected EntityManager em;

       

          ...

       

          public boolean findBigJobFlag(String sliceId){

              em.joinTransaction();

              ...

              TypedQuery<Integer> q = em.createNamedQuery(theQueryString, Integer.class);

         

              // run query

              ...

      {code}

       

      So I'm just using @PersistenceContext, as per the Weld documentation - nowhere am I defining an entityManagerFactory. When this method is called, the NullPointerException is thrown.

       

      When the EAR initially deploys, I can see that the persistence unit is deployed, and, via Eclipse's debugger, I can see that the org.jboss.as.jpa.service.PersistenceUnitService for CorePU has a non-null entityManagerFactory.

       

      However, also from debugger, I can see that the TransactionScopedEntityManager in the stacktrace at runtime always has a null entityManagerFactory. This value is set on it by org.jboss.as.weld.services.bootstrap.WeldJpaInjectionServices, in the following code:

       

       

      {code}

          @Override

          public EntityManager resolvePersistenceContext(InjectionPoint injectionPoint) {

              //TODO: cache this stuff

              final PersistenceContext context = injectionPoint.getAnnotated().getAnnotation(PersistenceContext.class);

              if(context == null) {

                  throw new RuntimeException("Could not find @PersistenceContext annotation on " + injectionPoint.getMember());

              }

              final String scopedPuName = getScopedPUName(deploymentUnit, context.unitName());

              final ServiceName persistenceUnitServiceName = PersistenceUnitService.getPUServiceName(scopedPuName);

       

              final ServiceController<?> serviceController = serviceRegistry.getRequiredService(persistenceUnitServiceName);

              //now we have the service controller, as this method is only called at runtime the service should

              //always be up

              PersistenceUnitService persistenceUnitService = (PersistenceUnitService)serviceController.getValue();

              return new TransactionScopedEntityManager(scopedPuName,new HashMap<Object,Object>(), persistenceUnitService.getEntityManagerFactory(), sfsbxpcMap);

          }

      {code}

       

      All the values in the code above, when it runs, appear to be correct, and the PersistenceUnitService is found. However its entityManagerFactory is null.

       

      Am I missing some entityManagerFactory config for AS7, now that the factory isn't looked up via JNDI? Why is the entityManagerFactory null on the service looked up up at runtime?

       

      Hope you can help, or suggest some next steps.

       

      Thanks,

      Ben

        • 1. Re: Null entityManagerFactory on PersistenceUnitService
          smarlow

          Could you attach a copy of the server.log.  I would like to see the placement of the above exception and the "starting Persistence Unit Service 'CorePU' message".

           

          Looks like a race condition in PersistenceUnitService but I will know better after seeing the log.

          • 2. Re: Null entityManagerFactory on PersistenceUnitService
            smarlow

            A code change to address the race condition in PersistenceUnitService was just committed.  If that is the root cause (which it certainly sounds like from you saw in the debugger). 

             

            https://github.com/jbossas/jboss-as/commit/0250351629b90d83c15b6dfdd117a04c624118f6

            1 of 1 people found this helpful
            • 3. Re: Null entityManagerFactory on PersistenceUnitService
              benkirby

              Thanks a lot for the (very!) quick reply and attempted fix, Scott. Got the latest build from Hudson and gave it a go, but unfortunately still getting the same exception.

               

              I should have made it clearer in my original post; the EAR and the persistence unit deploys fine. It then sits there, until I deploy a WAR and activate a method which hits the 'startCDIJob' method on MyService. So it's not a race condition at startup - although it could be when the PersistenceUnitService is looked up/has it's fields created, I suppose.

               

              I'm just trying to knock up a quick Arquillian test to show you the issue, will post here when done. As far as configuration and use is concerned, are we doing everything right? @PersistenceContext, @Transactional, no explicit definition of EntityManagerFactory? From reading the AS7 dev guide, it seems we are. Are there any examples of backend code using @PersistenceContext, persistence.xml, etc?

               

              In fact, just tried it with manual UserTransaction, and it still fails. So it's purely down to getting the entityManager/Factory.

              • 4. Re: Null entityManagerFactory on PersistenceUnitService
                benkirby

                Just read this at the top of the TransactionScopedEntityManager class:

                 

                {code}
                /**

                * Transaction scoped entity manager will be injected into SLSB or SFSB beans.  At bean invocation time, they

                * will join the active transaction if one is present.  Otherwise, they will simply be cleared at the end of

                * the bean invocation.

                * <p/>

                * This is a proxy for the underlying persistent provider EntityManager.

                {code}

                 

                and thought the bean types might be relevant.

                 

                • MyService is an EJB Singleton
                • ServiceUtil is injected on this, and is a managed bean
                • SliceDAO is injected on this, and is a managed bean

                 

                So there're no Stateful or Stateless session beans in the execution chain...

                • 5. Re: Null entityManagerFactory on PersistenceUnitService
                  benkirby

                  Been debugging this all day, and finally see exactly what you mean about the race condition - unfortunately the code change wasn't sufficient, as it's still an issue.

                   

                  What I didn't realise was that the TransactionScopedEntityManager is created at the very beginning, when Weld creates the managed bean object graph - I was thinking it would only try for the entityManager when the transactional code was actually executed (see my comment above), which I can see now isn't the case. As it happens at the beginning, this causes the race condition.

                   

                  I've put breakpoints on

                   

                  • the finally block of PersistenceUnitService.start() - at which point the entityManagerFactory HAS been created
                  • the constructor for TransactionScopedEntityManager (TSEM), which takes the entityManagerFactory as a parameter

                   

                  When the service deploys, you can clearly see the latter breakpoint comes up before the former - so the TSEM has a null entityManagerFactory, as it got it from the PersistenceUnitService before it had finished initialising itself!

                   

                  If I use a breakpoint to manually delay the construction of my SliceDAO in the object graph, then release when the service has finished initialising, all is well.

                   

                  Anyway, I guess you already know all this! I've been unable to create an Arquillian test that doesn't require a bespoke datasource/db mirroring ours, and that doesn't use a lot of our code. Will you be able to recreate?

                   

                  Also, any ideas for workarounds? The only one that appears to work at present (presumably because of no object graph?) is to make all the classes involved with transactions stateless or stateful session beans, along with the serialisation tweaks that entails - which sort of goes against one of the aims of CDI's managed beans, I think.

                   

                  Let me know what you think, and if you require any more input from us. Thanks for your help.

                  • 6. Re: Null entityManagerFactory on PersistenceUnitService
                    smarlow

                    Its fine, its great that we did the sweep of the code last night, to fix similar race conditions that could of happened.  To someone, someday.  All encouraged by your post.

                     

                    Regarding your question about examples, some are at https://docs.jboss.org/author/display/AS7/JPA+Reference+Guide.  More will probably be added, since its community documentation that anyone can update.

                    • 7. Re: Null entityManagerFactory on PersistenceUnitService
                      smarlow

                      Ben Kirby wrote:

                       

                      What I didn't realise was that the TransactionScopedEntityManager is created at the very beginning, when Weld creates the managed bean object graph - I was thinking it would only try for the entityManager when the transactional code was actually executed (see my comment above), which I can see now isn't the case. As it happens at the beginning, this causes the race condition.

                       

                      Initially, the injected TransactionScopedEntityManager, doesn't contain a Hibernate EntityManager instance.  We inject the instance of the TransactionScopedEntityManager, with just enough information (including the EntityManagerFactory), so when your code invokes any of the EntityManager methods, the underlying Hibernate EntityManager will be created and associated with the active transaction (to be reused on the next EntityManager invocation through the TransactionScopedEntityManager).  The TransactionScopedEntityManager acts like a proxy.

                       

                       

                       

                      I've put breakpoints on

                       

                      • the finally block of PersistenceUnitService.start() - at which point the entityManagerFactory HAS been created
                      • the constructor for TransactionScopedEntityManager (TSEM), which takes the entityManagerFactory as a parameter

                       

                      When the service deploys, you can clearly see the latter breakpoint comes up before the former - so the TSEM has a null entityManagerFactory, as it got it from the PersistenceUnitService before it had finished initialising itself!

                       

                      If I use a breakpoint to manually delay the construction of my SliceDAO in the object graph, then release when the service has finished initialising, all is well.

                       

                      Anyway, I guess you already know all this! I've been unable to create an Arquillian test that doesn't require a bespoke datasource/db mirroring ours, and that doesn't use a lot of our code. Will you be able to recreate?

                       

                      Also, any ideas for workarounds? The only one that appears to work at present (presumably because of no object graph?) is to make all the classes involved with transactions stateless or stateful session beans, along with the serialisation tweaks that entails - which sort of goes against one of the aims of CDI's managed beans, I think.

                       

                      Let me know what you think, and if you require any more input from us. Thanks for your help.

                       

                      A test case that might be similar to one of the tests in https://github.com/jbossas/jboss-as/tree/master/testsuite/integration/src/test/java/org/jboss/as/testsuite/integration (some JPA tests are under jpa subfolder), would be welcome.  To ensure that the bug is fixed and kept fixed.

                       

                      It might be helpful, if you could paste a copy of the call stack for the TransactionScopedEntityManager constructor call (just to confirm for me that it is what I think it is).

                       

                      From the excellent information that you have included above, I'm thinking that we need the TransactionScopedEntityManager constructor call, to indirectly depend on the PersistenceUnitService (such dependencies are expressed internally via our  services layer and cause proper ordering of initialization). 

                       

                      In terms of a workaround, I'm not sure yet.

                      1 of 1 people found this helpful
                      • 8. Re: Null entityManagerFactory on PersistenceUnitService
                        smarlow

                        Ben,

                         

                        Stuart worked on a Weld solution last night (https://github.com/jbossas/jboss-as/commit/2716b0caeabe8681829856fb96517c96e96cf224).  If you build AS7 from source or use the nightly builds, that change should show up.  Weld will now add a dependency on the PersistenceUnitService, such that the PU service will start and then the injection of the EntityManagerService will occur.

                         

                        Scott

                        • 9. Re: Null entityManagerFactory on PersistenceUnitService
                          benkirby

                          Ah, brilliant!

                           

                          Just came on here to post the call stack and detail a workaround (make the Thread sleep in my bean's constructor - advanced stuff), but, following on from the above, am now using the latest dist from Hudson, have removed the artifical delay and it works a treat. No NPE.

                           

                          Thanks a lot for the quick responses from both of you, very much appreciated. Will still try to do test case if I have time.