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?
The validation error message handling is wrong. You need to throw a
ValidatorExceptionwith aFacesMessageinstead of adding theFacesMessagemanually.So instead of all those
you need to do
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.