FYI created spec issue 817 [1] and Mojarra issue 1694 [2].

Regards,
Jakob

[1]
https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=817
[2] https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1694

2010/5/28 Jakob Korherr <jakob.korh...@gmail.com>

> Hi John,
>
> As it turns out, it is only working in Mojarra, because it violates the JSF
> specification's conversion rules. MyFaces does things right and thus it is
> not working here as you expected.
>
> However I think the enum problem is by all means a specification issue. As
> you pointed out before every other standard-converter passes through String
> values in getAsString() whereas the EnumConverter does not do it. Thus I
> will file a spec issue about this!
>
> As this will take some time until the EG decides what to do about this
> problem, I think it is the best solution to introduce a config parameter to
> enable the pass through mechanism on EnumConverter, because we won't get
> problems with the TCK but the functionality is available.
>
> Regards,
> Jakob
>
> 2010/5/28 John Wu <johnwu....@gmail.com>
>
>
>>
>> If 2.) is to be incorporated in the impl, the original exception message
>> is
>> then appropriate.
>>
>>
>> John Wu wrote:
>> >
>> > Hi Jakob,
>> >
>> > Suggestions:
>> > 1. Exception message: The value 'CardNumber' (type java.lang.String) is
>> > not an instance of the Enum type.
>> > 2. In the case the value is a String, check if it equals to one of Enum
>> > Constants' name, then ...
>> >
>> > Cheers,
>> >
>> > John Wu
>> >
>> >
>> > Jakob Korherr wrote:
>> >>
>> >> 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 <johnwu....@gmail.com>
>> >>
>> >>>
>> >>> 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 <johnwu....@gmail.com>
>> >>> >
>> >>> >>
>> >>> >> 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
>> >>
>> >>
>> >
>> >
>>
>> --
>> View this message in context:
>> http://old.nabble.com/MyFaces-2.0.0---Problem-of-rendering-Enum-tp28681934p28708291.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
>



-- 
Jakob Korherr

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

Reply via email to