dev@javaserverfaces.java.net

Seeking Review Re: [451-noSelection] PROPOSAL

From: Ed Burns <Ed.Burns_at_Sun.COM>
Date: Thu, 04 Dec 2008 11:46:05 -0800

>>>>> On Wed, 03 Dec 2008 08:57:03 +0000, Pete Muir said:

PM> Yes, that seems like a good approach.
PM> On 2 Dec 2008, at 19:25, Ed Burns wrote:

Seeking review for
https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=451

Attachment at
https://javaserverfaces-spec-public.dev.java.net/nonav/issues/showattachment.cgi/171/changebundle.txt

Inline below:

Issue: 451 part 1 of 2

This part deals with the introduction of the "noSelectionOption"
property on UISelectItem, SelectItem, and f:selectItem, in both Facelets
and JSP. When a select item is encountered that has "true" for the
value of this property, *and* the select* that contains the select item
has required="true", then the select* should fail validation.

FWIW, I had to modify code to implement this feature, and the code was
very well factored and easy to modify.


SECTION: Modified Files
----------------------------
M jsf-api/src/javax/faces/model/SelectItem.java

- Modify 5 arg ctor to be 6 arg ctor where the last arg is the boolean
  value of the noSelectionOption property.

- Modify places where 5 arg ctor is called to call 6 arg ctor.

- add boolean noSelectionOption JavaBeans property

M jsf-api/src/javax/faces/component/UISelectMany.java
M jsf-api/src/javax/faces/component/UISelectOne.java

- add boolean noSelectionOption JavaBeans property

- modify validateValue() to take the correct action in the case of
  noSelectionOption.

M jsf-api/src/javax/faces/component/SelectItemsIterator.java

- account for boolean noSelectionOption JavaBeans property on
  UISelectItem and SelectItem.

M jsf-api/src/javax/faces/component/UISelectItem.java

- add boolean noSelectionOption JavaBeans property

M jsf-api/src/javax/faces/component/SelectUtils.java

- modify matchValue() to take Iterator<SelectItem> items intstead of
  un-generified version

- extract one part of code formerly in matchValue() into its own method.
  Note the use of throwing an IllegalStateException where before the
  code would have done "continue".

- add new valueIsNoSelectionOption() method

+ * Returns true iff component has a {_at_link UISelectItem} child
+ * whose itemValue exactly matches the argument value

M jsf-ri/conf/share/jsf_core.tld

- Document noSelectionOption feature

M jsf-ri/src/com/sun/faces/renderkit/SelectItemsIterator.java

- Copy from jsf-api. PENDING should do this at build time.

M jsf-ri/src/com/sun/faces/taglib/jsf_core/SelectItemTag.java

- pass along noSelectionOption attribute

M jsf-ri/systest/web/WEB-INF/web.xml

- Say that *.jspx pages are JSP XML Syntax.

A jsf-ri/systest/web/render/selectStarNoSelection.jspx
A jsf-ri/systest/web/render/selectStarNoSelection.xhtml

- Fodder for automated test that is to be written.


SECTION: Diffs
----------------------------
Index: jsf-api/src/javax/faces/model/SelectItem.java
===================================================================
--- jsf-api/src/javax/faces/model/SelectItem.java (revision 5995)
+++ jsf-api/src/javax/faces/model/SelectItem.java (working copy)
@@ -84,7 +84,7 @@
      */
     public SelectItem(Object value) {
 
- this(value, value == null ? null : value.toString(), null, false, true);
+ this(value, value == null ? null : value.toString(), null, false, true, false);
 
     }
 
@@ -102,7 +102,7 @@
      */
     public SelectItem(Object value, String label) {
 
- this(value, label, null, false, true);
+ this(value, label, null, false, true, false);
 
     }
 
@@ -120,7 +120,7 @@
      */
     public SelectItem(Object value, String label, String description) {
 
- this(value, label, description, false, true);
+ this(value, label, description, false, true, false);
 
     }
 
