14 Replies Latest reply on May 5, 2009 10:27 AM by Greg Fasnacht

    ListShuttle not displaying sourceValue and targetValue lists

    Greg Fasnacht Newbie

      I'm attempting to use a listShuttle to display a list of available users and a list of already selected users. The listShuttle lives inside a modalPanel, and when I call the modalPanel I see the listShuttle, but both sides are empty. With my current test data I'd expect to see 3 users displayed in the source side and none in the target side. I've noticed that a co-worker's similar code works correctly on her development system, but not on mine. I'm wondering if I'm missing a dependency that's preventing the source and target lists from displaying. FYI...I have log.debug() statements in my converter class that I'm not seeing, so I'm wondering if the converter isn't actually being called. Any help would be greatly appreciated! (deadline's tomorrow :-(

      Here's my .xhtml code:

       <ui:define name="modalPanel">
       <rich:modalPanel id="panelSharedUser" width="650" height="250" rendered="true">
       <f:facet name="header">
       <h:panelGroup>
       <h:outputText value="Share "></h:outputText>
       <h:outputText value="#{selectedVersion.name}"/>
       </h:panelGroup>
       </f:facet>
       <f:facet name="controls">
       <h:panelGroup>
       <h:graphicImage value="/images/btn_close_sm.gif" styleClass="hidelink" id="hidelink"/>
       <rich:componentControl for="panelSharedUser" attachTo="hidelink" operation="hide" event="onclick"/>
       </h:panelGroup>
       </f:facet>
       <rich:listShuttle
       id="listShuttleShared" orderControlsVisible="false"
       fastOrderControlsVisible="false" fastMoveControlsVisible="false"
       sourceCaptionLabel="Available Users" targetCaptionLabel="Shared Users"
       moveControlsVerticalAlign="middle"
       sourceValue="#{userList.freeItems}"
       targetValue="#{userList.items}"
       var="items" converter="userConverter"
       columnClasses=" body, pointer" sourceListWidth="250px"
       targetListWidth="250px">
       <rich:column>
       <h:outputText value="#{items.name}"/>
       </rich:column>
       </rich:listShuttle>
       <h:outputText value="This panel is called using Component Control Component"></h:outputText>
       <br/>
       <h:outputText value="Closure link (X) works also through Component Control"></h:outputText>
       </rich:modalPanel>
       </ui:define>
      


      and here's the converter code:
      import org.apache.log4j.Logger;
      import javax.faces.component.UIComponent;
      import javax.faces.context.FacesContext;
      
      /**
       * Classification: Converter
       * <dl>
       * <dt>Definition + Responsibilities</dt>
       * <dd>UserConverter is used in Lists that populate menus, dropdown lists, and list shuttles
       * UI components. It is a standard JSF converter that converts between HTML String
       * attributes to Objects and back.</dd>
       * <p />
       * <dt>Constraints</dt>
       * <dd>None.</dd>
       * <p />
       * <dt>Composition</dt>
       * <dd>UserConverter has no properties and contains only methods necessary to convert
       * HTML String attributes to Objects and back.</dd>
       * <p />
       * <dt>Design Use Case Version</dt>
       * <dd>1.0</dd>
       * </dl>
       */
      
      
      public class UserConverter implements javax.faces.convert.Converter
      {
       private static Logger log = Logger.getLogger(UserConverter.class);
      
       public Object getAsObject(FacesContext context, UIComponent component,
       String value) {
      
       int index = value.indexOf(':');
       log.debug("getAsObject(): SimpleUser("+value.substring(0, index)+","+value.substring(index + 1)+")");
       return new SimpleUser(value.substring(0, index), value.substring(index + 1));
       }
      
       public String getAsString(FacesContext context, UIComponent component,
       Object value) {
      
       SimpleUser optionItem = (SimpleUser) value;
       log.debug("getAsString(): returning '"+optionItem.getName() + ":" + optionItem.getId()+"'");
       return optionItem.getName() + ":" + optionItem.getId();
       }
      
      }


      The user objects are being developed and stored in another class, UserList:
      import java.util.ArrayList;
      import java.util.List;
      import javax.faces.context.FacesContext;
      import mil.ekm.afewcis2.admin.LookupConstants;
      import mil.ekm.afewcis2.ejb.UserControllerLocal;
      import mil.ekm.afewcis2.ejb.factory.ControllerFactory;
      import mil.ekm.afewcis2.vo.TopicVersion;
      import mil.ekm.afewcis2.vo.User;
      import org.apache.log4j.Logger;
      
      /**
       * Classification: Utility
       * <dl>
       * <dt>Definition + Responsibilities</dt>
       * <dd>UserList is a simplified construct to hold two Lists of SimpleUsers. It is used
       * to populate menus, dropdown lists, and list shuttles of Users where only the name
       * and/or id properties are needed, facilitating use by the noted UI components.</dd>
       * <p />
       * <dt>Constraints</dt>
       * <dd>Used by {@link mil.ekm.afewcis2.web.TopicList_Backing}, and accesses the
       * EJB controller placed on the application session by the TopicList_Backing.</dd>
       * <p />
       * <dt>Composition</dt>
       * <dd>Each UserList contains a reference to the UserController, and
       * two Lists of SimpleUsers for use in displaying a PickList component. One List
       * contains the SimpleUsers installed on the given Platform, the other List contains
       * all other SimpleUsers, i.e., available to add.</dd>
       * <p />
       * <dt>Design Use Case Version</dt>
       * <dd>1.0</dd>
       * </dl>
       */
      public class UserList {
       private static Logger log = Logger.getLogger(UserList.class);
       private UserControllerLocal userController = (UserControllerLocal) FacesContext
       .getCurrentInstance().getExternalContext().getSessionMap().get(LookupConstants.CONTROLLER);
       private List<SimpleUser> items = new ArrayList<SimpleUser>();
       private List<SimpleUser> freeItems = new ArrayList<SimpleUser>();
      
      
       public UserList(){}
       /**
       * Initialize the SystemList by populating both of its List properties and creating
       * SimpleUser objects from a List of SystemTopics.
       * @param selectedVersion - the PlatformTopic, which determines which SimpleUsers are
       * available and which are already installed on that Platform.
       */
       public UserList(TopicVersion selectedVersion)
       {
       List<User> sUsers = new ArrayList<User>();
       List<User> fUsers = new ArrayList<User>();
      
       log.debug("UserList(): Entered constructor");
       if ((selectedVersion == null) || (selectedVersion.getTopic() != null))
       {
       if (userController == null)
       {
       try
       {
       log.debug("UserList(): userController was null, getting new instance");
       userController = ControllerFactory.getUserController();
       }
       catch (Exception e)
       {
       log.error("UserList(): Unable to get UserController.", e);
       }
       }
       if (userController != null)
       {
       log.debug("UserList(): getting shared users from topic");
       sUsers = selectedVersion.getTopic().getSharedAccess();
       if ((sUsers != null) && (sUsers.size() > 0))
       {
       fUsers = userController.getAvailableUsers(sUsers);
       log.debug("UserList(): got "+fUsers.size()+" available users");
       for (User user : sUsers)
       {
       this.items.add(new SimpleUser(user.getFormattedName(), user.getId().toString() ));
       }
       log.debug("UserList(): added " + this.items.size() + " shared users");
       }
       else
       {
       fUsers = userController.getAllUsers();
       log.debug("UserList(): got all "+fUsers.size()+" available users");
       }
      
       if ((fUsers != null) && (fUsers.size() > 0))
       {
       fUsers.remove(selectedVersion.getTopic().getOwner());
       for (User user : fUsers)
       {
       this.freeItems.add(new SimpleUser(user.getFormattedName(), user.getId().toString() ));
       }
       log.debug("UserList(): added " + this.freeItems.size() + " free users");
       }
       }
       else
       {
       log.error("UserList(): userController is null");
       }
       }
       log.debug("UserList(): leaving constructor. items size = "+this.items.size()+", freeItems size = "+this.freeItems.size());
       }
      
       public List<SimpleUser> getItems()
       {
       log.debug("getItems(): returning "+items.size()+" SimpleUser objects");
       return items;
       }
      
       public void setItems(List<SimpleUser> items)
       {
       log.debug("setItems(): setting "+items.size()+" SimpleUser objects");
       this.items = items;
       }
      
       public List<SimpleUser> getFreeItems()
       {
       log.debug("getFreeItems(): returning "+freeItems.size()+" SimpleUser objects");
       return freeItems;
       }
      
       public void setFreeItems(List<SimpleUser> freeItems)
       {
       log.debug("setFreeItems(): setting "+freeItems.size()+" SimpleUser objects");
       this.freeItems = freeItems;
       }
      
      }
      


      Thanks in advance for taking a look at this! I'm a newbie so I'm having a very difficult time troubleshooting...

      Greg

        • 1. Re: ListShuttle not displaying sourceValue and targetValue l
          Nick Belaevski Master

          Hello Greg,

          Have you registered converter in faces-config.xml? Do you see getFreeItems()/getItems() methods being called and returning right number of items?

          • 2. Re: ListShuttle not displaying sourceValue and targetValue l
            Greg Fasnacht Newbie

            Hi Nick,

            Yes, I'm seeing the log.debug statements being called...here's the log output from page instantiation (where the UserList constructor is called to set up the lists) through opening of the modalPanel containing the ListShuttle (the last 4 lines...each method call is made twice?):

            10:24:31,836 DEBUG [UserList] UserList(): Entered constructor
            10:24:31,836 DEBUG [UserList] UserList(): userController was null, getting new instance
            10:24:31,836 DEBUG [UserList] UserList(): getting shared users from topic
            10:24:31,836 DEBUG [UserList] UserList(): got all 4 available users
            10:24:31,868 DEBUG [SimpleUser] setName(): setting name 'Foonman, Peter T'
            10:24:31,868 DEBUG [SimpleUser] setId(): setting id '3'
            10:24:31,868 DEBUG [SimpleUser] setName(): setting name 'Goodman, Anita'
            10:24:31,868 DEBUG [SimpleUser] setId(): setting id '4'
            10:24:31,868 DEBUG [SimpleUser] setName(): setting name 'Knucklefutz, Harvey'
            10:24:31,868 DEBUG [SimpleUser] setId(): setting id '2'
            10:24:31,868 DEBUG [UserList] UserList(): added 3 free users
            10:24:31,868 DEBUG [UserList] UserList(): leaving constructor. items size = 0, freeItems size = 3
            10:24:31,868 DEBUG [UserList] getFreeItems(): returning 3 SimpleUser objects
            10:24:31,868 DEBUG [UserList] getItems(): returning 0 SimpleUser objects
            10:24:39,899 DEBUG [UserList] getFreeItems(): returning 3 SimpleUser objects
            10:24:39,899 DEBUG [UserList] getItems(): returning 0 SimpleUser objects
            10:24:39,930 DEBUG [UserList] getFreeItems(): returning 3 SimpleUser objects
            10:24:39,930 DEBUG [UserList] getItems(): returning 0 SimpleUser objects


            I'd expect to see the converter's log.debug statements next...

            • 3. Re: ListShuttle not displaying sourceValue and targetValue l
              Greg Fasnacht Newbie

              Oops, forgot to answer the "is the converter registered" question...yep! Here's the entry from faces-config:


              <converter-id>userConverter</converter-id>
              <converter-class>mil.ekm.afewcis2.web.util.UserConverter</converter-class>

              • 4. Re: ListShuttle not displaying sourceValue and targetValue l
                Nick Belaevski Master

                Hello,

                I cannot reproduce the problem neither with 3.3.0.GA nor with 3.3.1-snapshot. Can you please prepare small demo project showing the issue (you can put it to sendspace or somewhere else)?

                • 5. Re: ListShuttle not displaying sourceValue and targetValue l
                  Greg Fasnacht Newbie

                  I'll try, but it will be tough (and not quick). Code depends on a lot of background data that I'll have to fake...might be tough/impossible to replicate and still be meaningful.

                  • 6. Re: ListShuttle not displaying sourceValue and targetValue l
                    Greg Fasnacht Newbie

                    I'm still guessing that there's a problem with my build development...I verified that the similar code my co-worker wrote (that's not working in my development environment) is working in hers. I may have her try to use my code and see if it works in her environment...if it does that's a pretty good indication that something's wrong with my environment. I'll let you know what happens.

                    • 7. Re: ListShuttle not displaying sourceValue and targetValue l
                      Greg Fasnacht Newbie

                      Nick,

                      Problem found! Turns out it was an issue with the background data. Although my users were populating in the background list correctly, another table had changed that apparently kept my seemingly unrelated data from being converted. I don't even pretend to understand why...

                      Thanks for looking at the problem!

                      • 8. Re: ListShuttle not displaying sourceValue and targetValue l
                        Greg Fasnacht Newbie

                        Unfortunately, it looks like I need to reopen this topic. There appears to be a conflict between the modalPanel and the ListShuttle inside of it. The code I posted first doesn't populate the lists of users (converter isn't called). However, if I pull the listShuttle code out of the modalPanel and display it directly on the page then the lists of users get populated (converter is called).

                        Not that I want to muddy the waters further, but I've noticed when I call another page that contains a listShuttle component (contents displayed correctly) then I come back to my page, then when I open the modalPanel on my page the converter gets called and my user lists are populated. Very wierd!

                        Do you have any sample code available showing how to properly use a listShuttle inside a modalPanel? I see from the forum that others have had difficulty with this in the past, but not the exact same problem (and those were supposedly corrected in 3.3.0GA.

                        • 9. Re: ListShuttle not displaying sourceValue and targetValue l
                          Nick Belaevski Master

                          Greg,

                          Modal panel should not influence rich:listShuttle in such way. Can that be a problem with "userList" bean incorrectly passed into template?

                          • 10. Re: ListShuttle not displaying sourceValue and targetValue l
                            Greg Fasnacht Newbie

                            Sorry Nick, I'm still a newbie to JSF and I don't understand the template reference...

                            • 11. Re: ListShuttle not displaying sourceValue and targetValue l
                              Nick Belaevski Master

                              I wanted to ask if "userList" is declared in faces-config.xml or it is passed into template that contains modalPanel, e.g. using ui:param? BTW, what would you see for the following case:

                              <rich:listShuttle
                               id="listShuttleShared" orderControlsVisible="false"
                               fastOrderControlsVisible="false" fastMoveControlsVisible="false"
                               sourceCaptionLabel="Available Users" targetCaptionLabel="Shared Users"
                               moveControlsVerticalAlign="middle"
                               sourceValue="#{userList.freeItems}"
                               targetValue="#{userList.items}"
                               var="items" converter="userConverter"
                               columnClasses=" body, pointer" sourceListWidth="250px"
                               targetListWidth="250px">
                               <rich:column>
                               <h:outputText value="#{items.name}"/>
                               </rich:column>
                               </rich:listShuttle>
                               <br />#{userList.freeItems}<br />#{userList.items}
                              is items number correct?

                              • 12. Re: ListShuttle not displaying sourceValue and targetValue l
                                Greg Fasnacht Newbie

                                More info: I realized the modalPanel code (along with the listShuttle inside it) was being instantiated outside the page's form. I moved it inside and the users are being populated correctly. I think I initially moved it outside the form because of a submit issue I was having, but I'm going to try keeping it inside for now and see if the submit issue returns.

                                • 13. Re: ListShuttle not displaying sourceValue and targetValue l
                                  Ilya Shaikovsky Master

                                  and form also could not influence the listShuttle in such way.. please read again Nick's questions..

                                  And about sample creation.. in order not to loose many time for background-data you could checkout rf-demo or listshuttle-sample sources from our SVN(link in my signature) and just change the page structure to yours.. Then if reproduced it will be checked faster.

                                  • 14. Re: ListShuttle not displaying sourceValue and targetValue l
                                    Greg Fasnacht Newbie

                                    To answer Nick's question, the userList managed bean is declared in faces-config. A new version of it is instantiated in the backing bean for my page and is then saved on the session. Yes, the items numbers are correct.

                                    Ilya, after I moved the modalPanel (and listShuttle) code into my page's form I started seeing the userConverter being called. When the code was outside the form in its own ui:include the converter wasn't being called and the lists were not being populated in the listShuttle. I'm working another issue now (see below) but I'll try your sample creation idea later...

                                    The current problem I'm seeing is that the changes I make in the listShuttle are not being propagated to the UserList managed bean. If I make a change (moving one or more users from one side to the other) and then hit my OK button to close the modalPanel, that change isn't reflected in the managed bean and I'm not able to save the change to the database. If however I reopen the modalPanel, the last changes I made are still there and I can see the set methods being called to put those values into the managed bean. It appears as though the set methods are only being called when the component opens...not when it closes. Is there a way I can force the listShuttle to update UserList when it closes?