0 Replies Latest reply on Mar 7, 2006 3:30 PM by jan zimmek

    Inheritence of PersistenceContext

    jan zimmek Newbie

      I 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