@@ -139,7 +139,7 @@
     public SelectItem(Object value, String label, String description,
                       boolean disabled) {
 
- this(value, label, description, disabled, true);
+ this(value, label, description, disabled, true, false);
 
     }
     
@@ -154,10 +154,11 @@
      * @param disabled Flag indicating that this option is disabled
      * @param escape Flag indicating that the text of this option should be
      * escaped when rendered.
+ * @param noSelectionOption Flag indicating that the current option is a "no selection" option
      * @since 1.2
      */
     public SelectItem(Object value, String label, String description,
- boolean disabled, boolean escape) {
+ boolean disabled, boolean escape, boolean noSelectionOption) {
 
         super();
         setValue(value);
@@ -165,6 +166,7 @@
         setDescription(description);
         setDisabled(disabled);
         setEscape(escape);
+ setNoSelectionOption(noSelectionOption);
 
     }
 
@@ -298,6 +300,17 @@
     public void setEscape(boolean escape) {
         this.escape = escape;
     }
+
+ private boolean noSelectionOption = false;
 
+ public boolean isNoSelectionOption() {
+ return noSelectionOption;
+ }
 
+ public void setNoSelectionOption(boolean noSelectionOption) {
+ this.noSelectionOption = noSelectionOption;
+ }
+
+
+
 }
Index: jsf-api/src/javax/faces/component/UISelectMany.java
===================================================================
--- jsf-api/src/javax/faces/component/UISelectMany.java (revision 5995)
+++ jsf-api/src/javax/faces/component/UISelectMany.java (working copy)
@@ -576,6 +576,8 @@
         if (!isValid() || (value == null)) {
             return;
         }
+
+ boolean doAddMessage = false;
 
         // Ensure that the values match one of the available options
         // Don't arrays cast to "Object[]", as we may now be using an array
@@ -589,16 +591,37 @@
                                         currentValue,
                                         items,
                                         converter)) {
- // Enqueue an error message if an invalid value was specified
- FacesMessage message =
- MessageFactory.getMessage(context,
- INVALID_MESSAGE_ID,
- MessageFactory.getLabel(context, this));
- context.addMessage(getClientId(context), message);
- setValid(false);
- return;
+ doAddMessage = true;
+ break;
             }
         }
+
+ // Ensure that if the value is noSelection and a
+ // value is required, a message is queued
+ if (isRequired()) {
+ for (Iterator i = getValuesIterator(value); i.hasNext();) {
+ Iterator items = new SelectItemsIterator(context, this);
+ Object currentValue = i.next();
+ if (SelectUtils.valueIsNoSelectionOption(context,
+ this,
+ currentValue,
+ items,
+ converter)) {
+ doAddMessage = true;
+ break;
+ }
+ }
+ }
+
+ if (doAddMessage) {
+ // Enqueue an error message if an invalid value was specified
+ FacesMessage message =
+ MessageFactory.getMessage(context,
+ INVALID_MESSAGE_ID,
+ MessageFactory.getLabel(context, this));
+ context.addMessage(getClientId(context), message);
+ setValid(false);
+ }
 
     }
 
Index: jsf-api/src/javax/faces/component/UISelectOne.java
===================================================================
--- jsf-api/src/javax/faces/component/UISelectOne.java (revision 5995)
+++ jsf-api/src/javax/faces/component/UISelectOne.java (working copy)
@@ -147,14 +147,22 @@
                                                new SelectItemsIterator(context, this),
                                                getConverter());
 
+ boolean isNoSelection = SelectUtils.valueIsNoSelectionOption(getFacesContext(),
+ this,
+ value,
+ new SelectItemsIterator(context, this),
+ getConverter());
+
         // Enqueue an error message if an invalid value was specified
- if (!found) {
+ if ((!found) ||
+ (isRequired() && isNoSelection)) {
             FacesMessage message =
                 MessageFactory.getMessage(context, INVALID_MESSAGE_ID,
                      MessageFactory.getLabel(context, this));
             context.addMessage(getClientId(context), message);
             setValid(false);
         }
+
     }
 
 }
