我在尝试使用o:validateOrder验证rich:calendar组件时遇到了一个问题。
代码:<!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:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:tablas="http://java.sun.com/jsf/composite/tablas"
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions"
xmlns:templates="http://java.sun.com/jsf/composite/templates"
>
<body>
<f:metadata>
<f:event type="preRenderView" listener="#{baseController.iniciarConversacion()}" />
</f:metadata>
<ui:composition template="/templates/TemplateABM.xhtml">
<ui:define name="title">
#{msgs['facturacion.abm.generacion.factura.individual.pagina.titulo']}
</ui:define>
<ui:define name="top">
<h1>#{msgs['facturacion.abm.generacion.factura.individual.titulo']}</h1>
</ui:define>
<ui:define name="content">
<h:form id="formFacturaIndividual">
<h:panelGroup id="panelFechas">
<h:inputHidden id="fechaInicioFactura" value="#{facturaController.fechaInicioFactura}">
<f:convertDateTime type="date" pattern="dd/MM/yy"/>
</h:inputHidden>
<h:inputHidden id="fechaFinFactura" value="#{facturaController.fechaFinFactura}">
<f:convertDateTime type="date" pattern="dd/MM/yy"/>
</h:inputHidden>
<h:inputHidden id="fechaEmisionComprobanteUltima" value="#{comprobanteController.fechaEmisionComprobanteUltima}">
<f:convertDateTime type="date" pattern="dd/MM/yy"/>
</h:inputHidden>
</h:panelGroup>
<o:validateOrder id="validacionFechaFacturaMenorAFechaInicioFactura" type="gte" components="fechaFactura fechaInicioFactura"
message="#{msgs['comun.abm.fecha.factura.menor.limite.dia']}" showMessageFor="fechaFactura" />
<o:validateOrder id="validacionFechaFacturaMayorAFechaFinFactura" type="lte" components="fechaFactura fechaFinFactura"
message="#{msgs['comun.abm.fecha.factura.menor.limite.dia']}" showMessageFor="fechaFactura" />
<o:validateOrder id="validacionFechaFacturaMayorAFechaEmisionUltimoComprobante" type="gte" components="fechaFactura fechaEmisionComprobanteUltima"
message="#{of:format1(msgs['comun.abm.fecha.factura.menor.ultimo.comprobante'], comprobanteController.fechaEmisionComprobanteUltima)}" showMessageFor="fechaFactura" />
<o:massAttribute name="disabled" value="#{tipoComprobanteController.entidad == null}">
<rich:panel id="panelDatosFactura" header="#{msgs['facturacion.abm.generacion.padron.panel.datos.factura']}">
<h:panelGrid id="DatosFactura" columns="3">
<h:outputLabel value="#{msgs['facturacion.abm.generacion.padron.fecha.factura']}" for="fechaFactura"/>
<rich:calendar
id="fechaFactura"
datePattern="dd/MM/yyyy"
showWeeksBar="false"
enableManualInput="true"
value="#{generacionFacturacionIndividualController.facturaBean.fechaFactura}"
required="true"
requiredMessage="La Fecha de la Factura es Obligatoria" >
<a4j:ajax event="change" execute="@form" />
</rich:calendar>
<h:panelGroup>
<rich:message for="fechaFactura"/>
</h:panelGroup>
</h:panelGrid>
</rich:panel>
</o:massAttribute>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
异常:java.lang.IllegalArgumentException: All values must implement java.lang.Comparable.
at org.omnifaces.component.validator.ValidateOrder.validateValues(ValidateOrder.java:142)
at org.omnifaces.component.validator.ValidateMultipleFields.validateComponents(ValidateMultipleFields.java:213)
at org.omnifaces.component.validator.ValidatorFamily.processValidators(ValidatorFamily.java:63)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1216)
at javax.faces.component.UIForm.processValidators(UIForm.java:253)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:536)
at org.richfaces.context.MetaComponentProcessingVisitCallback.visit(MetaComponentProcessingVisitCallback.java:73)
at org.richfaces.context.BaseExtendedVisitContext.invokeVisitCallback(BaseExtendedVisitContext.java:103)
at org.richfaces.context.ExtendedExecuteVisitContext.invokeVisitCallback(ExtendedExecuteVisitContext.java:55)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1652)
at javax.faces.component.UIForm.visitTree(UIForm.java:371)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1663)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1663)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:383)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:257)
at org.richfaces.context.ExtendedPartialViewContext.processPartial(ExtendedPartialViewContext.java:263)
at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1162)
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:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at ar.com.filter.HibernateSessionRequestFilter.doFilter(HibernateSessionRequestFilter.java:35)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String
at java.lang.String.compareTo(String.java:108)
at java.util.Collections$ReverseComparator.compare(Collections.java:3578)
at java.util.Collections$ReverseComparator.compare(Collections.java:3569)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:324)
at java.util.TimSort.sort(TimSort.java:189)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at org.omnifaces.component.validator.ValidateOrder$Type$4.invoke(ValidateOrder.java:99)
at org.omnifaces.component.validator.ValidateOrder$Type$4.invoke(ValidateOrder.java:95)
at org.omnifaces.component.validator.ValidateOrder$Type.validateOrder(ValidateOrder.java:111)
at org.omnifaces.component.validator.ValidateOrder.validateValues(ValidateOrder.java:139)
... 44 more
我调试了代码,问题是:日历组件发送字符串而不是日期类型,这不会发生我在其他页面,我不知道是omnifaces问题或richfaces。什么好主意吗?
<o:validateXxx>
元件对其相对于目标输入元件的位置非常敏感。这对于根据组件自己的转换器和验证器来确定验证的优先级非常有用。
当放在目标输入组件之前时,它们将验证未提交的原始值,并且它们将在任何组件自己的验证器之前运行。 当放在目标输入组件之后时,它们将验证转换后的值(如果涉及任何转换器),并且它们将在<o:validateOrder>
放在这些组件之间。这不是推荐的方法。您将最终获得一个List
,其中充满来自验证器上方组件的Date
实例和来自验证器下方组件的String
实例。
参见ValidateMultipleFields
javadoc(重点是我的):
这个验证器可以放在表单的任何位置,但是请记住,组件将按照它们在表单中出现的顺序进行验证。因此,如果这个验证器被放置在所有组件之前,那么它将在组件自己的任何验证器之前执行。如果此验证器失败,则不会触发组件自己的验证器。如果这个验证器被放置在所有组件之后,那么它将在任何组件自己的验证器之后执行。如果其中任何一个失败,则不会执行此验证器。不建议将此验证器放在引用组件之间的某个地方,因为结果行为可能会令人困惑。将此验证器放在所有组件之前或之后,这取决于您希望如何优先考虑验证。