Null entityManagerFactory on PersistenceUnitService
benkirby Aug 16, 2011 1:35 PMHi,
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