使用转换器

时间:2017-12-02 17:13:30

标签: java jsf exception nullpointerexception omnifaces

我正在使用OmniFaces'omnifaces.SelectItemsConverter,因此我可以在selectOneMenu中显示对象的字符串值。一切正常,直到验证失败(f:validateDoubleRange)。一旦验证失败,无论我做什么,我在NullPointerException中显示的对象的equals方法中得到selectOneMenu

这是等于方法:

@Override
public boolean equals(Object obj) {
    Car other = (Car) obj;
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    if (!number.equals(other.number))
        return false;
    return true;
}

这是我使用OmniFaces的转换器

的地方
<h:selectOneMenu id="id_1" value="#{myBean.car}" converter="omnifaces.SelectItemsConverter">
    <f:selectItems value="#{myBean.cars}" />
</h:selectOneMenu>

这是导致NullPointerException

的验证
<h:inputText id="nom" value="#{myBean.num}"
                style="height: 24px; "><f:validateDoubleRange minimum="0.0"/></h:inputText>

我在这一行得到了例外:

if (!number.equals(other.number))

other.number没问题,但number为空

为什么this.number为空?

1 个答案:

答案 0 :(得分:0)

根本原因

问题的根本原因是在视图内的任何输入组件验证失败后,JSF默认处理输入组件状态。

accepted answer中已经很好地解释了这一点。

<强>解决方案

因此,在您的特定情况下,如前面提到的答案建议,您需要指示JSF重置输入组件状态(对于h:selectOneMenu最重要)并从中提取/刷新它们的值验证失败后支持bean模型。

如果您使用 JSF 2.2及更高版本,您可以这样做,例如,像这样

<h:commandButton value="Submit"  actionListener="#{myBean.onSubmit()}" >
    <f:ajax execute=":form:nom :form:id_1" 
            render=":form:messages :form:id_1" 
            resetValues="true"/>
</h:commandButton>

更新:如果您在JSF 2.2之前,您可以使用Primefaces p:ajax,例如,像这样(并再次解决和解释)可以在引用的accepted answer以及Primefaces showcase

中找到
<h:commandButton value="Submit"  actionListener="#{dtSelectionView.onSubmit()}">
       <p:ajax process="@form" update="@form" resetValues="true" />
</h:commandButton>

(虽然我不建议仅为此目的导入Primefaces ......最好探索其他可能性)

this.number为空的实际原因

我注意到,如果您尝试在第一次验证失败后提交(如果您不重置h:selectOneMenu的输入值),则以下某些类会创建新的Car对象调用default constructor(并将number属性初始化为默认值,在您的情况下等于null

Severe:   java.lang.NullPointerException
    at entities.Car.equals(Car.java:107)
    at javax.faces.component.UIInput.compareValues(UIInput.java:1224)
    at javax.faces.component.UIInput.validate(UIInput.java:990)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1248)
    at javax.faces.component.UIInput.processValidators(UIInput.java:712)
    at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:575)
    at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIForm.visitTree(UIForm.java:371)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
    at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
    at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
    at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:57)
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219)
    at org.omnifaces.context.OmniPartialViewContext.processPartial(OmniPartialViewContext.java:139)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1193)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)

坦率地说,我无法解释这种情况发生的地点和原因,因为它超出了我对这个主题的了解。