6 Replies Latest reply on Oct 6, 2010 11:29 PM by rvaneperen

    Problem with managed bean creation

    rvaneperen

      I have been using Seam for a while, and this should be really easy, but I can't figure out what's going on.  I begin on a page with a data table containing links in each row.  That bean is Conversation scoped and the pages.xml contains


      <page xmlns="http://jboss.com/products/seam/pages"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.1.xsd"
            login-required="true">
        <begin-conversation join="true" 
                            flush-mode="MANUAL" />
        <action execute="#{userRoleAdmin.init}" 
                on-postback="false" />
      </page>




      I click this link (below), and proceed to the new view.



      <s:link view="/UserRoleEdit.xhtml"
              value="#{messages.global_edit}"
              propagation="none"
              id="userEdit" >
        <f:param name="userRoleId"
                 value="#{userRole.id}" />
      </s:link>



      Here is the pages.xml for the new view


      <page xmlns="http://jboss.com/products/seam/pages"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.1.xsd"
            no-conversation-view-id="/userList.xhtml"
            login-required="true">
        <begin-conversation join="true"
                            flush-mode="MANUAL" />
        <action execute="#{userRoleEdit.init}" 
                on-postback="false" />
        <navigation from-action="#{userRoleAdmin.storeUserRole}">
          <rule if-outcome="added">
            <redirect view-id="/UserRoleEdit.xhtml" />
          </rule>
          <rule if-outcome="updated">
            <redirect view-id="/UserRoleEdit.xhtml" />
          </rule>
          <rule if-outcome="removed">
            <redirect view-id="/UserRoleAdmin.xhtml" />
          </rule>
        </navigation>
      </page>



      The init method is called which sets two properties on the bean - it fetches the UserRole from the Id parameter and initializes a list of options for the view. See below that userRole and availableAuths are populated (not null) as are Seam injected objects. I noticed in the debugger, that the object being managed at the point the init method completes is as follows (notice the id of the UserRoleEditBean)


      this  UserRoleEditBean (id=259)
             availableAuths           ArrayList<E>  (id=274)     
             entityManager            EntityManagerProxy  (id=264)     
             facesMessages            FacesMessages  (id=265)     
             selectedAuths            null     
             userAuthNameConverter    UserAuthorizationNameEnumConverter  (id=266)     
             userRole                 UserRole  (id=271)     
             userRoleId               "251" (id=267)     
             userRoleQuery            UserRoleQuery_$$_javassist_seam_7  (id=268)



      The next breakpoint is in the getter for the availableAuths list.  When I hit that (which appears to be in the RenderView phase), both the userRole and availableAuths objects are null.  And notice below that I now have a new object (a proxy)





      this     UserRoleEditBean_$$_javassist_seam_6  (id=302)     
           availableAuths     null     
           entityManager     null     
           facesMessages     null     
           handler     JavaBeanInterceptor  (id=303)     
           selectedAuths     null     
           userAuthNameConverter     UserAuthorizationNameEnumConverter  (id=304)     
           userRole     null     
           userRoleId     null     
           userRoleQuery     null



           
      So why the new object, and why is everything null after being initialized in a Conversation scoped bean?


      Here is the backing bean (I'd be glad to supply any more code you might need):



      @Name( "userRoleAdmin" )
      @Scope( ScopeType.CONVERSATION )
      @AutoCreate
      public class UserRoleAdminBean implements Serializable
      {
      
          /**
           * For serialization.
           */
          private static final long serialVersionUID = 2400901393261379751L;
      
          /**
           * Used to perform the search based on the role name.
           */
          @In
          private UserRoleSearchService userRoleSearchService;
      
          /**
           * The list of users as a result of searching.
           */
          @DataModel
          private List<UserRole> userRoles;
      
          /**
           * Used to search for authorizations.
           */
          private String roleName;
      
          /**
           * Used to indicate whether the search should be exact or approximate.
           */
          private boolean searchExact;
      
          /**
           * Tracks the current page for pagination of the authSearchResult table.
           */
          private int roleSearchResultPage = 1;
      
          /**
           * Initializes the bean once upon creation.
           */
          public void init()
          {
              this.roleName = "";
              this.searchExact = false;
              this.userRoles = new ArrayList<UserRole>();
          }
      
          /**
           * Performs a search for User Roles based on the search criteria selected by the user.
           */
          public void searchRoles()
          {
              this.userRoles = this.userRoleSearchService.searchUserRoles( this.roleName, this.searchExact );
          }
      
          /**
           * Resets the authorization name used in the search. 
           */
          public void resetRoles()
          {
              this.roleName = "";
          }
      
          public List<UserRole> getUserRoles()
          {
              return this.userRoles;
          }
      
          public String getRoleName()
          {
              return this.roleName;
          }
      
          public void setRoleName( final String pRoleName )
          {
              this.roleName = pRoleName;
          }
      
          public final int getRoleSearchResultPage()
          {
              return this.roleSearchResultPage;
          }
      
          public final void setRoleSearchResultPage( final int pRoleSearchResultPage )
          {
              this.roleSearchResultPage = pRoleSearchResultPage;
          }
      
          public final boolean isSearchExact()
          {
              return this.searchExact;
          }
      
          public final void setSearchExact( final boolean pSearchExact )
          {
              this.searchExact = pSearchExact;
          }
      }




        • 1. Re: Problem with managed bean creation
          lvdberg

          Hi,


          Not clear what the answer is yet, but have you tried putting the create annotation on the init, because you just initialize it once. Does that make any difference and send the code for the userRoleEdit, that will be helpful,


          Leo


          • 2. Re: Problem with managed bean creation
            rvaneperen

            Thanks Leo!


            First of all, I meant to post the userRoleEdit bean, but posted the wrong one, I have included it below.  And yes, last night, I did try changing the code to use @Create instead of the action execute - no luck.  Also, I tried making the admin and edit beans session, but no change.





            /**
             * Backing bean for user role add/change/delete.
             */
            @Name( "userRoleEdit" )
            @Scope( ScopeType.CONVERSATION )
            @AutoCreate
            public class UserRoleEditBean implements Serializable
            {
            
                /**
                 * For serialization.
                 */
                private static final long serialVersionUID = 2745848892268491219L;
            
                /**
                 * The user object being managed.
                 */
                @In( required = false )
                private UserRole userRole;
                
                /**
                 * The seam managed entity manager.
                 */
                @In
                private EntityManager entityManager;
                
                /**
                 * Used for user-related queries.
                 */
                @In
                private UserRoleQuery userRoleQuery;
                
                /**
                 * The seam managed JSF messages
                 */
                @In
                private FacesMessages facesMessages;
                
                /**
                 * The id of the user to be updated or deleted.  Will be null when adding a new role.
                 */
                @RequestParameter
                private String userRoleId;
            
                /**
                 * The list of available authorizations - which is the complete list of auths minus those already associated with the role.
                 */
                private List<UserAuthorizationNameEnum> availableAuths = null;
            
                /**
                 * The list of authorizations already associated with the role.
                 */
                private List<UserAuthorizationNameEnum> selectedAuths = null;
                
                /**
                 * Used to convert between the enumeration and the richfaces list shuffle component.
                 */
                private UserAuthorizationNameEnumConverter userAuthNameConverter = new UserAuthorizationNameEnumConverter();
            
                /**
                 * Initializes the bean for first use.
                 */
                public void init()
                {
                    if ( StringUtils.isNotBlank( this.userRoleId ) )
                    {
                        this.userRole = this.entityManager.find( UserRole.class, new Long( this.userRoleId ) );
                    }
                    else
                    {
                        this.userRole = new UserRole();
                    }
                    initializeAuths();
                }
            
                /**
                 * Initializes the list of available and selected authorizations.
                 */
                private void initializeAuths()
                {
                    this.availableAuths = new ArrayList<UserAuthorizationNameEnum>( Arrays.asList( UserAuthorizationNameEnum.values() ) );
                }
            
                /**
                 * Inserts for updates the user being managed.
                 * 
                 * @return the outcome.
                 */
                public String storeUserRole()
                {
                    String outcome;
                    if ( this.userRole.getId() == null )
                    {
                        if ( this.userRoleQuery.fetchUserRoleByName( this.userRole.getName() ) != null )
                        {
                            this.facesMessages.addFromResourceBundle( Severity.ERROR, "user_userRoleNameExists", this.userRole.getName() );
                            return null;
                        }
                        outcome = FacesUtil.ADDED;
                    }
                    else
                    {
                        outcome = FacesUtil.UPDATED;
                    }
                    this.entityManager.persist( this.userRole );
                    this.entityManager.flush();
                    this.facesMessages.addFromResourceBundle( "user_userRoleOutcomeSuccessful", this.userRole.getName(), outcome );
                    this.userRole = new UserRole();
                    return outcome;
                }
            
                /**
                 * Deletes the user being managed.
                 * 
                 * @return the outcome.
                 */
                public String deleteUserRole()
                {
                    String outcome = FacesUtil.REMOVED;
                    this.entityManager.remove( this.userRole );
                    this.entityManager.flush();
                    this.facesMessages.addFromResourceBundle( "user_userRoleOutcomeSuccessful", this.userRole.getName(), outcome );
                    this.userRole = new UserRole();
                    return outcome;
                }
            
                public final List<UserAuthorizationNameEnum> getAvailableAuths()
                {
                    return this.availableAuths;
                }
            
                public final List<UserAuthorizationNameEnum> getSelectedAuths()
                {
                    return this.selectedAuths;
                }
            
                public final void setAvailableAuths( final List<UserAuthorizationNameEnum> pAvailableAuths )
                {
                    this.availableAuths = pAvailableAuths;
                }
            
                public final void setSelectedAuths( final List<UserAuthorizationNameEnum> pSelectedAuths )
                {
                    this.selectedAuths = pSelectedAuths;
                }
            
                public final UserAuthorizationNameEnumConverter getUserAuthNameConverter()
                {
                    return this.userAuthNameConverter;
                }
            
                public final void setUserAuthNameConverter( UserAuthorizationNameEnumConverter pUserAuthNameConverter )
                {
                    this.userAuthNameConverter = pUserAuthNameConverter;
                }
            
                public final UserRole getUserRole()
                {
                    return this.userRole;
                }
            
                public final void setUserRole( final UserRole pUserRole )
                {
                    this.userRole = pUserRole;
                }
            }



            I look forward to any other suggestions you might have.

            • 3. Re: Problem with managed bean creation
              lvdberg

              Hi,


              I always a bit confused when inits and its calls are scattered over the code/xml. The thing I do in these cases is use the excellent paramatrized calls of EL. So instead of complex request parameter in- and outjecting I just do something like:






              <s:link action="#{userRoleEdit.init(userRole.id)}"
                      value="#{messages.global_edit}" />
              




              This construct is much clearer and it is highly maintainable. You then adapt the init method and return a String, something like init, which you add in you navigation rule.


              Never fails.


              Leo

              • 4. Re: Problem with managed bean creation
                rvaneperen

                I have actually used that pattern before, Thanks for the reminder.  I made that change, but no difference, I still get the actual object when init() is executed, and then a proxy when the getters are called - on which the initialized values are now null.  Sorry to be a pest here, but I've just never seen this before in something that appears so simple.


                However, for what it's worth, I dug into the proxy object in the debugger at a point after init has run and it is now accessing the getters and found the wrapped object inside.  It has the availableAuths, selectedAuths lists and the converter set, but no other properties.  Curiously, these are the three properties used in the RichFaces ListShuffle component on the page. I set breakpoints on the getters for available, selected auths, the converter, and the userRole object.  The first three I hit, but getUserRole is never hit.  Again, mysteriously only the getters for the list shuffle component attributes.  I'm now wondering if this is some kind of RichFaces related issue except RichFaces doesn't manage proxies, only Seam/Hibernate etc (as far as I know).


                Just in case it helps, I'm including the debug parameters and the code for the page.



                this     UserRoleEditBean_$$_javassist_seam_6  (id=12816)     
                     availableAuths     null     
                     entityManager     null     
                     facesMessages     null     
                     handler     JavaBeanInterceptor  (id=12815)     
                          bean     UserRoleEditBean  (id=12804)     
                               availableAuths     ArrayList<E>  (id=12948)     
                               entityManager     null     
                               facesMessages     null     
                               selectedAuths     ArrayList<E>  (id=12949)     
                               userAuthNameConverter     UserAuthorizationNameEnumConverter  (id=12860)     
                               userRole     null     
                               userRoleQuery     null     
                          beanClass     Class<T> (com.bedrock.user.web.bean.UserRoleEditBean) (id=12737)     
                          component     Component  (id=12891)     
                          componentName     "userRoleEdit" (id=12894)     
                          dirty     true     
                          isSeamComponent     true     
                          type     InterceptorType  (id=12895)     
                          userInterceptors     ArrayList<E>  (id=12897)     
                     selectedAuths     null     
                     userAuthNameConverter     UserAuthorizationNameEnumConverter  (id=12890)     
                     userRole     null     
                     userRoleQuery     null






                <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                                xmlns:s="http://jboss.com/products/seam/taglib"
                                xmlns:ui="http://java.sun.com/jsf/facelets"
                                xmlns:f="http://java.sun.com/jsf/core"
                                xmlns:h="http://java.sun.com/jsf/html"
                                xmlns:a="http://richfaces.org/a4j"
                                xmlns:r="http://richfaces.org/rich"
                                template="layout/template.xhtml">
                
                  <ui:define name="body">
                    <h:form id="userRole" styleClass="edit">
                      <r:panel>
                        <f:facet name="header">#{userRole.id == null ? 'Add' : 'Edit'} #{messages.user_role}</f:facet>
                        <s:decorate id="roleName" 
                                    template="layout/edit.xhtml">
                          <ui:define name="label">#{messages.global_name}</ui:define>
                          <h:inputText id="roleName"
                                       required="true"
                                       value="#{userRole.name}" />
                        </s:decorate>
                        <s:decorate id="description" 
                                    template="layout/edit.xhtml">
                          <ui:define name="label">#{messages.global_description}</ui:define>
                          <h:inputText id="description"
                                       required="false"
                                       value="#{userRole.description}" />
                        </s:decorate>
                        <div style="clear:both">
                          <span class="required">*</span>
                          required fields
                        </div>
                        <r:listShuttle id="availableAuthsId" 
                                       sourceValue="#{userRoleEdit.availableAuths}" 
                                       targetValue="#{userRoleEdit.selectedAuths}"  
                                       sourceRequired = "true"
                                       targetRequired = "false" 
                                       var="item" 
                                       converter="#{userRoleEdit.userAuthNameConverter}"
                                       sourceCaptionLabel="Available Authorizations" 
                                       targetCaptionLabel="Selected Authorizations">
                          <r:column>
                            <h:outputText value="#{item.displayValue}" />
                          </r:column>
                        </r:listShuttle>
                      </r:panel>
                      <div class="actionButtons">
                        <h:commandButton id="save"
                                         value="#{messages.global_save}"
                                         action="#{userRoleEdit.storeUserRole}"/>
                        <h:commandButton id="delete"
                                         value="#{messages.global_delete}"
                                         action="#{userRoleEdit.removeUserRole}"
                                         immediate="true"
                                         rendered="#{userRole.id != null}" />
                        <s:button id="cancelEdit"
                                  value="#{messages.global_cancel}"
                                  propagation="end"
                                  view="/UserRoleAdmin.xhtml" />
                      </div>
                    </h:form>
                  </ui:define>
                </ui:composition>





                • 5. Re: Problem with managed bean creation
                  rvaneperen

                  By the way, as far as versions of things, I'm currently on JBoss 4.2.3.GA and for seam/jsf and other related jars, I'm using those contained in the seam-2.2.0.GA distribution.

                  • 6. Re: Problem with managed bean creation
                    rvaneperen

                    One more item. I omitted the @Out on the userRole property of the UserRoleEditBean.  I added that and I now see the userRole info on the page since that was outed after the init method executed, but still no difference - including the lack of hitting a breakpoint in the getUserRole() method - so how did the property values show on the page?