myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jakob Korherr <jakob.korh...@gmail.com>
Subject Re: Bad Bug: SelectOneMenu, SelectItems, _SystemItemsUtil, and the missing conversion
Date Wed, 06 Jan 2010 20:59:14 GMT
You're welcome!

Here's the explanation to your problem:

You always have to set itemValue to an object with the same type as the
value attribute of the surrounding t:selectXXX. This is also the type you
have to write a converter for.

In your case:
<t:selectOneMenu id="daysOfWeekList"
                value="#{calendar.day}">
   <t:selectItems var="day"
                  value="#{daysEnumList}"
                  itemLabel="#{day.label}"
                  itemValue="#{day}"/>
   <f:converter converterId="dayEnumConverter"/>
</t:selectOneMenu>

#{calendar.day} references to a property of type DaysOfWeek, thus itemValue
has also to be of type DaysOfWeek and you have to write a converter, because
it is no String.

If you set itemValue="#{day.label}", you'll also have to change
#{calendar.day} to point to a String property. But that's of course not what
you want!

I hope it is now clear to you.

And sorry for my first short answer, I did not have the time to write this
earlier.

Regards,
Jakob Korherr

2010/1/6 Ogrady, John <john.ogrady@citi.com>

>  I do so love "secret sauce" answers.  I'm not surprised that it was
> something I did (or didn't do).  This is my first foray into JSF teritory
> after years of Spring MVC, Struts, and Webwork, and faces is by far the most
> frustrating framework of all.
>
> Thanks for the quick reply!
>
> ___________________________________________________________
> John O'Grady, Dragon Tamer
> The important thing is not to stop questioning. - Albert Einstein
> ___________________________________________________________
>
>
> -----Original Message-----
> From: sethfromaustria@gmail.com [mailto:sethfromaustria@gmail.com] On
> Behalf Of Jakob Korherr
> Sent: Wednesday, January 06, 2010 3:09 PM
> To: MyFaces Discussion
> Subject: Re: Bad Bug: SelectOneMenu, SelectItems, _SystemItemsUtil, and the
> missing conversion
>
> Hi John,
>
> Use >itemValue="#{day}"< and it will work.
>
> Regards,
> Jakob Korherr
>
>
> 2010/1/6 Ogrady, John <john.ogrady@citi.com>
>
> > Java 1.5
> > MyFaces 1.1.7
> > Tomahawk 1.1.9
> > Spring 2.5.6
> > Weblogic 9.2.3
> >
> >
> > All I wanted to do was display a drop-down list of enums.  It seemed
> > simple enough, with examples all over the 'net.  Apparently, myfaces
> > has decided that using anything other than strings for a drop down is "no
> - not yours".
> >
> > The setup:
> >
> >
> > My example enum:
> > ------------------------------------------------------------
> > package com.facets;
> > import java.util.Arrays;
> > import java.util.List;
> > public enum DaysOfWeek {
> >    SUNDAY("Sunday"),
> >    MONDAY("Monday"),
> >    TUESDAY("Tuesday"),
> >    WEDNESDAY("Wednesday"),
> >    THURSDAY("Thursday"),
> >    FRIDAY("Friday"),
> >    SATURDAY("Saturday");
> >
> >    private static List<DaysOfWeek> dayList =
> > Arrays.asList(DaysOfWeek.values());
> >
> >    private String label;
> >
> >    private DaysOfWeek(String label) {
> >        this.label = label;
> >    }
> >    public String getLabel() {
> >        return this.label;
> >    }
> >    public static DaysOfWeek getByLabel(String label) {
> >        for(DaysOfWeek day : dayList) {
> >            if(day.getLabel().equals(label)) {
> >                return day;
> >            }
> >        }
> >        return null;
> >    }
> >    public static final List<DaysOfWeek> getAllList() {
> >        return dayList;
> >    }
> > }
> > ------------------------------------------------------------
> >
> > JSF Converter:
> > ------------------------------------------------------------
> > package com.facets;
> > import javax.faces.component.UIComponent;
> > import javax.faces.context.FacesContext; import
> > javax.faces.convert.Converter; import
> > javax.faces.convert.ConverterException;
> > public class DayEnumConverter implements Converter {
> >    public Object getAsObject(FacesContext context, UIComponent
> > component, String value)
> >          throws ConverterException {
> >        DaysOfWeek day = DaysOfWeek.getByLabel(value);
> >        return (day==null ? DaysOfWeek.SUNDAY : day);
> >    }
> >    public String getAsString(FacesContext context, UIComponent
> > component, Object object)
> >          throws ConverterException {
> >        if(object instanceof String) {
> >            return (String)object;
> >        }
> >        if(!(object instanceof DaysOfWeek)) {
> >            return "";
> >        }
> >        return ((DaysOfWeek)object).getLabel();
> >    }
> > }
> > ------------------------------------------------------------
> >
> >
> > Spring definition to get a list of the enums:
> > ------------------------------------------------------------
> > <bean id="daysEnumList"
> >      class="com.facets.DaysOfWeek"
> >      factory-method="getAllList" />
> > ------------------------------------------------------------
> >
> >
> > A simple drop down list made from an ArrayList of Enums.
> > ------------------------------------------------------------
> > <h:outputLabel for="daysOfWeekList" value="#{labels.dayList}" />
> > <t:selectOneMenu id="daysOfWeekList"
> >                 value="#{calendar.day}">
> >    <t:selectItems var="day"
> >                   value="#{daysEnumList}"
> >                   itemLabel="#{day.label}"
> >                   itemValue="#{day.label}"/>
> >    <f:converter converterId="dayEnumConverter"/> </t:selectOneMenu>
> > ------------------------------------------------------------
> >
> > Assumptions:
> > 1) I'm using SpringBeanVariableResolver to get the "daysEnumList"
> > object from the spring application context.
> > 2) The problem goes away if I take the daysOfWeekList selectOneMenu
> > control off the jsp page.  Also, there is another dropdown list using
> > only strings and that works just fine.
> > 3) The converter is properly listed in the faces-context.xml file, as
> > it is called normally during the JSF lifecycle - at least until the bug
> hits.
> >
> >
> > The Bug:
> > When I submit a form containing the above selectOneMenu control, the
> > list of which is created from a Java 5 Enum, I get this error in the
> logs:
> >
> > ------------------------------------------------------------
> > DEBUG | 2010-01-06 13:28:53,912 | LifecycleImpl.java:178 | exiting
> > from lifecycle.execute in RESTORE_VIEW(1) because getRenderResponse is
> > true from one of the after listeners
> > ------------------------------------------------------------
> >
> > This means that backing bean never gets bound to the form values, and
> > the form action is never called.  I never get past the "Apply Request
> Values"
> > step of the faces lifecycle.
> >
> > Take a look at this stack trace...
> >
> > ------------------------------------------------------------
> > Daemon Thread [[ACTIVE] ExecuteThread: '0' for queue:
> > 'weblogic.kernel.Default (self-tuning)'] (Suspended)
> > _SelectItemsUtil.matchValue(Object, Iterator) line: 65
> > HtmlSelectOneMenu(UISelectOne).validateValue(FacesContext, Object) line:
> > 77
> >  HtmlSelectOneMenu(UIInput).validate(FacesContext) line: 428
> >  HtmlSelectOneMenu(UIInput).processValidators(FacesContext) line: 245
> >  HtmlTag(UIComponentBase).processValidators(FacesContext) line: 866
> >  HtmlForm(UIForm).processValidators(FacesContext) line: 78
> >  UIViewRoot(UIComponentBase).processValidators(FacesContext) line: 866
> >  UIViewRoot.processValidators(FacesContext) line: 169
> >  ProcessValidationsExecutor.execute(FacesContext) line: 32
> > LifecycleImpl.executePhase(FacesContext, PhaseExecutor,
> > PhaseListenerManager) line: 105
> >  LifecycleImpl.execute(FacesContext) line: 80
> > FacesServlet.service(ServletRequest, ServletResponse) line: 143
> >  StubSecurityHelper$ServletServiceAction.run() line: 225
> > StubSecurityHelper.invokeServlet(ServletRequest, HttpServletRequest,
> > ServletRequestImpl, ServletResponse, HttpServletResponse, Servlet)
> > line: 127  ServletStubImpl.execute(ServletRequest, ServletResponse,
> > FilterChainImpl)
> > line: 283
> >  TailFilter.doFilter(ServletRequest, ServletResponse, FilterChain)
> > line: 26  FilterChainImpl.doFilter(ServletRequest, ServletResponse)
> > line: 42  ExtensionsFilter.doFilter(ServletRequest, ServletResponse,
> > FilterChain)
> > line: 246
> >  FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 42
> > NavigationFilter.doFilter(ServletRequest, ServletResponse,
> > FilterChain)
> > line: 93
> >  DelegatingFilterProxy.invokeDelegate(Filter, ServletRequest,
> > ServletResponse, FilterChain) line: 236
> > DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse,
> > FilterChain) line: 167
> >  FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 42
> > ExtensionsFilter.doFilter(ServletRequest, ServletResponse,
> > FilterChain)
> > line: 301
> >  FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 42
> >  WebAppServletContext$ServletInvocationAction.run() line: 3212
> > AuthenticatedSubject.doAs(AbstractSubject, PrivilegedAction) line: 321
> > SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject,
> > PrivilegedAction) line: 121
> >  WebAppServletContext.securedExecute(HttpServletRequest,
> > HttpServletResponse, boolean) line: 1983
> > WebAppServletContext.execute(ServletRequestImpl, ServletResponseImpl)
> > line: 1890
> >  ServletRequestImpl.run() line: 1344
> >  ExecuteThread.execute(Runnable) line: 209
> >  ExecuteThread.run() line: 181
> > ------------------------------------------------------------
> >
> > The bug is at line 65 of _SelectItemsUtil.
> >
> > ------------------------------------------------------------
> > 44 public static boolean matchValue(Object value,
> > 45                 Iterator selectItemsIter)
> > 46 {
> > 47     while (selectItemsIter.hasNext())
> > 48     {
> > 49         SelectItem item = (SelectItem) selectItemsIter.next();
> > 50         if (item instanceof SelectItemGroup)
> > 51         {
> > 52             SelectItemGroup itemgroup = (SelectItemGroup) item;
> > 53            SelectItem[] selectItems = itemgroup.getSelectItems();
> > 54             if (selectItems != null
> > 55                             && selectItems.length > 0
> > 56                             && matchValue(value, Arrays.asList(
> > 57                                             selectItems).iterator()))
> > 58             {
> > 59                 return true;
> > 60             }
> > 61         }
> > 62         else
> > 63         {
> > 64             Object itemValue = item.getValue();
> > 65             if (value==itemValue || (itemValue.equals(value)))
> > 66             {
> > 67                 return true;
> > 68             }
> > 69         }
> > 70     }
> > 71     return false;
> > 72 }
> > ------------------------------------------------------------
> >
> >
> > The problem is that at this point, the "value" is the value that was
> > selected in the dropdown.  The CONVERTED value - compliments of line
> > 428 in the UIInput class:
> >
> > ------------------------------------------------------------
> > 424 Object convertedValue = getConvertedValue(context,
> > submittedValue);
> > 425
> > 426 if (!isValid()) return;
> > 427
> > 428 validateValue(context, convertedValue);
> > ------------------------------------------------------------
> >
> > BUT - the "item" object is from an Iterator created on line 77 of
> > UISelectOne, which only has the string values of the select component.
> >
> > This means when "item.getValue()" is called on line 64 (above), you
> > are getting the string value from whatever selectitem entry is
> > currently targeted - and of course the object version of the selected
> > value isn't going to equal its non-converted string value.
> >
> > Either I'm missing something and there's some configuration I missed
> > to fix this (which would make this behaviour a horrible default), or
> > this is a pretty big bug that just cost me five hours of development
> time.
> >
> > If no one cares about JSF 1.1 implementations anymore, just let me
> > know and I'll not spend the time posting here.  Otherwise, any chance
> > this could be fixed?
> >
> > ___________________________________________________________
> > John O'Grady
> > Dragon Tamer
> >
> > Human beings, who are almost unique in having the ability to learn
> > from the experience of others, are also remarkable for their apparent
> > disinclination to do so.
> > - Douglas Adams
> >
> > Those who do not learn from history are doomed to repeat it.
> > - George Santayana
> >
> > Qui tacet consentit
> > (Silence implies consent)
> > ___________________________________________________________
> >
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message