Hi John,

On my opinion this is not a workaround, but rather how it really should be
done. However I agree that this could/should be easier.

To your points:
1. Yes this is really confusing. IMO it should say "The String 'CardNumber'
has to be an enum".
2. The problem here is that we somehow have to check if the String provided
in the f:selectItem is a valid enum constant or not. If we just pass through
the String value, it may end up in weird behavior on the postback, because
we can't create an enum value out of a wrong name.
3. I also had a look at them and you're right. However the specification
javadoc does not mention this fact on the EnumConverter (see [1]), but it
says that we have to throw a ConverterException if the value is no valid
enum and this is exactly what MyFaces does. So we must not change this
behavior, since it is not in the spec.

I also did some tests with Mojarra and they allow this scenario, however
they seem to handle it in another way (not in the EnumConverter, because a
blackbox test revealed that they also throw a ConverterException in that
case). I will do some further tests here and try to figure out how this
should be handled in the right way.

Regards,
Jakob

[1]
https://javaserverfaces.dev.java.net/nonav/docs/2.0/javadocs/javax/faces/convert/EnumConverter.html#getAsString%28javax.faces.context.FacesContext,%20javax.faces.component.UIComponent,%20java.lang.Object%29


2010/5/27 John Wu <[email protected]>

>
> I've thought about the type mis-match right after I posted the message. But
> I'd rather call that a workaround, not a real solution.
>
> Still, there are a few things I want to point out:
> 1. The exception message ('CardNumber' must be convertible to an enum.) is
> confusion. In fact, 'CardNumber' is indeed convertible to an enum.
> 2. The purpose of the rendering (and
>
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.getConvertedStringValue(..))
> is to get the text representation of the specified value. Here in this
> case,
> the value is already an instance of String. I don't think it's a bad idea
> of
> just returning the String value, either by
> RendererUtils.getConvertedStringValue(..) or by
> javax.faces.convert.EnumConverter.getAsString(..).
> 3. I've further checked all implementations of
> javax.faces.convert.Converter.getAsString(..). They all (except
> EnumConverter.getAsString(..)) simply return the specified value if it's an
> instance of String.
>
> So, my suggestion after further investigation is to change
> EnumConverter.getAsString(..) to follow that convention, that is, to simply
> return the specified value if it's an instance of String.
>
> Cheers,
>
> John Wu
>
>
> Jakob Korherr wrote:
> >
> > Hi John,
> >
> > The problem is that on <f:selectItem /> the attribute itemValue has to be
> > of
> > the same type as the property in the managed bean. In your case this is
> > ClientIdType.
> >
> > However you are providing the String "CardNumber" as the value which is
> > definitely not the same as the enum value ClientIdType.CardNumber. Thus
> > you
> > get the Exception.
> >
> > Try using the following:
> >
> > <f:selectItem itemValue="#{bean.propertyThatResolvesToCardNumber}"
> > itemLabel="#{msgs['labelCardNumber.full']}:" />
> >
> > with Bean.getPropertyThatResolvesToCardNumber() returning the enum value
> > ClientIdType.CardNumber.
> >
> > Regards,
> > Jakob
> >
> >
> > 2010/5/26 John Wu <[email protected]>
> >
> >>
> >> I'd say the issue exist in
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.getConvertedStringValue(FacesContext
> >> context, UIComponent component, Converter converter, Object value). In
> >> the
> >> case of rendering a selectRadio and the underlying model property type
> is
> >> an
> >> Enum, this method is called with the converter be an instance of
> >> javax.faces.convert.EnumConverter and the value be an instance of
> >> java.lang.String. Then, ideally, it may just return the value (No
> >> conversion
> >> is needed). But it delegates to
> >> javax.faces.convert.EnumConverter.getAsString(..) which expects the
> value
> >> to
> >> be an instance of the Enum, thus the following exception is thrown.
> >>
> >> javax.faces.convert.ConverterException: form:clientIdType: 'CardNumber'
> >> must
> >> be convertible to an enum.
> >>        at
> >> javax.faces.convert.EnumConverter.getAsString(EnumConverter.java:82)
> >>        at
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.getConvertedStringValue(RendererUtils.java:640)
> >>        at
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.html.HtmlRadioRendererBase.renderGroupOrItemRadio(HtmlRadioRendererBase.java:200)
> >>        at
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.html.HtmlRadioRendererBase.encodeEnd(HtmlRadioRendererBase.java:106)
> >>        at
> >>
> javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:486)
> >>        at
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:527)
> >>        at
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:296)
> >>        at
> >>
> >>
> org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:131)
> >>        at
> >>
> javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:486)
> >>        at
> >> javax.faces.component.UIComponent.encodeAll(UIComponent.java:618)
> >>        at
> >> javax.faces.component.UIComponent.encodeAll(UIComponent.java:614)
> >>        at
> >> javax.faces.component.UIComponent.encodeAll(UIComponent.java:614)
> >>        at
> >> javax.faces.component.UIComponent.encodeAll(UIComponent.java:614)
> >>        at
> >>
> >>
> org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1117)
> >>        at
> >>
> >>
> org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:231)
> >>        at
> >>
> >>
> org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:122)
> >>        at
> >>
> org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:207)
> >>        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:191)
> >>
> >>
> >> My code snippets:
> >>
> >> In clientId.xhtml
> >>        <h:selectOneRadio id="clientIdType"
> value="#{model.clientIdType}">
> >>          <f:selectItem itemValue="CardNumber"
> >> itemLabel="#{msgs['labelCardNumber.full']}:" />
> >>          <f:selectItem itemValue="UserId"
> >> itemLabel="#{msgs['labelUserId.full']}:" />
> >>        </h:selectOneRadio>
> >>
> >> In MyModel.java
> >>    private ClientIdType clientIdType;
> >>
> >>    public ClientIdType getClientIdType() {
> >>        return clientIdType;
> >>    }
> >>
> >>    public void setClientIdType(ClientIdType clientIdType) {
> >>        this.clientIdType = clientIdType;
> >>    }
> >>
> >> In ClientIdType.java
> >> public enum ClientIdType {
> >>    CardNumber("labelCardNumber.short", "labelCardNumber.full"),
> >>    UserId("labelUserId.short", "labelUserId.full");
> >>
> >>    private final String shortLabelId;
> >>    private final String fullLabelId;
> >>
> >>    private ClientIdType(String shortLabelId, String fullLabelId) {
> >>        this.shortLabelId = shortLabelId;
> >>        this.fullLabelId = fullLabelId;
> >>    }
> >>
> >>    public String getShortLabelId() {
> >>        return shortLabelId;
> >>    }
> >>
> >>    public String getFullLabelId() {
> >>        return fullLabelId;
> >>    }
> >> }
> >>
> >> --
> >> View this message in context:
> >>
> http://old.nabble.com/MyFaces-2.0.0---Problem-of-rendering-Enum-tp28681934p28681934.html
> >> Sent from the MyFaces - Users mailing list archive at Nabble.com.
> >>
> >>
> >
> >
> > --
> > Jakob Korherr
> >
> > blog: http://www.jakobk.com
> > twitter: http://twitter.com/jakobkorherr
> > work: http://www.irian.at
> >
> >
>
> --
> View this message in context:
> http://old.nabble.com/MyFaces-2.0.0---Problem-of-rendering-Enum-tp28681934p28693696.html
> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>
>


-- 
Jakob Korherr

blog: http://www.jakobk.com
twitter: http://twitter.com/jakobkorherr
work: http://www.irian.at

Reply via email to