IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector $ ValueExpressionType to class java.lang.Boolean

I have a <o:validateBean />

class level problem with OmniFaces 1.11 ( http://showcase.omnifaces.org/validators/validateBean )

Basically, I am trying to validate the same bean using two validation groups according to the button I click:

            <h:commandButton value="Mandatory">
                <o:validateBean value="#{testBean.pojo}" validationGroups="bo.ihm.beans.Mandatory" />
            </h:commandButton>

            <h:commandButton value="Optional">
                <o:validateBean value="#{testBean.pojo}" validationGroups="javax.validation.groups.Default" />
            </h:commandButton>

      

Whenever I click the button I get

GRAVE: Exception occured while doing validation.
javax.el.ELException: /testOmnifaces.xhtml @21,74 value="#{testBean.pojo.forain}": java.lang.IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.Boolean
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
    at org.omnifaces.el.ExpressionInspector.getValueReference(ExpressionInspector.java:43)
    at org.omnifaces.taghandler.ValidateBean$6.invoke(ValidateBean.java:331)
    at org.omnifaces.taghandler.ValidateBean$6.invoke(ValidateBean.java:326)
    at org.omnifaces.util.Components$ForEach$1.visit(Components.java:508)
    at org.omnifaces.util.Components$ForEach$TypesVisitCallback.visit(Components.java:573)
    at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIForm.visitTree(UIForm.java:371)
    at org.omnifaces.util.Components$ForEach.invoke(Components.java:541)
    at org.omnifaces.util.Components$ForEach.invoke(Components.java:505)
    at org.omnifaces.taghandler.ValidateBean.forEachInputWithMatchingBase(ValidateBean.java:326)
    at org.omnifaces.taghandler.ValidateBean.access$400(ValidateBean.java:151)
    at org.omnifaces.taghandler.ValidateBean$3.run(ValidateBean.java:286)
    at org.omnifaces.taghandler.ValidateBean$ValidateBeanCallback.invoke(ValidateBean.java:430)
    at org.omnifaces.util.Events$1.invoke(Events.java:278)
    at org.omnifaces.util.Events$4.beforePhase(Events.java:312)
    at org.omnifaces.eventlistener.CallbackPhaseListener.beforePhase(CallbackPhaseListener.java:63)
    at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:228)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:99)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:696)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:521)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:138)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:564)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:213)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1097)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:448)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1031)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:200)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:446)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:271)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:246)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.el.ELException: java.lang.IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.Boolean
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:229)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    ... 44 more
Caused by: java.lang.IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.Boolean
    at com.sun.el.lang.ELSupport.coerceToBoolean(ELSupport.java:189)
    at com.sun.el.lang.ELSupport.coerceToType(ELSupport.java:394)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:227)
    ... 45 more

      

testWithClassLevelValidation.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:o="http://omnifaces.org/ui">

<f:metadata>
    <f:viewAction action="#{testBean.init}" />
</f:metadata>

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Test</title>
</h:head>

<h:body>

    <h:form id="formaliteACCRE">
        <h:panelGrid columns="1" style="width: 100%;">
            <h:panelGrid columns="2" style="width: 100%; display: inline-block;">
                <h:outputLabel for="forain">Yes or No ?</h:outputLabel>
                <h:selectBooleanCheckbox id="forain" value="#{testBean.pojo.forain}">
                    <f:ajax execute="forain" render="groupeDomicile" />
                </h:selectBooleanCheckbox>
            </h:panelGrid>

            <h:panelGroup id="groupeDomicile">
                <h:outputText value="Yes" rendered="#{testBean.pojo.forain}" />
                <h:outputText value="No" rendered="#{not testBean.pojo.forain}" />
            </h:panelGroup>

            <h:inputText id="numeroSecu" value="#{testBean.pojo.numeroSecuriteSociale}" maxlength="13" size="13" />
            <h:inputText id="numeroSecuCle" value="#{testBean.pojo.cleSecuriteSociale}" maxlength="2" size="3" />

            <h:panelGrid columns="2" style="width: 100%; display: inline-block;">
                <h:inputText id="mandatory" value="#{testBean.pojo.mandatory}" maxlength="13" size="13" />
                <h:outputText value="*" style="color:red;" />
            </h:panelGrid>

            <f:ajax execute="@form" render="@form">

                <h:commandButton value="Mandatory">
                    <o:validateBean value="#{testBean.pojo}" validationGroups="bo.ihm.beans.Mandatory" />
                </h:commandButton>

                <h:commandButton value="Optional">
                    <o:validateBean value="#{testBean.pojo}" validationGroups="javax.validation.groups.Default" />
                </h:commandButton>
            </f:ajax>
        </h:panelGrid>

        <ui:remove> ################################################################################################ </ui:remove>
        <ui:remove>                             ===== MESSAGES D'ERREURS =====                                       </ui:remove>
        <ui:remove> ################################################################################################ </ui:remove>

        <h:panelGroup id="messagesErreur">
            <h:panelGrid class="dr-pnl" width="100%" rendered="#{not empty facesContext.messageList}">
                <h:messages style="color:red;" />
            </h:panelGrid>
        </h:panelGroup>
    </h:form>
