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