Inheritence of PersistenceContext
jzmmek2k2 Mar 7, 2006 3:30 PMI am currently trying to integrate the "open-session-in-view" pattern in my project (tapestry4 + ejb3).
Both technologies are great, but I get this LazyInitializationException, you know what I mean.
Inspired by the Seam-approach I tried to do something similar using tapestry instead of jsf.
My main problem is the handling of "injected" EntityManagers.
EntityManager of type "EXTENDED" are only inherited to other @EJB resources within a JTA-transaction.
For my understanding the "open-session-in-view" does not need a transaction at all,
just a open session (=> HibernateSession = EntityManager(EXTENDED)) to prevent the LazyInitializationException.
But calling an EJB (having a PersistenceContext.TRANSACTION) in the weblayer without having a JTA-transaction returns detached Entities.
This is correct according to the EJB 3 spec, so I thought about a solution by using an @Interceptor.
public class ThreadedEntityManagerInterceptor { private final static ThreadLocal<EntityManager> THREADED_ENTITY_MANAGER = new ThreadLocal<EntityManager>(); public synchronized static void setEntityManager(EntityManager eMgr) { THREADED_ENTITY_MANAGER.set(eMgr); } @AroundInvoke public Object injectEntityManager(InvocationContext ctx) throws Exception { if(THREADED_ENTITY_MANAGER.get() == null) { return ctx.proceed(); } Class cls = ctx.getBean().getClass(); for(Field f : cls.getDeclaredFields()) { if(EntityManager.class.isAssignableFrom(f.getType())) { if(f.isAnnotationPresent(PersistenceContext.class)) continue; if(f.get(ctx.getBean()) == null) f.set(ctx.getBean(), THREADED_ENTITY_MANAGER.get()); } } return ctx.proceed(); } }
"setEntityManager" will be called by a servlet-filter before any EJB is referenced.
The filter passes in a EntityManager(PersistenceContext.EXTENDED) of a @Stateful session-bean.
This should work in my opinion.
But calling a method on a EntityManager which is setted by the above @Intercepter results in the following exception:
Caused by: java.lang.NullPointerException at org.jboss.ejb3.entity.ExtendedEntityManager.getPersistenceContext(ExtendedEntityManager.java:59) at org.jboss.ejb3.entity.ExtendedEntityManager.find(ExtendedEntityManager.java:114) at de.jitek.component.friendler.EntityServiceBean.findByPrimaryKey(EntityServiceBean.java:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:109) at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:168) at de.jitek.component.friendler.ThreadedEntityManagerInterceptor.injectEntityManager(ThreadedEntityManagerInterceptor.java:57) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:120) at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:62) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98) at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98) at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
Would be great if someone could explain why this happen and how to solve the problem.
Is it possible at all, what I am trying to do or is there already an existing solution of the LazyInitializationException (tapestry + ejb3) ?
Any help would very appreciated.
Regards,
Jan