Uploaded image for project: 'WildFly'
  1. WildFly
  2. WFLY-2504

add lazy xpc inheritance to handle legacy case, remote client with UserTransaction fails on 2nd SFSB invocation when using extended persistence context

    XMLWordPrintable

Details

    • Enhancement
    • Resolution: Won't Do
    • Major
    • None
    • None
    • JPA / Hibernate
    • None

    Description

      AS5 allowed a remote client to instantiate a set of stateful session beans (e.g. SFSB1 + SFSB2) and then call the remote stateful session beans (SFSB1+SFSB2) in a started user transaction (UT1). Each of the stateful beans reference the same extended persistence context by name. In AS5, both stateful beans will share the same extended persistence unit context but on AS7/WF8, each bean has its own extended persistence unit context. Having both XPCS involved in the same user transaction, causes an (EJBException: JBAS011437: Found extended persistence context in SFSB invocation call stack but that cannot be used because the transaction already has a transactional context associated with it...) error to be thrown.

      On AS7/WF8, Allow the separate (remote) stateful beans to share the same persistence context.

      One approach might be to defer creation of the extended persistence context until the first invocation (need to verify that this is the right approach).

      Currently, we support shallow + deep extended persistence context inheritance. This will be a "lazy" variation of the deep XPC inheritance.

      Some of the AS5 code is pasted below for easy reference.

      public class ExtendedPersistenceContextPropagationInterceptor implements Interceptor
      {
         private static final Logger log = Logger.getLogger(ExtendedPersistenceContextPropagationInterceptor.class);
      
         public String getName()
         {
            return this.getClass().getName();
         }
      
         public Object invoke(Invocation invocation) throws Throwable
         {
            log.debug("++++ LongLivedSessionPropagationInterceptor");
            StatefulContainerInvocation ejb = (StatefulContainerInvocation) invocation;
            StatefulBeanContext ctx = (StatefulBeanContext) ejb.getBeanContext();
      
            Map<String, EntityManager> extendedPCs = ctx.getExtendedPersistenceContexts();
            if (extendedPCs == null || extendedPCs.size() == 0)
            {
               return invocation.invokeNext();
            }
      
            TransactionManager tm = TxUtil.getTransactionManager();
            if (tm.getTransaction() != null)
            {
               for (String kernelname : extendedPCs.keySet())
               {
                  EntityManager manager = extendedPCs.get(kernelname);
                  ManagedEntityManagerFactory factory = ManagedEntityManagerFactoryHelper.getManagedEntityManagerFactory(kernelname);
                  factory.registerExtendedWithTransaction(manager);
               }
            }
            return invocation.invokeNext();
         }
      }
      
      public class EJB3XPCResolver implements XPCResolver
      {
         private static final Logger log = Logger.getLogger(EJB3XPCResolver.class);
         /**
          * Query the current stateful bean contexts for the specified XPC.
          */
         public EntityManager getExtendedPersistenceContext(String kernelName)
         {
            StatefulBeanContext beanContext = StatefulBeanContext.currentBean.get();
      
            if (beanContext != null)
            {
               EntityManager em = null;
      
               em = beanContext.getExtendedPersistenceContext(kernelName);
               if (em != null) {
                  log.info("current SFSB has XPC with scoped pu name=" + kernelName + " on SFSB bean=" + beanContext.getContainer().getIdentifier() + beanContext.getId());
                  return em;
               }
               /**
                * Look for XPC in current bean set.
                */
               log.info("looking for existing XPC with scoped pu name=" + kernelName);
      
               List <StatefulBeanContext> beanContexts = StatefulBeanContext.currentBean.getList();
               for( StatefulBeanContext bc : beanContexts)
               {
                  em = bc.getExtendedPersistenceContext(kernelName);
                  if (em != null) {
                     log.info("found existing XPC with scoped pu name=" + kernelName + " on SFSB bean=" + bc.getContainer().getIdentifier() + bc.getId());
                     //  Propagate created XPC as required (7.6.2.1 Inheritance of Extended Persistence Context
                     beanContext.addExtendedPersistenceContext(kernelName, em);
                     return em;
                  }
                  log.info("XPC not found yet, scoped pu name=" + kernelName + " not in SFSB bean=" + bc.getContainer().getIdentifier() + bc.getId());
               }
            }
            log.info("XPC not found scoped, search done, pu name=" + kernelName);
            return null;
         }
      
         @Override
         public EntityManager createExtendedPersistenceContext(String kernelName)
         {
            StatefulBeanContext beanContext = StatefulBeanContext.currentBean.get();
      
            if (beanContext != null)
            {
               EntityManager em = null;
               ManagedEntityManagerFactory factory=
                  ((PersistenceUnitDeployment) PersistenceUnitRegistry.getPersistenceUnit(kernelName)).getManagedFactory();
               if (factory != null)
               {
                  em = factory.createEntityManager();
                  if (em != null)
                  {
                     beanContext.addExtendedPersistenceContext(factory.getKernelName(), em);
                     log.info("created new XPC with scoped pu name=" + kernelName + " on SFSB bean=" + beanContext.getContainer().getIdentifier() + beanContext.getId());
                     /**
                      * TODO:  Propagate created XPC as required (7.6.2.1 Inheritance of Extended Persistence Context
                      *
                      */
      
      //               List <StatefulBeanContext> beanContexts = StatefulBeanContext.currentBean.getList();
      //               for( StatefulBeanContext bc : beanContexts)
      //               {
      //                  bc.addExtendedPersistenceContext(kernelName, em);
      //               }
                  }
               }
      
               return em;
            }
            return null;
         }
      }
      
      public class ManagedEntityManagerFactoryHelper
      {
         public static ManagedEntityManagerFactory getManagedEntityManagerFactory(String kernelName)
         {
            PersistenceUnitDeployment pu = (PersistenceUnitDeployment) PersistenceUnitRegistry.getPersistenceUnit(kernelName);
            if(pu != null)
               return pu.getManagedFactory();
            return null;
         }
      }
      

      Attachments

        Activity

          People

            smarlow1@redhat.com Scott Marlow
            smarlow1@redhat.com Scott Marlow
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: