ICEfaces
  1. ICEfaces
  2. ICE-8480

ELException - Cannot convert 0 of type class java.lang.Byte to class java.lang.Boolean

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: 3.1
    • Fix Version/s: 3.2
    • Component/s: ICE-Components
    • Labels:
      None
    • Environment:
      ICEfaces 3.1.0
    • Workaround Exists:
      Yes
    • Workaround Description:
      Application bean property getter/setter be changed to type boolean, and do the byte <-> boolean conversion itself inside the getter and setter methods.

      Description

      A custom converter has been created so that the ice:selectBooleanCheckbox can use a Byte value instead of a Boolean. Due to a known issue with JSF, a custom renderer for the CheckboxRenderer is required so that the getAsObject() method can be correctly called.

      This code is working fine with ICEfaces 1.8.x. Upon migration to ICEfaces 3.1.0 this code is no longer working and is throwing the following exception:

      javax.el.ELException: /welcomeICEfaces.xhtml @22,94 value="#{testBean.checkBoxValue}": Cannot convert 0 of type class java.lang.Byte to class java.lang.Boolean
      at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
      at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
      at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
      at javax.faces.component.UIOutput.getValue(UIOutput.java:169)
      at com.icesoft.faces.renderkit.dom_html_basic.DomBasicInputRenderer.getValue(DomBasicInputRenderer.java:43)
      at com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer.getValue(DomBasicRenderer.java:143)
      at com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer.encodeBegin(CheckboxRenderer.java:84)
      at com.icesoft.faces.component.ext.renderkit.CheckboxRenderer.encodeBegin(CheckboxRenderer.java:33)
      at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:820)
      at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
      at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)
      at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129)
      at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1757)
      at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
      at org.icefaces.impl.renderkit.RendererWrapper.encodeChildren(RendererWrapper.java:49)
      at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1757)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
      at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402)
      at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
      at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
      at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:662)

        Activity

        Hide
        Arran Mccullough added a comment -

        Attached test case that shows the issue in ICEfaces 3.1.0. Error is thrown on immediate access/rendering of the page.

        Show
        Arran Mccullough added a comment - Attached test case that shows the issue in ICEfaces 3.1.0. Error is thrown on immediate access/rendering of the page.
        Hide
        Deryk Sinotte added a comment -

        From what I can tell, the converter methods are never called at all. I couldn't really tell why but then I finally tried some web searches and apparently this is "on purpose" - converters are not supported for this component in JSF 2.0.

        http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-238

        So it's a regression in the sense that this used to work in previous versions of ICEfaces but we may need to do some work to get it working again in the current version. The custom renderer provided is supposed to help with this issue but I don't see an instance of it being created so it's not being overridden properly for some reason.

        Show
        Deryk Sinotte added a comment - From what I can tell, the converter methods are never called at all. I couldn't really tell why but then I finally tried some web searches and apparently this is "on purpose" - converters are not supported for this component in JSF 2.0. http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-238 So it's a regression in the sense that this used to work in previous versions of ICEfaces but we may need to do some work to get it working again in the current version. The custom renderer provided is supposed to help with this issue but I don't see an instance of it being created so it's not being overridden properly for some reason.
        Hide
        Mark Collette added a comment -

        It looks like where the exception is thrown is where it gets the value, which would later then be fed to the converter. So it happens before the converter would even have a chance to operate.

        So in the basic EL coercion being used by the ValueExpression, to coerce between the component property's Boolean type and the bean property's Byte type, here are the rules:

        http://commons.apache.org/el/api/org/apache/commons/el/Coercions.html

        coerce A to Number type N
        A is Boolean
        error

        coerce A to Boolean
        A is null or ""
        return false
        A is Boolean
        return A
        A is String
        Boolean.valueOf(A) throws exception
        error
        return Boolean.valueOf(A)
        otherwise
        error

        In both directions, it's an error.

        So the question is, why can't the app provide a different bean property getter/setter that is typed Boolean and does the conversion itself.

        Show
        Mark Collette added a comment - It looks like where the exception is thrown is where it gets the value, which would later then be fed to the converter. So it happens before the converter would even have a chance to operate. So in the basic EL coercion being used by the ValueExpression, to coerce between the component property's Boolean type and the bean property's Byte type, here are the rules: http://commons.apache.org/el/api/org/apache/commons/el/Coercions.html coerce A to Number type N A is Boolean error coerce A to Boolean A is null or "" return false A is Boolean return A A is String Boolean.valueOf(A) throws exception error return Boolean.valueOf(A) otherwise error In both directions, it's an error. So the question is, why can't the app provide a different bean property getter/setter that is typed Boolean and does the conversion itself.
        Hide
        Mark Collette added a comment -

        The code in the custom renderer is only applicable to decode, of converting a submittedValue. This exception happens at render time on the first lifecycle, and doesn't make it to any postback where decode would be relevant.

        Show
        Mark Collette added a comment - The code in the custom renderer is only applicable to decode, of converting a submittedValue. This exception happens at render time on the first lifecycle, and doesn't make it to any postback where decode would be relevant.
        Hide
        Deryk Sinotte added a comment -

        Slight correction to the last comment. I do see the customer renderer being created but it's methods are not invoked - including the getConvertedValue() method.

        Show
        Deryk Sinotte added a comment - Slight correction to the last comment. I do see the customer renderer being created but it's methods are not invoked - including the getConvertedValue() method.
        Hide
        Deryk Sinotte added a comment -

        We can suggest the workaround. The original question related to the fact that "this worked before and doesn't now" during their migration from 1.8 to 3.x.

        Show
        Deryk Sinotte added a comment - We can suggest the workaround. The original question related to the fact that "this worked before and doesn't now" during their migration from 1.8 to 3.x.
        Hide
        Mark Collette added a comment -

        Were they using JSF 1.1 or JSF 1.2 with ICEfaces 1.8.x? That would affect the ValueBinding versus ValueExpression wiring, and it could be that affects the ValueBiding/ValueExpression's type usage with coercion. Or maybe JSF 2 changes how that's wired up. We could go into our own renderer and add code to print out the ValueBinding or ValueExpression's type, and see if that was Boolean or just Object, back in ICEfaces 1.8 and now in ICEfaces 3.1 to see if that's changed.

        Show
        Mark Collette added a comment - Were they using JSF 1.1 or JSF 1.2 with ICEfaces 1.8.x? That would affect the ValueBinding versus ValueExpression wiring, and it could be that affects the ValueBiding/ValueExpression's type usage with coercion. Or maybe JSF 2 changes how that's wired up. We could go into our own renderer and add code to print out the ValueBinding or ValueExpression's type, and see if that was Boolean or just Object, back in ICEfaces 1.8 and now in ICEfaces 3.1 to see if that's changed.
        Hide
        Deryk Sinotte added a comment -

        This isn't "solved" yet but I did convert the app back to a 1.8 version and confirmed that it worked. However my new theory is that it appears to be an issue with the resolution of the ValueExpression $

        {textBean.checkBoxValue}

        (which occurs prior to the converters being called).

        First of all, I updated the el-api and el-impl libs I was using to 2.2.1_b04 and then set the following context parameter:

        <context-param>
        <param-name>com.sun.faces.expressionFactory</param-name>
        <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
        </context-param>

        I still ended up with the same issue but got a bit more information on the cause:

        Caused by: java.lang.IllegalArgumentException: Cannot convert 0 of type class java.lang.Byte to class java.lang.Boolean
        at com.sun.el.lang.ELSupport.coerceToBoolean(ELSupport.java:178)
        at com.sun.el.lang.ELSupport.coerceToType(ELSupport.java:379)
        at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:222)
        at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)

        Debugging this area showed that the coersion was being done based on the fact that there is an "expected type" for this expression. In this case a Boolean. Screen shot shows the relevant code involved.

        I haven't verified with the ICEfaces 1.x code yet but I suspect that there were no ValueExpressions with expectedTypes back in the JSF 1.2 days and so there was no attempted coercion to the expected type and therefore no problem appeared before the converters got a chance to run.

        Show
        Deryk Sinotte added a comment - This isn't "solved" yet but I did convert the app back to a 1.8 version and confirmed that it worked. However my new theory is that it appears to be an issue with the resolution of the ValueExpression $ {textBean.checkBoxValue} (which occurs prior to the converters being called). First of all, I updated the el-api and el-impl libs I was using to 2.2.1_b04 and then set the following context parameter: <context-param> <param-name>com.sun.faces.expressionFactory</param-name> <param-value>com.sun.el.ExpressionFactoryImpl</param-value> </context-param> I still ended up with the same issue but got a bit more information on the cause: Caused by: java.lang.IllegalArgumentException: Cannot convert 0 of type class java.lang.Byte to class java.lang.Boolean at com.sun.el.lang.ELSupport.coerceToBoolean(ELSupport.java:178) at com.sun.el.lang.ELSupport.coerceToType(ELSupport.java:379) at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:222) at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) Debugging this area showed that the coersion was being done based on the fact that there is an "expected type" for this expression. In this case a Boolean. Screen shot shows the relevant code involved. I haven't verified with the ICEfaces 1.x code yet but I suspect that there were no ValueExpressions with expectedTypes back in the JSF 1.2 days and so there was no attempted coercion to the expected type and therefore no problem appeared before the converters got a chance to run.
        Hide
        Mark Collette added a comment -

        Since this is likely a difference of enhanced coercion strictness in the newer EL library, and the exception happens when getting the value property, before the Converter comes into play, the simplest solution would be for the application to provide converting getter/setter methods. The value property on this ICE component is inherited from the JSF super-class, so it's not really our property to alter to try to loosen it's typing. And I doubt it would be good to generally loosen the typing on properties.

        Show
        Mark Collette added a comment - Since this is likely a difference of enhanced coercion strictness in the newer EL library, and the exception happens when getting the value property, before the Converter comes into play, the simplest solution would be for the application to provide converting getter/setter methods. The value property on this ICE component is inherited from the JSF super-class, so it's not really our property to alter to try to loosen it's typing. And I doubt it would be good to generally loosen the typing on properties.

          People

          • Assignee:
            Mark Collette
            Reporter:
            Arran Mccullough
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: