I remember adding this feature in 2006 :)

If you have a map you actually don't need t:selectItems much. f:selectItems would suffice where labels are the keys and values are the map values.

t:selectItems is handy to autogenerate selectItems from collections like lists.

Cagatay

On Mar 14, 2009, at 10:41 PM, Simon Kitching wrote:

Hi Johannes,

On Sat, 2009-03-14 at 19:10 +0000, Johannes Ruthenberg wrote:

Simon Kitching wrote on 14.03.2009 15:39:
Have you tried this? <t:selectItems value="#{myBean.allRoles}"/>

I have, but I get a NullPointerException if I do.

Caused by: java.lang.NullPointerException
at org.apache.catalina.connector.Request.getAttribute(Request.java:877)
   at
org .apache .catalina.connector.RequestFacade.getAttribute(RequestFacade.java: 263)
   at
javax .servlet .ServletRequestWrapper.getAttribute(ServletRequestWrapper.java:82)
   at
org .apache .myfaces.context.servlet.RequestMap.getAttribute(RequestMap.java:47)
   at
org .apache .myfaces.util.AbstractAttributeMap.put(AbstractAttributeMap.java:104)
   at
org .apache .myfaces.util.AbstractAttributeMap.put(AbstractAttributeMap.java:38)
   at
org .apache .myfaces .custom .selectitems .AbstractUISelectItems .putIteratorToRequestParam(AbstractUISelectItems.java:131)
   at
org .apache .myfaces .custom .selectitems .AbstractUISelectItems.createSelectItems(AbstractUISelectItems.java: 107)
   at
org .apache .myfaces .custom .selectitems .AbstractUISelectItems.getValue(AbstractUISelectItems.java:75)
   at
org .apache .myfaces .shared_impl .util.SelectItemsIterator.hasNext(SelectItemsIterator.java:128)
   at
org .apache .myfaces .shared_impl .renderkit .RendererUtils.internalGetSelectItemList(RendererUtils.java:557)
   at
org .apache .myfaces .shared_impl .renderkit.RendererUtils.getSelectItemList(RendererUtils.java:542)
   at
org .apache .myfaces .shared_impl .renderkit .html .HtmlCheckboxRendererBase .renderCheckboxList(HtmlCheckboxRendererBase.java:117)
   at
org .apache .myfaces .shared_impl .renderkit .html .HtmlCheckboxRendererBase.encodeEnd(HtmlCheckboxRendererBase.java:65)
   at
javax .faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:624)
   ... 76 more

Looking at the actual implementation of the t:selectItems tag, I think this is consistent (it sets the current map value to the request under the provided variable name and then calls a method which retrieves this and tries to get the label and value for the select item -- this fails
if no variable name is given). It just doesn't fit what the tag is
supposed to do as per the documentation, at least as I understand it.

I could simply built the list of SelectItem instances myself and set
this in my bean. But I actually wouldn't want to handle more of the
internal UI elements than necessary, so if the tag could do this, I
think that would be the better approach. I also wonder if the
documentation is wrong here or the tag class (a matter of perspective, I
guess). ;-)


I'm looking at the code now, and it seems clear enough to me.

Class SelectItemsTag has this comment:
// Generated from class
   org.apache.myfaces.custom.selectitems.AbstractUISelectItems.

This is part of our automatic-tag-generation: generally, tag classes are
generated from annotations on the component class. So the component
class is AbstractUISelectItems.

And AbstractUISelectItems has:
   public Object getValue() {
       Object value = super.getValue();
       return createSelectItems(value);
   }

Method createSelectItems contains:
   List items = new ArrayList();
   if (value instanceof SelectItem[]) {
       return (SelectItem[]) value;
   }
   else if (value instanceof Collection) {
       ....
   }
   else if (value instanceof Map) {
       Map map = (Map) value;
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
{
           Entry currentItem = (Entry) iter.next();
           putIteratorToRequestParam(currentItem.getValue());
           SelectItem selectItem = createSelectItem();
           removeIteratorFromRequestParam();
           items.add(selectItem);
       }
   }
   return (SelectItem[]) items.toArray(new SelectItem[0]);


So clearly, when evaluating the value expression returns a Map, then the
component returns an array of SelectItem objects that have been built
from the map values.

This code is from the current trunk. Unfortunately due to svn
rearrangements in Sept 2008 when the new tomahawk build framework was
introduced, it isn't easy to track svn history for components anymore.
However I'm pretty sure this is not a new feature. It certainly was
there in september 2008, and you say you are using 1.1.8 which was
released in November 2008.

You say you are using tomahawk-1.1.8, which is the latest release. Are
you sure about that?

However from memory I'm pretty sure this is not a new feature...

Regards,
Simon


Reply via email to