Index: jsf-api/src/javax/faces/component/SelectItemsIterator.java
===================================================================
--- jsf-api/src/javax/faces/component/SelectItemsIterator.java (revision 5995)
+++ jsf-api/src/javax/faces/component/SelectItemsIterator.java (working copy)
@@ -187,7 +187,8 @@
                                       ui.getItemLabel(),
                                       ui.getItemDescription(),
                                       ui.isItemDisabled(),
- ui.isItemEscaped());
+ ui.isItemEscaped(),
+ ui.isNoSelectionOption());
             }
             updateSingeItemIterator(item);
             items = singleItemIterator;
@@ -415,6 +416,7 @@
             private static final String ITEM_DESCRIPTION = "itemDescription";
             private static final String ITEM_ESCAPED = "itemEscaped";
             private static final String ITEM_DISABLED = "itemDisabled";
+ private static final String NO_SELECTION_OPTION = "noSelectionOption";
 
             /**
              * Resolves to the value of the <code>SelectItem</code>.
@@ -442,6 +444,11 @@
             private ValueExpression itemDisabled;
 
             /**
+ * Determines the value for the noSelectionOption property of the <code>SelectItem</code>/
+ */
+ private ValueExpression noSelectionOption;
+
+ /**
              * The request-scoped variable under which the current object
              * will be exposed.
              */
@@ -458,6 +465,7 @@
                 itemDescription = sourceComponent.getValueExpression(ITEM_DESCRIPTION);
                 itemEscaped = sourceComponent.getValueExpression(ITEM_ESCAPED);
                 itemDisabled = sourceComponent.getValueExpression(ITEM_DISABLED);
+ noSelectionOption = sourceComponent.getValueExpression(NO_SELECTION_OPTION);
 
             }
 
@@ -496,6 +504,9 @@
                     setDisabled(((itemDisabled != null)
                                      ? (Boolean) itemDisabled.getValue(elContext)
                                      : false));
