我真正想要的是两个PrimeFaces <p:pickList>
组件,它们通过OmniFaces' <o:validateAll>
组件进行了验证。请注意,使用<o:validateAll>
验证pickList存在一个问题,可以在OmniFaces问题跟踪器中以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>
后面的 dummy 备用bean只是为两个dualListModel
属性和不做任何事情的操作方法提供了获取方法/方法。
当我运行此代码并将至少一个pickList留为空白时,提交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)
[...]
我使用OmniFaces 2.7和PrimeFaces 6.2。
请注意,正如我上面链接的问题所述,我正在使用自定义渲染器来替代getConvertedValue()
的PickList。但是,这不会以任何影响此错误的方式改变渲染器的行为。它只是使<o:validateAll>
认识到pickList为空。
对我来说,这似乎是一个错误,但是我不确定这是OmniFaces还是PrimeFaces中的错误。有人知道吗?
作为一种解决方法,可以将required="true"
属性添加到所有pickList中。
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)
在corresponding code中,通过oldModel
初始化的getValue()
的值为null
。
答案 0 :(得分:2)
问题已在GitHub上验证并报告:https://github.com/primefaces/primefaces/issues/4756
我提交了一个修补程序,希望该修补程序可以包含在PF 7.0.2和PF 7.1中
答案 1 :(得分:1)
正如 Melloware 所写,该问题报告为PrimeFaces issue #4756。事实证明,该问题仅存在于Mojarra(经2.2.17、2.2.18、2.2.19和2.3.9测试)而不是MyFaces。因此创建了另一个问题:Mojarra #4398。
答案 2 :(得分:0)
如果您的选择列表使用 FacesConverter,请注意,与检索原始对象相比,输入值必须未转义。事实上,如果输入字符串类似于“Chicken&Egg”,转换器会收到 'Chicken&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();
}