带有 OmniFaces validateAll 的 PrimeFaces PickList 导致 NullPointerException

Mar*_*ler 5 jsf primefaces omnifaces

我真正想要的是两个PrimeFaces<p:pickList>,它们通过OmniFaces 的<o:validateAll>组件进行验证。请注意,验证pickList<o:validateAll>有一个问题,可以按照OmniFaces 问题跟踪器中的问题488中的描述解决该问题。

因此,我的需求的一个非常简单的示例如下所示:

<h:form id="form1">
  <p:messages id="messages">
    <p:autoUpdate/>
  </p:messages>

  <p:pickList id="pick1" value="#{dummy.dualListModel}"
              var="item" itemLabel="#{item}" itemValue="#{item}">
    <p:ajax event="transfer"/>
  </p:pickList>

  <p:pickList id="pick2" value="#{dummy.dualListModel2}"
              var="item" itemLabel="#{item}" itemValue="#{item}">
    <p:ajax event="transfer"/>
  </p:pickList>

  <o:validateAll id="validPicks" components="pick1 pick2"
                 message="all values required!" />

  <h:commandButton id="done" value="Done" action="#{dummy.action1}"/>
</h:form>

<h:form id="theOtherForm">
  <h:commandButton id="otherFormAction" value="Action in other form"
                   action="#{dummy.action2}"/>
</h:form>
Run Code Online (Sandbox Code Playgroud)

后面的虚拟backing-bean 只为这两个dualListModel属性和什么都不做的动作方法提供 getter/setter 。

当我运行此代码并至少保留一个 pickList 为空时,提交Done-button 会导致验证失败作为例外。但是,单击按钮,在其他形式的后验证失败,导致一NullPointerExceptionPickListRenderer。这是堆栈跟踪:

Caused by:java.lang.NullPointerException
    at org.primefaces.component.picklist.PickListRenderer.encodeMarkup(PickListRenderer.java:92)
    at org.primefaces.component.picklist.PickListRenderer.encodeEnd(PickListRenderer.java:59)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:920)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:890)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:134)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
    at org.omnifaces.viewhandler.OmniViewHandler.renderView(OmniViewHandler.java:119)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    [...]
Run Code Online (Sandbox Code Playgroud)

我使用 OmniFaces 2.7 和 PrimeFaces 6.2。

请注意,我正在为覆盖的 PickList 使用自定义渲染器getConvertedValue(),如上面链接的问题中所述。但是,这不会以任何应该影响此错误的方式更改渲染器的行为。它只是<o:validateAll>认识到pickList 是空的。

这对我来说似乎是一个错误,但我不确定这是 OmniFaces 还是 PrimeFaces 中的错误。有人知道吗?

解决方法

作为一种解决方法,可以将该required="true"属性添加到所有选择列表中。

更新

PrimeFaces 7.0 也存在同样的问题(只是行号略有不同)。

此外,我使用上述代码和 PrimeFaces 7.0 制作了另一个 NPE,当通过“完成”对空选项列表求和时,然后将其中一个选项列表中的项目传输到目标列表。

另一个异常发生在这里:

Caused by:java.lang.NullPointerException
    at org.primefaces.component.picklist.PickList.validateValue(PickList.java:140)
    at javax.faces.component.UIInput.validate(UIInput.java:982)
    at org.primefaces.component.picklist.PickList.validate(PickList.java:181)
    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:63)
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219)
    at org.omnifaces.context.OmniPartialViewContext.processPartial(OmniPartialViewContext.java:124)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1193)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
Run Code Online (Sandbox Code Playgroud)

对应的代码中oldModel通过初始化的 的getValue()值为null

Mel*_*are 2

在 GitHub 上验证并报告问题:https ://github.com/primefaces/primefaces/issues/4756

我提交了一个修复程序,希望包含在 PF 7.0.2 和 PF 7.1 中

https://github.com/primefaces/primefaces/pull/4759