Version 36

    s:selectItems

     

    The s:selectItems tag has been in Seam itself since 1.1.5.GA, the EntityConverter has been packaged separately for use with s:selectitems.

     

    SeamSelectItems (1.1.1beta4) is compatible with Seam > 1.1.5.GA BUT SeamSelectItems is deprecated in favour of the above and there will be no further releases by me (petemuir).

     

     

    Download

    Latest version: 1.1.1beta4 - stable, compatible with Seam 1.1.0.GA

     

    -


     

    Getting Started Guide - Using si:selectItems with EJB3 Entities

     

    1. Download and Configure SeamSelectItems

      1. Download the selectitems zip, and unzip it.  Included are prebuilt jars, source code and an example

      2. Place selectitems.jar and selectitems-ui.jar in the WEB-INF/lib of your war

      3. Make sure you have a Seam-managed persistence context set up (see Chapter 13.4.2 of the reference documentation) with entityManager as the   name, and are using it to manage your entities.

    2. Ensure your Entity Beans and Action beans are setup correctly

      1. Make sure you have the correct relationships between your entities (i.e. use the @ManyToOne, @OneToOne etc. annotations)

      2. Make sure you are outjecting a list of entities (NOT a List<SelectItem>)

    3. Alter your page

      1. Include the taglibrary definition in your page.  The uri of the taglibrary is http://jboss.com/products/seam/selectitems/taglib.

        1. If you are using facelets add xmlns:si="http://jboss.com/products/seam/selectitems/taglib" to your root tag (probably ui:composition)

        2. If you are using JSP add <%@ taglib uri="http://jboss.com/products/seam/selectitems/taglib" prefix="si"%> to the top of the file

      2. Add a select JSF component (e.g. h:selectOneMenu)

      3. Make sure you use si:selectItems rather than f:selectItems (see Code Block 1 below)

        1. Add the value attribute, with an EL expression referencing the outjected list you want to display

        2. Add the var attribute; this must be a static text variable

        3. Add the label attribute to set the label for each item in the dropdown.  You will probably want to reference the var attribute

    4. Hopefully you've now got a simple select menu up and running without having to write any custom converters and without having to manually convert all you List<Foo> into List<SelectItem>.  The reference guide below will tell you about other attributes on si:selectItems and easy ways to deal with more complex Entities.

     

    Code Blocks

     

    Code Block 1: Example use of si:selectItems

    <h:selectOneMenu value="#{user.nationality}">
       <si:selectItems value="#{nationalities}" var="nationality" label="#{nationality.label}" ></si:selectItems>
    </h:selectOneMenu>

     

    -


     

    Example Explained

     

    The examples show a number of common cases for the use of SeamSelectItems.  The example code described here applies equally to the facelets and the jsp example.  Make sure you look at the example code when reading this section!

     

    Discount

     

    <h:selectOneMenu value="#{client.discount}">
       <si:selectItems value="#{discounts}" var="discount" label="#{messages[discount.labelKey]}" hideNoSelection="true" noSelectionLabel="Please Select..."></si:selectItems>
    </h:selectOneMenu>
    

     

    Discount is an enum, which uses noSelectionLabel and hideNoSelection. Each item in the discounts list is assigned to var="discount" as the list is iterated over. The label is looked up in the Seam message bundle.

     

    ClientType

     

    <h:selectOneListbox value="#{client.clientType}" required="true">
       <si:selectItems value="#{clientTypes}" var="clientType" label="#{clientType.description}" noSelectionLabel="Please Select..." cache="true"></si:selectItems>
    </h:selectOneListbox>
    

     

    Client Type is pre set in the example. It is a required field, and has a no selection label set - if you try to select it and submit, JSF will reject it as an entry is required. clientTypes are cached so are only loaded on the first page load (or if the cache expires).

     

    Department

    <h:selectOneListbox value="#{client.department}" converter="#{clientAction.departmentConverter}">
       <si:selectItems value="#{departments}" var="department" label="#{department.description} (#{department.manager})"></si:selectItems>
    </h:selectOneListbox>
    

    The @Id property on department is an embedded object, so a custom converter has been written, and specified using the converter attribute.

     

    public Converter getDepartmentConverter() {
       return new EntityConverter<Department>() {
    
          protected Object getIdAsObject(String id, Class clazz) {
             String branch = id.substring(0, id.indexOf("_"));
             String manager = id.substring(id.indexOf("_") + 1);
             return new DepartmentId(branch, manager);
          }
    
          protected String getIdAsString(Department entity) {
             return entity.getId().getBranch() + "_" + entity.getId().getManager();
          }
       };
    }
    

     

    As you can see the converter is very simple (N.B. Don't use this conversion strategy in anger!)

     

    Factory

     

    <h:selectManyListbox value="#{client.factories}" id="factory">
       <si:selectItems value="#{factories}" var="factory" label="#{factory.manager} (#{factory.capacity})" config="#{mySelectItemsConfig}"></si:selectItems>
    </h:selectManyListbox>
    

     

    Factory is a select many, which works just as a select one.  Also, you can see the way in which we can easily combine fields in the label. The default config has been overridden by use of the config= attribute - mySelectItemsConfig has been defined in components.xml.

     

    <components ... xmlns:selectitems="http://jboss.com/products/seam/selectitems">
       ...
       <selectitems:config name="mySelectItemsConfig" no-selection-label="Please Select..."></selectitems:config>
    </components>
    

     

    Filter results by...

     

    This example is currently not in the example set and is not tested

     

    si:selectItems also allows you to return the key unconverted, this is useful if you are using the dropdown on a search page, and want to include some non-entity options in the dropdown.  In this example we include the dropdown in a search screen; searchAction collates all the filters and produces a list of search results.

     

    <h:selectOneMenu value="#{searchAction.taskPriority}">
       <f:selectItem itemValue="-1" itemLabel="Disable filter" ></f:selectItem>
       <f:selectItem itemValue="-2" itemLabel="Task priority less than 3" ></f:selectItem>
       <f:selectItem itemValue="-3" itemLabel="Taks priority more than 3" ></f:selectItem>
       <si:selectItems value="#{taskPriorities}" var="tp" label="#{tp.description}" key="#{tp.id}" ></si:selectItems>
    </h:selectOneMenu>

     

    @Name("filterAction")
    public Class FilterActionBean {
    
       private Integer taskPriorityId;
    
       ...
       public void setTaskPriority(String key) {
           this.taskPriorityId = Integer.parseInt(key);
       }
    
       public String getTaskPriority() {
          return taskPriorityId != null ? taskPriorityId.toString() : null;
       }
    
       @Factory("searchResults")
       public List<Foo> getFoo() {
          if (taskPriorityId > 0) {
             TaskPriority taskPriority = entityManager.getReference(TaskPriority.class, taskPriorityId);
             return entityManager.createQuery("select f from Foo where f.taskPriority = :taskPriority").setParameter("taskPriority", taskPriority).getResultList();
          } else if (taskPriorityId.equals(0)) {
             return entityManager.createQuery("select f from Foo").getResultList();
          } // etc
       }
    }
    

     

    An "everyday" example: Using EJB-Queries with si:selectItems

     

    The combination of si:selectItems and Seam's query objects is really powerful. Imagine you have entities like this:

     

    @Entity
    public class Department {
    
      @Id
      private Integer id;
      private String name;
      // other properties
    
    }
    
    @Name("employee")
    @Scope(CONVERSATION)
    @Entity
    public class Employee {
    
      @Id
      private Integer id;
    
      @ManyToOne
      private Department department;
      // other properties
    
    }
    

     

    If you create or edit the record of an employee, you want to set the department. This list of available departments has to be fetched from the database. You can do this by defining a query object in

    components.xml

    .

     

     <factory name="departments" value="#{qry_department.resultList}" scope="PAGE"></factory>
        <framework:entity-query name="qry_department" ejbql="select d from Department d" ></framework:entity-query>
    

     

    Now you can use the seam component "departments" with the si:selectitems tag:

     

    <h:selectOneMenu value="#{employee.department}">
       <si:selectItems value="#{departments}" var="department" label="#{department.name}"></si:selectItems>
    </h:selectManyListbox>
    

     

    -


     

    Reference Guide

     

    Taglibrary

     

    • si:convertEnum Attaches the org.jboss.seam.EnumConverter to the Select{One, Many}

    • si:convertEntity Attaches the org.jboss.seam.EntityConverter to the Select{One, Many}

      • entityClass attribute sets the class of the entities being converted. Only required if the converter is having problems guessing the class. (static value only)

    • si:selectItems An extension of f:selectItems, it will automatically attach a org.jboss.seam.EnumConverter or org.jboss.seam.EntityConverter if required. If a converter is specified (using f:converter or the converter="..." attribute) it will be used instead.

      • value attribute references to an Iterable object (EL only)

      • var attribute defines the name of the variable that will hold the current row during iteration. (static value only)

      • label attribute defines the label to use for the row. Reference to var is supported. (static value or EL)

      • disabled attribute defines whether to disabled a row. Reference to var is supported. (static value or EL)

      • cache attribute enables caching of select items; the key is based upon the reference of the value attribute (unless cacheKey is specified). (static value or EL)

      • cacheKey attribute sets the cacheKey. Setting this implicitly enables caching. (static value or EL)

      • noSelectionLabel attribute defines a 'Please Select one...' label placed at the top of the list. If the attribute is not specified no label will be put on the top of the list. (static value or EL)

      • hideNoSelection attribute causes the noSelectionLabel will be hidden when the Select{Many,One}'s value is not null. (static value or EL)

      • key EL or string which defines the id for an option. Reference to var is supported. Disables auto conversion; the Select{Many,One}'s value attribute should reference a String. (static value or EL)

      • config EL which references a non-default configuration

     

    Converters

     

    • org.jboss.seam.EnumConverter - A generic converter which is capable of dealing with all enums

    • org.jboss.seam.EntityConverter - A generic converter which can deal with all objects marked with @Entity which have primitive, primitive-wrapped or String ids.

     

    Abstract Converters

    • org.jboss.seam.selectitems.jsf.SelectItemsConverter. Any custom converter used with si:selectItems should extend this

      • Override convertToString, and provide conversion from an a unique property in object form to a unique String. This conversion must be reversible in convertToObject

      • Override convertToObject, and provide conversion from the string to the object

    • org.jboss.seam.selectitems.jsf.EntityConverter. This converter will do most of the work for you. You just need to:

      • Override getIdAsString, and provide conversion from the entities Id to a string

      • Override getIdAsObject, and provide conversion from a string back to an Id

     

    Configuration through components.xml

     

    A number of the attributes described above are configurable on a global level. They are entityManager, cache, noSelectionLabel, hideNoSelection, cacheRegion and noSelectionValue (see tips & tricks below).  The namespace used is http://jboss.com/products/seam/selectitems and the schema is at SeamSelectItemsNewDesign/Selectitems1.1.xsd.  Alternative configurations can be specified in components.xml using a different name, and specified on the config attribute of si:selectitems or by extension.

     

     

    Jars

     

    SeamSelectItems is split into two jars - selectitems.jar and selectitems-ui.jar.  If you are using the new-style si:selectItems then you can just place both these jars in my.war/WEB-INF/lib.  If you need to access the EntityConverter or the SelectItemsConverter from a Seam component (e.g. to create a custom converter) then you'll need to place the selectitems.jar in the ear, and reference it from application.xml (the selectitems-ui.jar still goes in WEB-INF/lib

     

    Caching

     

    You don't have to use caching with SeamSelectItems, but if you do, you must make sure your application support caching.

     

    The jgroups.jar and jboss-cache.jar need to be added to your ear, and the cache configuration file treecache.xml should be added to the root of the ear. A sample (non-clustered) can be found in the example app. The default region (allows control of cache content expiration etc.) is org/jboss/seam/selectitems. This can be overridden by using the cacheRegion attribute on si:selectItems.

     

    Error messages

     

    SeamSelectItems will print messages to the page if an error occurs.  These are:

     

    • org.jboss.seam.selectitems.entityConverter.idNotFound

    • org.jboss.seam.selectitems.entityConverter.notAnEntity

    • org.jboss.seam.selectitems.entityConverter.entityClassNotFound

    • org.jboss.seam.selectitems.entityConverter.classNotFound

    • org.jboss.seam.selectitems.entityConverter.emAccessError

    • org.jboss.seam.selectitems.entityConverter.invalidSelection

    • org.jboss.seam.selectitems.enumConverter.classNotFound

    • org.jboss.seam.selectitems.enumConverter.notAnEnum

     

    These can be overriden by placing the property in the Seam Message Bundle.

     

    -


     

    Tips and Troubleshooting

    • Select Many: SeamSelectItems might have issues working out which converter to attach to the select many, and, if you are trying to convert an entity, might have problems working out which entity to use.  If this is the case, just specify the converter manually. (e.g. <s:convertEntity entityClass="example.entity" />).

    • Trinidad: Trinidad provides an (IMO inferior ) version of noSelectionLabel/hideNoSelectionLabel (if you don't specify a label, it puts in an empty string and hides it when a value is set, if you do specify a string it doesn't hide it AND you can't turn it off completely).  To use SeamSelectItems noSelectionLabel and disable trinidad's you need to set the config property noSelectionValue to an empty string (i.e. <selectitems: config noSelectionValue="" />).

     

    -


     

    Changelog

     

    .1.1beta4

    • BUG Support selectMany without having to specify converter/entityConverter (in most cases)

    • FEATURE Trinidad work around for noSelectionLabel/hideNoSelectionLabel

    • FEATURE Schema version of configuration

    • FEATURE Specify an alternative configuration on si:selectItems

    • BUG Fix ResourceNotFoundException thrown if an error is to be displayed

    • FEATURE Can now outject an array or DataModel (using @DataModel) as the list of selectitems

    • BUG Remove need for id equality

    • BUG Remove need to configure persistenceUnitJndiName

      • The EntityConverter now uses the same SMPC as is used in the rest of the applicaiton.

      • If the SMPC is called entityManager (as generated by seam-gen) no configuration is needed, otherwise it must be configured in components.xml

      • Can no longer set persistenceUnitJndiName on si:convertEntity

    • BUG Automatically instatiate SelectItemsConfig

    • BUG Don't error if @Entity is missing, on entity class, but, if cannot find @Id notify the user that @Entity is missing (due to Seam proxying)

     

    1.1.1beta3

    • Modify exception thrown if value of si:selectitems is not iterable to be more descriptive

     

    1.1.1beta2

    • FEATURE Support JSP tags by moving logic from a ComponentHandler to UISeamSelectItems, xxxTag for tags, tld file

    • BUG Fix tag not working in render-time loops

    • FEATURE Copy and alter example to show jsp version

    • FEATURE Improve EntityConverter so that it guesses the entity class if it is extended using generics

    • Split into core jar and ui jar (allows access to EntityConverter on backing bean)

     

    1.1.1beta1

     

    • Deprecate @SelectItems

    • Handle conversion in ComponentHandler and control through si:selectItems attributes

    • Global config

    • Support easy overriding of EntityConverter for custom conversion (e.g. @EmbeddedId

     

    1.1.0rc2

     

    • FEATURE Add convertEnum tag for facelets

    • FEATURE Added caching support. This is based on the pojoCache component of Seam.

    • Rename org.jboss.seam.selectitems.SelectItemsPersistenceConfig to org.jboss.seam.selectitems.SelectItemsConfig. THIS IS A BREAKING CHANGE.

     

    1.0.1rc1 to 1.1.0rc1

     

    • Make compatible with Seam 1.1BETA1

     

    1.0rc4 to 1.0.1rc1

     

    • FEATURE: Patch from Mikko Koponen to support 'noSelectionLabel'. This places a SelectItem at the top of the list which has a value null. Combined with the use of required="true" this allows the UI to force the user to select a value from the list.

    • BUG FIX: Patch from Mikko Koponen to correct error in jsfValue (Thanks to others for spotting this)

    • BUG FIX: Patch from Mikko Koponen to search superclasses for @Id (Thanks also to Jarkko for finding the bug)

    • FEATURE: Use of Seam Messages resource bundle. By default any label is interpreted as a key for the Seam message bundle. As usual with the Seam message bundle if the key/value pair isn't defined the key is used.

    • FEATURE: An EnumConverter to complement the EntityConverter

    • BUG FIX: Example upgraded to show new features

    • BUG FIX: Upgrade Ant Build to support build numbers

    • FEATURE: Move homepage of project to Seam Wiki SeamSelectItems

     

    1.0rc3 to 1.0rc4

     

    • @SelectItems Binder altered so that the getter methods for label, jsfValue and disabled must be public. They may also be on the superclass.

    • Multiple selection example and fix

     

    -


     

    Also

     

     

    Thanks to

    • Mikko Koponen

    • Newlukai for Getting Started Guide