6 Replies Latest reply on Jul 10, 2006 1:28 PM by gavin.king

    Can't get a conversational stateful bean to work

    andrew.rw.robinson

      I have an administration bean that contains a list of users and then a dataTable that the user can select a user to edit or delete (or click an add button on the page to create a new user).

      I wanted to start the conversation on add/edit. The problem I am having is that my methods are never called when the bean is in the conversation state.

      Bean:

      @Stateful
      @Name("userAdmin")
      @Interceptors(SeamInterceptor.class)
      @Scope(ScopeType.CONVERSATION)
      @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
      @RolesAllowed(Roles.USER_ADMIN)
      public class UserAdminAction
       extends FacesBean
       implements UserAdmin
      {
       @In(create=true)
       private EntityManager entityManager;
       private List<User> users;
      
       @Out(required=false) @Valid
       private User editingUser;
      
       /**
       * @return Returns the editingUser.
       */
       public User getEditingUser()
       {
       return this.editingUser;
       }
      
       /**
       * @see org.bethanyefree.beans.admin.UserAdmin#setEditingUser(org.bethanyefree.data.User)
       */
       public void setEditingUser(User editingUser)
       {
       this.editingUser = editingUser;
       }
      
       @Begin(join=true, ifOutcome="edit.user")
       public String editUser()
       {
       if (editingUser == null)
       return null;
      
       userPwordChanged = false;
       initUserData();
       return "edit.user";
       }
      
       @Begin(join=true)
       @TransactionAttribute(TransactionAttributeType.REQUIRED)
       public String onLoad()
       {
       if (load())
       return null;
       return "failed";
       }
       ...
      


      Pages.xhtml:
      <pages>
       <page view-id="/administration/users/index.xhtml" action="#{userAdmin.onLoad}" />
       <page view-id="/administration/users/details.xhtml" action="#{userAdmin.checkEditing}" />
      </pages>


      index.xhtml:
      <t:dataTable value="#{userAdmin.users}"
       var="_user">
       ...
       <t:column>
       <t:commandLink
       action="#{userAdmin.editUser}"
       styleClass="imageButton"
       rendered="#{!_user.system}">
       <b:imageButton url="edit" />
       <seam:conversationPropagation type="join"/>
       <t:updateActionListener property="#{userAdmin.editingUser}"
       value="#{_user}"/>
       </t:commandLink>
       </t:column>
       ...
      


      When I click the edit button nothing happens (setEditingUser and editUser methods are not called). If I change the bean's scope from CONVERSATION to SESSION everything works fine. I've tried just about everything I can think of:

      * @Begin on the onLoad, begin not on the onload
      * seam:link instead of commandLink
      * seam:link instead of commandLink with propagate = begin and @DataModel on the users and @DataModelSelection on the editingUser
      * Begin on the setEditingUser

      And a bunch of other permutations involving the propagateConversation settings in both the seam link and a param to command link, using or not using begin, using updateActionListener vs. data model and data model selection, using the data model's name vs. bean.users method of referencing.

      I have had no luck with any of these permutations. The only way I got it to work is using a SESSION bean (which is not what I am after).

      I am obviously missing something, any ideas on what?

      Thanks,
      Andrew

      Using Seam 1.0.1

        • 1. Re: Can't get a conversational stateful bean to work
          andrew.rw.robinson

          Sorry, forgot to mention that clicking on the link two times in a row works in that navigation works, but the user is the wrong user (it ends up always being the first user in the data table)

          • 2. Re: Can't get a conversational stateful bean to work
            andrew.rw.robinson

            Here is some more information with seam's logging turned up:

            18:31:10,020 DEBUG [Lifecycle] destroying conversation context
            18:31:10,020 DEBUG [Contexts] destroying: userAdminPword
            18:31:10,020 DEBUG [Contexts] destroying: facesMessages
            18:31:10,020 DEBUG [Contexts] destroying: entityManager
            18:31:10,020 DEBUG [ManagedPersistenceContext] destroying seam managed persistence context for persistence unit: java:/bethanyEntityManagerFactory
            18:31:10,023 DEBUG [Contexts] destroying: userAdmin
            18:31:10,024 DEBUG [SeamInterceptor] not intercepted: destroy
            18:31:10,036 DEBUG [Contexts] destroying: currentUser
            18:31:10,036 DEBUG [Lifecycle] flushing server-side conversation context
            


            For some reason, the @Begin(join=true) on my "public String onLoad()" method seems to be being ignored. So when I click a link, my list is no longer around as the conversation is dead.

            Will keep looking, but not sure why Seam is ignoring the @Begin

            • 3. Re: Can't get a conversational stateful bean to work
              andrew.rw.robinson

              I got it to work by starting the conversation with a factory method instead of just relying on the page load method.

              I made the following adjustments:

              @Out(scope=ScopeType.CONVERSATION, value="adminUserList", required=false)
               private List<User> users;
              
               @Out(required=false, scope=ScopeType.CONVERSATION) @Valid
               private User editingUser;
              
              ...
               @Begin(join=true)
               @Factory("adminUserList")
               public String onLoad() ...
              


              And in the xhtml:
              <t:dataTable
               value="#{adminUserList}"
               var="_user" ...


              That got me past my problem, but I'd still like to know what I am missing in terms of why the load method called from the pages.xml didn't cause a conversation to be started but the factory method did.


              • 4. Re: Can't get a conversational stateful bean to work

                Is onLoad() returning null in the cases where @Begin is failing? The conversation interceptor interprets null as a failure condition.

                • 5. Re: Can't get a conversational stateful bean to work
                  andrew.rw.robinson

                  Oh, that would explain it, thanks.

                  Yes it is returning null, as I thought that was the appropriate result in the pages.xml if you don't want to change the navigation. If I return a non-null result, the navigation handler will be invoked. Is there a happy medium (like Outcome.REDISPLAY)?

                  • 6. Re: Can't get a conversational stateful bean to work
                    gavin.king

                    Any non-null result that does not have an explicit navigation rule defined is ignored by the navigation handler" So just return "success".