</h:body>
</html>

      

TestBean.java:

package bo.ihm.beans;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.validation.Valid;

@ViewScoped
@ManagedBean(name = "testBean")
public class TestBean implements Serializable {

    private static final long serialVersionUID = 1L;

    @Valid
    private Pojo pojo;

    public Pojo getPojo() {
        return pojo;
    }

    public void init() {
        pojo = new Pojo();
        pojo.setNumeroSecuriteSociale("2531257351038");
        pojo.setCleSecuriteSociale("22");
    }

    public void setPojo(final Pojo pPojo) {
        this.pojo = pPojo;
    }
}

      

Pojo.java:

package bo.ihm.beans;

import org.hibernate.validator.constraints.NotEmpty;

@NumeroSecuriteSociale
public class Pojo {

    private boolean forain;
    private String cleSecuriteSociale;
    private String numeroSecuriteSociale;

    @NotEmpty(groups = Mandatory.class)
    private String mandatory;

    public String getCleSecuriteSociale() {
        return cleSecuriteSociale;
    }

    public String getMandatory() {
        return mandatory;
    }

    public String getNumeroSecuriteSociale() {
        return numeroSecuriteSociale;
    }

    public boolean isForain() {
        return forain;
    }

    public void setCleSecuriteSociale(final String pCleSecuriteSociale) {
        cleSecuriteSociale = pCleSecuriteSociale;
    }

    public void setForain(final boolean pForain) {
        forain = pForain;
    }

    public void setMandatory(final String pMandatory) {
        mandatory = pMandatory;
    }

    public void setNumeroSecuriteSociale(final String pNumeroSecuriteSociale) {
        numeroSecuriteSociale = pNumeroSecuriteSociale;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("Pojo [forain=");
        builder.append(forain);
        builder.append(", cleSecuriteSociale=");
        builder.append(cleSecuriteSociale);
        builder.append(", numeroSecuriteSociale=");
        builder.append(numeroSecuriteSociale);
        builder.append(", mandatory=");
        builder.append(mandatory);
        builder.append("]");
        return builder.toString();
    }
}

      

full code is available at https://github.com/ErwanLeroux/Bo_ihm_test_omnifaces just run clean jetty: run-war et go to http: // localhost: 14080 / bo_ihm / testWithClassLevelValidation.xhtml

The second page http: // localhost: 14080 / bo_ihm / testWithoutClassLevelValidation.xhtml is its demonstration that class level constraints don't work, when I click the "whenever" button I should get a validation error: "Pojo [forain = false, cleSecuriteSociale = 22, numeroSecuriteSociale = 2531257351038, required = null] not valid '

+3


source to share


1 answer


It turns out that implicit EL coercion causes all of this. We passed internal values ​​such as ValueExpressionType.PROPERTY

and ValueExpressionType.METHOD

to indicate whether the EL expression is a function call (getter / setter) or method call (action). However, this approach fails if the value has an implicit EL confirmation, for example java.lang.Boolean

, to which EL would implicitly convert, for example. string "true"

to boolean true

.

This approach of passing internal values ​​to denote the kind of EL expression has been around since OmniFaces 2.0 was used to parse an EL expression into <o:grapicImage value>

and extract any EL method arguments so that they can be converted and passed as HTTP request string parameters. This explains why it still works great in OmniFaces 1.x.



As of this commit , this has been fixed for OmniFaces 2.2.

+1


source







All Articles