Parametrizing custom validator in JSF 2

Writing a custom validator in JSF 2 is not a complicated task. You implement Validator interface, add @FacesValidator annotation and insert validator declaration in faces-config.xml, that’s all. A piece of cake. But let’s consider following scenario:

You need custom date validator, let’s say checking that date from rich:calendar is not in the past. So we place calendar component with validator inside.

<rich:calendar value="#{fieldValue}" id="dateField" datePattern="yyyy/MM/dd">
        <f:validator validatorId="dateNotInThePast"/>
    </rich:calendar>

And our validator could look like below:

@FacesValidator("dateNotInThePast")
public class DateNotInThePastValidator implements Validator {

  @Override
  public void validate(FacesContext facesContext, UIComponent uiComponent, Object value)
                                                              throws ValidatorException {
    if (ObjectUtil.isNotEmpty(value)) {
      checkDate((Date)value, uiComponent, facesContext.getViewRoot().getLocale());
    }
  }

  private void checkDate(Date date, UIComponent uiComponent, Locale locale) {
    if(isDateInRange(date) == false) {
      ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
      String messageText = rb.getString("date.not.in.the.past");
      throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                     messageText, messageText));
    }
  }

  private boolean isDateInRange(Date date) {
    Date today = new DateTime().withTime(0, 0, 0, 0).toDate();
    return date.after(today) || date.equals(today);
  }
}

And if we provide key value in properties file we will see something like this:

So it looks that we have working and production-ready custom validator.

The problem

But while our form becomes more and more complex we might encouter issue described on the screen below:

So the problem is how user can determine which date is valid and which is not? Our validator uses the same property key to display both error messages.

The solution

We need to somehow provide a label of validated field to our custom validator. And, suprisingly for JSF, it can be achieved pretty easily. The only catch is that you have to know how to do it :)

So in Java Server Faces we could parametrize components with attributes (f:attribute tag). So we add attribute to rich:calendar and then read this passed value value inside validator assigned to this calendar field. So now our calendar components should look like that:

<rich:calendar value="#{fieldValue}" id="dateField" datePattern="yyyy/MM/dd">
        <f:validator validatorId="dateNotInThePast"/>
        <f:attribute name="fieldLabel" value="Date field 2" />
    </rich:calendar>

And in our validator Java class we could get this value using uiComponent.getAttributes().get(“fieldLabel”);

private void checkDate(Date date, UIComponent uiComponent, Locale locale) {
        if(isDateInRange(date) == false) {
            ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
            String messageText = getFieldLabel(uiComponent) +" " + rb.getString(getErrorKey());

            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                            messageText, messageText));
        }
    }

    protected String getFieldLabel(UIComponent uiComponent) {
        String fieldLabel = (String) uiComponent.getAttributes().get("fieldLabel");

        if(fieldLabel == null) {
            fieldLabel = "Date" ;
        }

        return fieldLabel;
    }

Our property value for error should have value can not be in the past as Date or field label will be added at the beginning of error message.

And working example should show something similar to this screen:

Reference: Parametrizing custom validator in JSF 2 from our JCG partner Tomasz Dziurko at the Code Hard Go Pro blog

Related Articles :

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


four − = 2



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books