ListShuttle not displaying sourceValue and targetValue lists
ggfuzzy Apr 30, 2009 11:59 PMI'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