+ setNoSelectionOption(((noSelectionOption != null)
+ ? (Boolean) noSelectionOption.getValue(elContext)
+ : false));
                 } finally {
                     if (var != null) {
                         if (oldVarValue != null) {
Index: jsf-api/src/javax/faces/component/UISelectItem.java
===================================================================
--- jsf-api/src/javax/faces/component/UISelectItem.java (revision 5995)
+++ jsf-api/src/javax/faces/component/UISelectItem.java (working copy)
@@ -105,6 +105,7 @@
     private String itemDescription = null;
     private Boolean itemDisabled;
     private Boolean itemEscaped;
+ private Boolean noSelectionOption = false;
     private String itemLabel = null;
     private Object itemValue = null;
     private Object value = null;
@@ -327,8 +328,16 @@
         this.value = value;
 
     }
+
+ public boolean isNoSelectionOption() {
+ return noSelectionOption;
+ }
 
+ public void setNoSelectionOption(boolean noSelectionOption) {
+ this.noSelectionOption = noSelectionOption;
+ }
 
+
     // ----------------------------------------------------- StateHolder Methods
 
 
@@ -337,7 +346,7 @@
     public Object saveState(FacesContext context) {
 
         if (values == null) {
- values = new Object[7];
+ values = new Object[8];
         }
        
         values[0] = super.saveState(context);
@@ -347,6 +356,7 @@
         values[4] = itemLabel;
         values[5] = itemValue;
         values[6] = value;
+ values[7] = noSelectionOption;
         return (values);
 
     }
@@ -362,6 +372,7 @@
         itemLabel = (String) values[4];
         itemValue = values[5];
         value = values[6];
+ noSelectionOption = (Boolean) values[7];
 
     }
 
Index: jsf-api/src/javax/faces/component/SelectUtils.java
===================================================================
--- jsf-api/src/javax/faces/component/SelectUtils.java (revision 5995)
+++ jsf-api/src/javax/faces/component/SelectUtils.java (working copy)
@@ -75,11 +75,11 @@
     static boolean matchValue(FacesContext ctx,
                               UIComponent component,
                               Object value,
- Iterator items,
+ Iterator<SelectItem> items,
                               Converter converter) {
 
         while (items.hasNext()) {
- SelectItem item = (SelectItem) items.next();
+ SelectItem item = items.next();
             if (item instanceof SelectItemGroup) {
                 SelectItem subitems[] =
                       ((SelectItemGroup) item).getSelectItems();
@@ -89,27 +89,17 @@
                     }
                 }
             } else {
- Object itemValue = item.getValue();
- if (itemValue == null && value == null) {
- return (true);
- }
- if ((value == null) ^ (itemValue == null)) {
+ Object compareValue = null;
+
+ try {
+ compareValue = doConversion(ctx, component, item, value,
+ converter);
+ } catch (IllegalStateException ise) {
                     continue;
                 }
- Object compareValue;
- if (converter == null) {
- compareValue =
- coerceToModelType(ctx, itemValue, value.getClass());
- } else {
- compareValue = itemValue;
- if (compareValue instanceof String
- && !(value instanceof String)) {
- // type mismatch between the time and the value we're
- // comparing. Invoke the Converter.
- compareValue = converter.getAsObject(ctx,
- component,
- (String) compareValue);
- }
+
+ if (null == compareValue && null == value) {
+ return true;
                 }
 
                 if (value.equals(compareValue)) {
@@ -120,8 +110,90 @@
         return (false);
 
     }
+
+ /**
+ * Returns true iff component has a {_at_link UISelectItem} child
+ * whose itemValue exactly matches the argument value
+ * @param ctx
+ * @param component
+ * @param value
+ * @param items
+ * @return
+ */
+
+ static boolean valueIsNoSelectionOption(FacesContext ctx,
+ UIComponent component,
+ Object value,
+ Iterator<SelectItem> items,
+ Converter converter) {
+ boolean result = false;
+
+ while (items.hasNext()) {
+ SelectItem item = items.next();
+ if (item instanceof SelectItemGroup) {
+ SelectItem subitems[] =
+ ((SelectItemGroup) item).getSelectItems();
+ if ((subitems != null) && (subitems.length > 0)) {
+ if (valueIsNoSelectionOption(ctx, component, value, new ArrayIterator(subitems), converter)) {
+ result = true;
+ break;
+ }
+ }
+ } else {
+ Object compareValue = null;
+
+ try {
+ compareValue = doConversion(ctx, component, item, value,
+ converter);
+ } catch (IllegalStateException ise) {
+ continue;
+ }
+
+ if (null == compareValue && null == value &&
+ item.isNoSelectionOption()) {
+ result = true;
+ break;
+ } else if (value.equals(compareValue) && item.isNoSelectionOption()) {
+ result = true;
+ break;
+ }
+ }
+
+ }
+
+ return result;
+ }
+
+ private static Object doConversion(FacesContext ctx,
+ UIComponent component, SelectItem item,
+ Object value, Converter converter) throws IllegalStateException {
+ Object itemValue = item.getValue();
+ if (itemValue == null && value == null) {
+ return (null);
+ }
+ if ((value == null) ^ (itemValue == null)) {
+ throw new IllegalStateException("XOR comparison failed");
+ }
+ Object compareValue;
+ if (converter == null) {
+ compareValue =
+ coerceToModelType(ctx, itemValue, value.getClass());
+ } else {
+ compareValue = itemValue;
+ if (compareValue instanceof String
+ && !(value instanceof String)) {
+ // type mismatch between the time and the value we're
+ // comparing. Invoke the Converter.
+ compareValue = converter.getAsObject(ctx,
+ component,
+ (String) compareValue);
+ }
+ }
 
+ return compareValue;
+ }
 
+
     /**
      * Coerce the provided value to the specified type using EL coercion.
      *
Index: jsf-ri/conf/share/jsf_core.tld
===================================================================
--- jsf-ri/conf/share/jsf_core.tld (revision 5995)
+++ jsf-ri/conf/share/jsf_core.tld (working copy)
@@ -711,6 +711,20 @@
             </deferred-value>
         </attribute>
 
+ <attribute>
+ <description>
+ Flag indicating whether the option created by this
+ component represents the special "no selection"
+ option. Expressions must evaluate to a boolean.
+ Default value is false.
+ </description>
+ <name>noSelectionOption</name>
+ <deferred-value>
+ <type>java.lang.Boolean</type>
+ </deferred-value>
+ </attribute>
+
+
     </tag>
 
 
Index: jsf-ri/src/com/sun/faces/renderkit/SelectItemsIterator.java
===================================================================
--- jsf-ri/src/com/sun/faces/renderkit/SelectItemsIterator.java (revision 5995)
+++ jsf-ri/src/com/sun/faces/renderkit/SelectItemsIterator.java (working copy)
@@ -1,7 +1,11 @@
 /*
+ * $Id$
+ */
+
+/*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -37,9 +41,9 @@
 package com.sun.faces.renderkit;
 
 import java.util.Iterator;
-import java.util.ListIterator;
 import java.util.NoSuchElementException;
 import java.util.Map;
+import java.util.ListIterator;
 import java.io.ObjectOutputStream;
 import java.io.IOException;
 import java.io.NotSerializableException;
@@ -48,25 +52,22 @@
 
 import javax.faces.model.SelectItem;
 import javax.faces.context.FacesContext;
+import javax.el.ValueExpression;
+import javax.el.ELContext;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UISelectItem;
 import javax.faces.component.UISelectItems;
-import javax.el.ValueExpression;
-import javax.el.ELContext;
+import javax.faces.component.UISelectMany;
+import javax.faces.component.UISelectOne;
 
 
 /**
- * <p>
- * This class is responsible for iterating over the set of {_at_link javax.faces.model.SelectItem}s
- * for a parent {_at_link javax.faces.component.UISelectMany} or {_at_link javax.faces.component.UISelectOne}.
- * </p>
+ * <p>Package private class for iterating over the set of {_at_link SelectItem}s
+ * for a parent {_at_link UISelectMany} or {_at_link UISelectOne}.</p>
  *
- * <p>
- * <em>NOTE:</em> this code is duplicated by javax.faces.component.SelectItemsIterator. Any changes
- * here should be made there.
- * </p>
+ * // RELEASE_PENDING (rlubke,driscoll) performanc review
  */
-public class SelectItemsIterator implements Iterator<SelectItem> {
+final class SelectItemsIterator implements Iterator<SelectItem> {
 
 
     // ------------------------------------------------------------ Constructors
@@ -75,7 +76,7 @@
     /**
      * <p>Construct an iterator instance for the specified parent component.</p>
      *
- * @param parent The parent {_at_link javax.faces.component.UIComponent} whose children will be
+ * @param parent The parent {_at_link UIComponent} whose children will be
      * processed
      */
     public SelectItemsIterator(FacesContext ctx, UIComponent parent) {
@@ -144,7 +145,7 @@
     /**
      * <p>Return the next element in the iteration.</p>
      *
- * @throws java.util.NoSuchElementException if there are no more elements
+ * @throws NoSuchElementException if there are no more elements
      */
     @SuppressWarnings({"unchecked"})
     public SelectItem next() {
@@ -191,7 +192,8 @@
                                       ui.getItemLabel(),
                                       ui.getItemDescription(),
                                       ui.isItemDisabled(),
- ui.isItemEscaped());
+ ui.isItemEscaped(),
+ ui.isNoSelectionOption());
             }
             updateSingeItemIterator(item);
             items = singleItemIterator;
@@ -212,7 +214,7 @@
             } else {
                 throw new IllegalArgumentException();
             }
- }
+ }
 
     }
 
@@ -343,7 +345,7 @@
             item.setLabel(((key != null) ? key.toString() : value.toString()));
             item.setValue(((value != null) ? value : ""));
             return item;
-
+
         }
 
 
