代码之家  ›  专栏  ›  技术社区  ›  Martin Höller

带有OmniFaces validateAll的PrimeFaces选取列表导致NullPointerException

  •  0
  • Martin Höller  · 技术社区  · 5 年前

    PrimeFaces <p:pickList> 得到了验证 OmniFaces' <o:validateAll> 组件。请注意,使用 < described in issue 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>
    

    这个 笨蛋 后面的backingbean只为这两个提供getter/setter dualListModel

    当我运行此代码并将至少一个选择列表留空时,提交 Done NullPointerException PickListRenderer . 下面是StackTrace:

    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)
        [...]
    

    请注意 ,我正在为覆盖的选择列表使用自定义呈现器 getConvertedValue() <o:验证所有> 确认选择列表为空。

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

    变通办法

    作为解决方法,可以添加 required="true" 属性设置为所有选择列表。

    更新

    此外,我还用上面的代码和PrimeFaces7.0生成了另一个NPE,它通过“done”处理空的选择列表,然后将其中一个选择列表中的一个项目转移到目标列表。

    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)
    

    corresponding code ,的值 oldModel ,通过 getValue() null .

    0 回复  |  直到 5 年前
        1
  •  3
  •   Martin Höller    5 年前

    作为 酒器 PrimeFaces issue #4756 . 结果证明,这个问题只存在于Mojarra(用2.2.17、2.2.18、2.2.19和2.3.9测试过),而不存在于MyFaces。所以另一个问题是: Mojarra #4398

        3
  •  0
  •   Tommaso Torti    3 年前

    如果选择列表使用FacesConverter,请注意,在比较输入值以检索原始对象时,必须取消其范围。实际上,如果输入字符串类似于“Chicken&转换器接收的“鸡蛋” 'Chicken&amp;Egg' 例子:

          @Override
      public YourObject getAsObject(FacesContext facesContext, UIComponent uiComponent, String name)
      {
        PickList pickList = (PickList) uiComponent;
        DualListModel<YourObject> dualListModel = (DualListModel<YourObject>) pickList.getValue();
        List<YourObject> all = dualListModel.getSource();
        all.addAll(dualListModel.getTarget());
    
        return all.stream().filter(element ->
          String.valueOf(element.getName()).equals(HtmlUtils.htmlUnescape(name)))
          .findFirst().get();
      }