【问题标题】:IllegalArgumentException: Cannot convert PROPERTY of type class org.omnifaces.el.ExpressionInspector$ValueExpressionType to class java.lang.BooleanIllegalArgumentException:无法将类型类 org.omnifaces.el.E​​xpressionInspector$ValueExpressionType 的属性转换为类 java.lang.Boolean
【发布时间】:2015-07-03 14:32:09
【问题描述】:

我在班级级别 (http://showcase.omnifaces.org/validators/validateBean) 遇到 OmniFaces 1.11 <o:validateBean /> 的问题

基本上,我正在尝试根据我单击的按钮使用两个验证组来验证同一个 bean:

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

每当我点击一个按钮时,我都会得到

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();
    }
}

完整代码可在https://github.com/ErwanLeroux/Bo_ihm_test_omnifaces 获得,只需运行 clean jetty:run-war 等转到http://localhost:14080/bo_ihm/testWithClassLevelValidation.xhtml

第二页http://localhost:14080/bo_ihm/testWithoutClassLevelValidation.xhtml 是她证明类级别约束不起作用,当我单击任何按钮时,我应该收到这样的验证错误消息:'Pojo [forrain=false, cleSecuriteSociale=22, numeroSecuriteSociale=2531257351038,强制=null] 无效'

【问题讨论】:

  • 转载,错误是由 h:selectBooleanCheckbox 触发的(删除它,问题就消失了)。我们将对其进行调查并修复 2.2。
  • 谢谢。我降级到 1.10 版,我无法重现此问题。我会问一个新问题,因为 在类级别的行为不像我认为的那样。

标签: jsf bean-validation omnifaces


【解决方案1】:

事实证明,隐式 EL 强制是造成这一切的原因。我们传递了像ValueExpressionType.PROPERTYValueExpressionType.METHOD 这样的内部值来指示EL 表达式是表示属性(getter/setter)调用还是方法(动作)调用。但是,如果该值具有隐式 EL 强制支持(如 java.lang.Boolean),则此方法将失败,EL 将在其上隐式转换,例如"true" 的字符串到布尔值 true

这种传递内部值以指示 EL 表达式类型的方法是因为 OmniFaces 2.0 用于分解 &lt;o:grapicImage value&gt; 中的 EL 表达式并提取任何 EL 方法参数,以便它们可以转换并作为 HTTP 查询字符串参数传递.这就解释了为什么它在 OmniFaces 1.x 中仍然可以正常工作。

根据this commit,该问题已针对 OmniFaces 2.2 进行了修复。

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    • 2021-07-08
    • 1970-01-01
    • 2020-12-19
    • 2017-02-23
    相关资源
    最近更新 更多