@@ -397,7 +399,7 @@
 
             genericObjectSI.updateItem(ctx, value);
             return genericObjectSI;
-
+
         }
 
 
@@ -419,6 +421,7 @@
             private static final String ITEM_DESCRIPTION = "itemDescription";
             private static final String ITEM_ESCAPED = "itemEscaped";
             private static final String ITEM_DISABLED = "itemDisabled";
+ private static final String NO_SELECTION_OPTION = "noSelectionOption";
 
             /**
              * Resolves to the value of the <code>SelectItem</code>.
@@ -446,6 +449,11 @@
             private ValueExpression itemDisabled;
 
             /**
+ * Determines the value for the noSelectionOption property of the <code>SelectItem</code>/
+ */
+ private ValueExpression noSelectionOption;
+
+ /**
              * The request-scoped variable under which the current object
              * will be exposed.
              */
@@ -462,6 +470,7 @@
                 itemDescription = sourceComponent.getValueExpression(ITEM_DESCRIPTION);
                 itemEscaped = sourceComponent.getValueExpression(ITEM_ESCAPED);
                 itemDisabled = sourceComponent.getValueExpression(ITEM_DISABLED);
+ noSelectionOption = sourceComponent.getValueExpression(NO_SELECTION_OPTION);
 
             }
 
