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 <[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
>> 
>> 
> 
> 

-- 
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.

Reply via email to