Ошибка Omnifaces o:validateOrder с компонентом календаря Rich Faces

У меня возникла проблема при попытке проверить компонент rich:calendar с помощью o:validateOrder.

Код:

<!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

Я отладил код, и проблема в том, что компонент rich:calendar отправляет String вместо типа Date, этого не происходит на других страницах, которые я не знаю, это проблема omnifaces или richfaces. Любые идеи?


person Ignacio    schedule 15.05.2015    source источник
comment
я исправил размещение o:validateOrder в конце файла.   -  person Ignacio    schedule 15.05.2015


Ответы (1)


Компоненты <o:validateXxx> чувствительны к их расположению относительно целевых входных компонентов. Это очень полезно для определения приоритетов проверки в зависимости от собственного конвертера и валидаторов компонента.

При размещении перед целевыми входными компонентами они будут проверять необработанные неотправленные значения и будут выполняться перед любым из собственных средств проверки компонента.

При размещении после целевых компонентов ввода они будут проверять преобразованные значения (если задействован какой-либо преобразователь) и будут выполняться после любых собственных средств проверки компонента.

В вашем конкретном случае вы поместили <o:validateOrder> между этими компонентами. Это не рекомендуемый подход. В итоге вы получите List, заполненный Date экземплярами из компонентов выше валидатора и String экземпляров из компонентов ниже валидатора.

См. также документацию ValidateMultipleFields javadoc (выделено мной) :

Этот валидатор можно разместить в любом месте формы, но имейте в виду, что компоненты будут проверяться в том порядке, в котором они появляются в форме. Таким образом, если этот валидатор был помещен перед всеми компонентами, то он будет выполнен перед любым из собственных валидаторов компонента. Если этот валидатор выйдет из строя, собственные валидаторы компонента не будут запущены. Если этот валидатор был размещен после всех компонентов, то он будет выполняться после любого из собственных валидаторов компонента. Если какой-либо из них не работает, то этот валидатор не будет выполнен. Не рекомендуется размещать этот валидатор где-то между указанными компонентами, так как результирующее поведение может сбивать с толку. Поместите этот валидатор до или после всех компонентов, в зависимости от того, как вы хотите расставить приоритеты. Проверка.

person BalusC    schedule 18.05.2015