@@ -500,6 +509,9 @@
                     setDisabled(((itemDisabled != null)
                                      ? (Boolean) itemDisabled.getValue(elContext)
                                      : false));
+ setNoSelectionOption(((noSelectionOption != null)
+ ? (Boolean) noSelectionOption.getValue(elContext)
+ : false));
                 } finally {
                     if (var != null) {
                         if (oldVarValue != null) {
@@ -650,7 +662,7 @@
         public void remove() {
 
             throw new UnsupportedOperationException();
-
+
         }
 
     } // END CollectionItemIterator
Index: jsf-ri/src/com/sun/faces/taglib/jsf_core/SelectItemTag.java
===================================================================
--- jsf-ri/src/com/sun/faces/taglib/jsf_core/SelectItemTag.java (revision 5995)
+++ jsf-ri/src/com/sun/faces/taglib/jsf_core/SelectItemTag.java (working copy)
@@ -71,6 +71,8 @@
     protected ValueExpression itemLabel;
     protected ValueExpression itemDescription;
     protected ValueExpression itemDisabled;
+ protected ValueExpression noSelectionOption = null;
+
     protected ValueExpression value;
 
     // Relationship Instance Variables
@@ -114,7 +116,11 @@
         this.value = value;
     }
 
+ public void setNoSelectionOption(ValueExpression noSelectionOption) {
+ this.noSelectionOption = noSelectionOption;
+ }
 
+
     //
     // General Methods
     //
@@ -175,6 +181,15 @@
                         booleanValue());
             }
         }
