JSF validator method results in duplicate FacesMessage shown in p:messages

我的未来我决定 提交于 2019-12-11 04:49:21

问题


I have two PrimeFaces p:calendar components, one representing a begin and the other representing an end date.

I want to run a validator method now whenever one of them changes.

Here's the end date component:

                <p:calendar id="end-date"
                            widgetVar="testEndDate"
                            value="#{testManager.endDate}"
                            mindate="#{testManager.minEndDate}"
                            maxdate="#{testManager.maxEndDate}"
                            validator="#{testManager.validateEndDate}">
                    <p:ajax event="dateSelect" update="begin-date msgs" global="false" />
                </p:calendar>

Here's the validator method code:

@Override
public void validateEndDate(FacesContext context, UIComponent component, Object value)throws ValidatorException
{
    System.out.println(this.getClass().getSimpleName() + ".validateEndDate()!");

    Date beginDate = this.getBeginDate();
    Date endDate = (Date)value;

    if ( endDate != null && endDate.getTime() <= beginDate.getTime() )
    {
        System.out.println("End date less than or equal to begin date!");

        // this.setValidated( false );
        //
        // throw new ValidatorException( JsfUtil.getValidationErrorFacesMessage( "common.validator.validTo.message" ) );
        context.addMessage(null, JsfUtil.getValidationErrorFacesMessage("common.validator.validTo.message"));
    }

    List < FacesMessage > messages = context.getMessageList();

    if ( !messages.isEmpty() )
    {
        System.out.println("Faces messages list not empty! Size = " + messages.size());

        this.setValidated(false);

        throw new ValidatorException(messages);
    }

    this.setValidated(true);
}

Here's what I do:

  • Show the dialog via command button.
  • Click into the empty end date calendar input, which pops up the calendar.
  • Click on the 22 (same date as the begin date).

The code basically works, at least according to the console output:

INFO: DefaultValidatingBeginEndDateChecker.validateEndDate()!
INFO: End date less than or equal to begin date!
INFO: Faces messages list not empty! Size = 1

However, this shows the same FacesMessage twice on the UI:

As you can see, the output doesn't match what the validator method is saying.

Does anyone know what's going on/wrong and how to fix this? (Also note the outcommented code showing the working solution, but I need to know why this isn't working, because I have another more complex validator which has 1+ ifs which is supposed to show more than one message...).


回答1:


What works is to collect the faces messages in an own list:

    List<FacesMessage> messages = new ArrayList<FacesMessage>();

    if ( endDate != null && endDate.getTime() <= beginDate.getTime() )
    {
        System.out.println( "End date less than or equal to begin date!" );

        // context.addMessage( null, JsfUtil.getValidationErrorFacesMessage( "common.validator.validTo.message" ) );
        messages.add( JsfUtil.getValidationErrorFacesMessage( "common.validator.validTo.message" ) );
    }

    // ... more ifs

    if ( !messages.isEmpty() )
    {
        System.out.println( "Faces messages list not empty! Size = " + messages.size() );

        this.setValidated( false );

        throw new ValidatorException( messages );
    }

    this.setValidated( true );

Doh.




回答2:


I think that this is an expected behaviour. Look suspiciously at the following two lines of code:

  1. context.addMessage(null, JsfUtil.getValidationErrorFacesMessage("common.validator.validTo.message")); and
  2. throw new ValidatorException(messages);.

Think what they do. The first line adds a message to the current context and the second one throws an exception, instructing JSF that validation has failed, and this in turn adds your list of exceptions to the current context as well.

So, the solution is straightforward: remove the redundant context.addMessage(null, JsfUtil.getValidationErrorFacesMessage("common.validator.validTo.message")); line and replace your throws clause for throw new ValidatorException(new FacesMessage(JsfUtil.getValidationErrorFacesMessage("common.validator.validTo.message")));.



来源:https://stackoverflow.com/questions/16694036/jsf-validator-method-results-in-duplicate-facesmessage-shown-in-pmessages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!