Walle
Walle

Reputation: 570

How to skip action when validation with a custom validator fails?

I have a small webapplication for a library, with a customized ISBN validator. My .xhtml page for adding a book looks like this:

<fieldset>
<h:messages/>
<ul>
    <li>
        <h:outputLabel for="isbn" value="#{labels.isbn}:" />
        <h:inputText id="isbn" value="#{addController.book.isbn.isbnValue}" required="true" requiredMessage="- ISBN must be filled in.">
            <f:validator validatorId="isbnValidator" />
        </h:inputText>
    </li>
    <li>
        <h:outputLabel for="title" value="#{labels.title}:" />
        <h:inputText id="title" value="#{addController.book.title}" required="true" requiredMessage="- Title must be filled in."/>
    </li>
    <li>
        <h:outputLabel for="name" value="#{labels.name}:" />
        <h:inputText id="name" value="#{addController.book.person.name}" required="true" requiredMessage="- Name must be filled in."/>
    </li>
    <li>
        <h:outputLabel for="firstname" value="#{labels.firstname}:" />
        <h:inputText id="firstname" value="#{addController.book.person.firstname}" />
    </li>

</ul>
<h:commandButton id="addButton" action="#{addController.save}" value="#{labels.add}" />
<h:commandButton id="cancelButton" action="bookOverview" value="#{labels.cancel}" />
</fieldset>
</ui:define>

The isbnValidator of the first input field is this class:

private Isbn isbn;

@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
    isbn = new Isbn((String) value);
    if (!isbn.isIsbn17Characters()) {
        addMessageToContext(context, "- ISBN needs to have 17 characters");
    }
    if (isbn.isIsbn17Characters() && !isbn.isIsbnInRightFormat()) {
        addMessageToContext(context, "- Wrong format, it should be like 'XXX-XX-XXX-XXXX-X'");
    }
    if (isbn.isIsbn17Characters() && isbn.isIsbnInRightFormat() && !isbn.isIsbnFormatValid()) {
        addMessageToContext(context, "- ISBN can only contain numbers, and no other tokens");
    }
    if (isbn.isIsbn17Characters() && isbn.isIsbnInRightFormat() && isbn.isIsbnFormatValid()
            && !isbn.isLastNumberValid()) {
        addMessageToContext(context, "- Last number of the ISBN should be " + isbn.getCorrectLastNumber()
                + " with those 12 numbers");
    }

}

public static void addMessageToContext(FacesContext context, String message) {
    FacesMessage facesMessage = new FacesMessage();
    facesMessage.setSummary(message);
    facesMessage.setDetail(message);
    context.addMessage("isbn", facesMessage);
}

When I click the 'add' button, the book should be added to the database.

When the ISBNfield, namefield or titlefield aren't filled in, I get the corresponding error message. But when my fields are filled in, and the ISBN validation fails, he shows the error message, but he still adds the book (with a wrong ISBN-number) to the database.

A solution which I thought about: If my messages tags is not empty, he shouldn't add the book to the database. But how can I check that?

Or is there a better solution to my problem?

Upvotes: 2

Views: 464

Answers (1)

BalusC
BalusC

Reputation: 1109715

The validation error message handling is wrong. You need to throw a ValidatorException with a FacesMessage instead of adding the FacesMessage manually.

So instead of all those

addMessageToContext(context, "- ISBN needs to have 17 characters");

you need to do

throw new ValidatorException(new FacesMessage("- ISBN needs to have 17 characters"));

This is for JSF sign that the input is invalid and hence the action method won't be invoked. You also don't need to specify the client ID, it will just end up in the <h:message> associated with the input component where this validator is fired on.

Upvotes: 3

Related Questions