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.

