4 Replies Latest reply on Feb 26, 2010 8:05 AM by kapitanpetko

    Passivation

    amontobin

      Hi Seam Users,


      I've read this chapter EJB Passivation and the ManagedEntityInterceptor
      As I understand it, it seems that seam is capable of passivate SMPC (EntityManager with @In) and
      reattach all instances loaded at activation.


      It works fine if the persistent object is directly a field of the stateful bean but not
      if i use a wrapper object for it.


      Is it a bug ? Or do i have to do the work manually ?


      Here is my example :
      When i first click on the submit button, the two needs are loaded and binded to current sesssion (I use Hibernate).
      I wait passivation.
      On the second click, activation takes place and the result is that one need is rebinded to the current session but not the one in the wrapper (wrapper is serializable)


      @Stateful
      @Name("testconversation1")
      @AutoCreate
      @Scope(ScopeType.CONVERSATION)
      public class TestConversation1Controller implements TestConversation1ControllerInterface {
           private static Logger logger = Logger.getLogger(TestConversation1Controller.class);
      
           @In
           EntityManager entityManager;
      
           private NeedImpl need;
           private Test1Wrapper wrapper;
      
           public String submit() {
                logger.info("submit");
                Seams.printConversationStackTrace();
                NeedManagerImpl manager = new NeedManagerImpl();
                manager.setEntityManager(entityManager);
                if (wrapper == null) {
                     wrapper = new Test1Wrapper();
                }
                if (wrapper.getNeed() == null) {
                     wrapper.setNeed(manager.getById(1));
                }
                if (need == null) {
                     need = manager.getById(2);
                }
                logger.info("Object :" + entityManager.contains(need));
                logger.info("Wrapper Object :" +entityManager.contains(wrapper.getNeed()));
                return null;
           }
      
           @Remove
           public void destroy() {
      
           }
      
           @PostConstruct
           public void postConstruct() {
                logger.info("postConstruct");
           }
      
           @PreDestroy
           public void preDestroy() {
                logger.info("preDestroy");
           }
      
           @PrePassivate
           public void prePassivate() {
                logger.info("prePassivate");
           }
      
           @PostActivate
           public void preActivate() {
                logger.info("preActivate");
           }
      }



      Any help would be appreciated,


      Thanks,


      Sebastien Boutte

        • 1. Re: Passivation
          amontobin

          I found this :


          in the block :



           if ( containsReferenceToEntityInstance(value) )
                            {
                               log.trace("Attempting to save wrapper for " + field + " (" + value + ")");
                               saveWrapper(target, component, field, dataModel, value);
                            }
                            else
                            {
                              // Don't we have to deal with wrapper containing persitent object ???
          
          log.trace("Clearing wrapper for " + field + " (" + value + ") as it isn't a entity reference");
                               clearWrapper(component, field);
                            }
          



          of the following code



          /**
           * @author Gavin King
           * @author Pete Muir
           * @author Norman Richards
           * @author Dan Allen
           */
          public class ManagedEntityWrapper
          {
          
             private static LogProvider log = Logging.getLogProvider(ManagedEntityWrapper.class);
             
             public void wrap(Object target, Component component) throws Exception
             {
                if ( !touchedContextsExist() )
                {
                   log.trace("No touched persistence contexts. Therefore, there are no entities in this conversation whose identities need to be preserved.");
                   return;
                }
                
                String oldCid = switchToConversationContextOfComponent(component);
                Class beanClass = target.getClass();
                for (; beanClass!=Object.class; beanClass=beanClass.getSuperclass())
                {
                   log.trace("Examining fields on " + beanClass);
                   for ( Field field: beanClass.getDeclaredFields() )
                   {
                      if ( !ignore(field) )
                      {
                         Object value = getFieldValue(target, field);
                         if (value!=null)
                         {
                            Object dataModel = null;
                            if ( DATA_MODEL.isInstance(value) )
                            {
                               dataModel = value;
                               value = getWrappedData(dataModel);
                            }
                            if ( containsReferenceToEntityInstance(value) )
                            {
                               log.trace("Attempting to save wrapper for " + field + " (" + value + ")");
                               saveWrapper(target, component, field, dataModel, value);
                            }
                            else
                            {
                              // **** 
          
          log.trace("Clearing wrapper for " + field + " (" + value + ") as it isn't a entity reference");
                               clearWrapper(component, field);
                            }
                         }
                         else
                         {
                            log.trace("Clearing wrapper for " + field + " as it is null");
                            clearWrapper(component, field);
                         }
                      }
                      else
                      {
                         log.trace("Ignoring field " + field + " as it is static, transient or annotated with @In");
                      }
                   }
                }
                restorePreviousConversationContextIfNecessary(oldCid);
             }
          




          • 2. Re: Passivation
            kapitanpetko

            The MEI doesn't check fields recursively. Check containsReferenceToEntityInstance for the details. Basically, it won't look inside your TestWrapper and will skip it since it's neither a Collection, nor an Entity.


            HTH

            • 3. Re: Passivation
              amontobin

              For me, the MEI should be enhance to take care of recursion and inspect all wrapper classes.


              Sebastien

              • 4. Re: Passivation
                kapitanpetko

                Sebastien Boutte wrote on Feb 26, 2010 08:01:


                For me, the MEI should be enhance to take care of recursion and inspect all wrapper classes.



                So file a JIRA, state your case, provide a patch and keep your fingers crossed :) But unless you can convince people that this is critical, it's unlikely to get into Seam 2.