+ if (null != noSelectionOption) {
+ if (!noSelectionOption.isLiteralText()) {
+ selectItem.setValueExpression("noSelectionOption", noSelectionOption);
+ } else {
+ selectItem.setNoSelectionOption(
+ Boolean.valueOf(noSelectionOption.getExpressionString()).
+ booleanValue());
+ }
+ }
         if (null != escape) {
             if (!escape.isLiteralText()) {
                 selectItem.setValueExpression("escape", escape);
Index: jsf-ri/systest/web/render/selectStarNoSelection.jspx
===================================================================
--- jsf-ri/systest/web/render/selectStarNoSelection.jspx (revision 0)
+++ jsf-ri/systest/web/render/selectStarNoSelection.jspx (revision 0)
@@ -0,0 +1,170 @@
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:jsp="http://java.sun.com/JSP/Page"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xml:lang="en" lang="en">
+<jsp:output doctype-root-element="html"
+ doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
+<jsp:directive.page contentType="application/xhtml+xml; charset=UTF-8"/>
+<head>
+ <title>Select* with noSelectionOption</title>
+</head>
+<body bgcolor="white">
+<f:view>
+ <h:form prependId="false">
+
+<h1>SelectOneListbox</h1>
+
+<p>
+
+ <h:selectOneListbox id="selectOneListbox" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectOneListbox>
+
+</p>
+
+<h1>SelectOneMenu</h1>
+
+<p>
+
+ <h:selectOneMenu id="selectOneMenu" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectOneMenu>
+
+</p>
+
+<h1>SelectOneRadio</h1>
+
+<p>
+
+ <h:selectOneRadio id="selectOneRadio" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectOneRadio>
+
+</p>
+
+<h1>SelectManyCheckbox</h1>
+
+<p>
+
+ <h:selectManyCheckbox id="selectManyCheckbox" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectManyCheckbox>
+
+</p>
+
+<h1>SelectManyListbox</h1>
+
+<p>
+
+ <h:selectManyListbox id="selectManyListbox" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectManyListbox>
+
+</p>
+
+<h1>SelectManyMenu</h1>
+
+<p>
+
+ <h:selectManyMenu id="selectManyMenu" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectManyMenu>
+
+</p>
+
+
+
+<p>
+
+ <h:commandButton value="submit" />
+
+</p>
+
+ <p> messages: <h:messages /> </p>
+
+
+
+ </h:form>
+</f:view>
+
+<p>
+ <a href="http://validator.w3.org/check?uri=referer"><img
+ src="http://www.w3.org/Icons/valid-xhtml10"
+ alt="Valid XHTML 1.0!" height="31" width="88"/></a>
+</p>
+</body>
+</html>
Index: jsf-ri/systest/web/render/selectStarNoSelection.xhtml
===================================================================
--- jsf-ri/systest/web/render/selectStarNoSelection.xhtml (revision 0)
+++ jsf-ri/systest/web/render/selectStarNoSelection.xhtml (revision 0)
@@ -0,0 +1,123 @@
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core">
+<h:head>
+ <title>Test select* with noselection</title>
+</h:head>
+<h:body>
+ <h:form prependId="false">
+
+<h1>SelectOneListbox</h1>
+
+<p>
+
+ <h:selectOneListbox id="selectOneListbox" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectOneListbox>
+
+</p>
+
+<h1>SelectOneMenu</h1>
+
+<p>
+
+ <h:selectOneMenu id="selectOneMenu" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectOneMenu>
+
+</p>
+
+<h1>SelectOneRadio</h1>
+
+<p>
+
+ <h:selectOneRadio id="selectOneRadio" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectOneRadio>
+
+</p>
+
+<h1>SelectManyCheckbox</h1>
+
+<p>
+
+ <h:selectManyCheckbox id="selectManyCheckbox" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectManyCheckbox>
+
+</p>
+
+<h1>SelectManyListbox</h1>
+
+<p>
+
+ <h:selectManyListbox id="selectManyListbox" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectManyListbox>
+
+</p>
+
+<h1>SelectManyMenu</h1>
+
+<p>
+
+ <h:selectManyMenu id="selectManyMenu" required="true">
+
+ <f:selectItem noSelectionOption="true" itemLabel="No selection" itemValue="noSelection"/>
+ <f:selectItem itemLabel="Apple" itemValue="Apple"/>
+ <f:selectItem itemLabel="Orange" itemValue="Orange" />
+ <f:selectItem itemLabel="Pear" itemValue="Pear" />
+ <f:selectItem itemLabel="Peach" itemValue="Peach"/>
+
+ </h:selectManyMenu>
+
+</p>
+
+
+
+<p>
+
+ <h:commandButton value="submit" />
+
+</p>
+
+ <p> messages: <h:messages /> </p>
+
+
+
+ </h:form>
+</h:body>
+</html>
Index: jsf-ri/systest/web/WEB-INF/web.xml
===================================================================
--- jsf-ri/systest/web/WEB-INF/web.xml (revision 5995)
+++ jsf-ri/systest/web/WEB-INF/web.xml (working copy)
@@ -88,6 +88,12 @@
         <param-value>.jsp</param-value>
     </context-param>
 
+ <jsp-config>
+ <jsp-property-group>
+ <url-pattern>*.jspx</url-pattern>
+ <is-xml>true</is-xml>
+ </jsp-property-group>
+ </jsp-config>
 
     <!-- Faces Servlet -->
     <servlet>



-- 
| ed.burns_at_sun.com  | office: 408 884 9519 OR x31640
| homepage:         | http://ridingthecrest.com/