Close

JSF - Creating a Custom Validator Tag

[Last Updated: Sep 11, 2017]

This tutorial demonstrates how to create a custom validator tag. With the custom tag, we can specify attributes as well which will map to the validator class properties.

Example

Creating a Validator

@FacesValidator("phValidator")
public class PhoneValidator implements Validator {
    private String pattern;

    @Override
    public void validate(FacesContext context, UIComponent component,
                         Object value) throws ValidatorException {
        PhonePattern phonePattern = PhonePattern.getPhonePattern(pattern);
        if (!phonePattern.match(value.toString())) {
            FacesMessage msg =
                    new FacesMessage("Invalid phone format",
                            String.format("invalid input: %s, The valid format regex: %s",
                                    value, phonePattern.getPattern()));
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(msg);
        }
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
}
public enum PhonePattern {
    STANDARD("(\\d{3})-(\\d{3})-(\\d{4})"),
    PLAIN("(\\d{3})(\\d{3})(\\d{4})");

    private final Pattern compiledPattern;

    PhonePattern(String pattern) {
        compiledPattern = Pattern.compile(pattern);
    }

    public static PhonePattern getPhonePattern(String patternString) {
        try {
            return valueOf(patternString.toUpperCase());
        } catch (IllegalArgumentException | NullPointerException e) {
            //returning default pattern;
            return STANDARD;
        }
    }

    public boolean match(String inputString) {
        Matcher matcher = compiledPattern.matcher(inputString);
        return matcher.matches();
    }

    public String getPattern() {
        return compiledPattern.pattern();
    }
}

Creating validator tag

src\main\webapp\WEB-INF\mylib.taglib.xml

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
        version="2.0">
    <namespace>http://example.com/ui</namespace>

    <tag>
        <tag-name>phoneValidator</tag-name>
        <validator>
            <validator-id>phValidator</validator-id>
        </validator>
        <attribute>
            <name>pattern</name>
            <type>java.lang.String</type>
        </attribute>
    </tag>
</facelet-taglib>

Registering the tag

src\main\webapp\WEB-INF\web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">

    <context-param>
        <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
        <param-value>/WEB-INF/mylib.taglib.xml</param-value>
    </context-param>

</web-app>

JSF page

src/main/webapp/index.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!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:u="http://example.com/ui">
<h:head></h:head>
<h:body>
    <h2>JSF custom converter example</h2>
    <h:form>
        <h:panelGrid columns="3">

            <h:outputLabel for="wph" value="Work Phone: "/>
            <h:inputText id="wph" value="#{phoneBean.workPhone}">
                <u:phoneValidator pattern="standard"/>
            </h:inputText>
            <h:message for="wph" style="color:red"/>

            <h:outputLabel for="cph" value="Cell Phone: "/>
            <h:inputText id="cph" value="#{phoneBean.cellPhone}">
                <u:phoneValidator pattern="plain"/>
            </h:inputText>
            <h:message for="cph" style="color:red"/>

            <span></span>
            <h:commandButton value="Submit"/>
        </h:panelGrid>
        <div>
            work Phone:
            <h:outputText value="#{phoneBean.workPhone}"/>
        </div>
        <div>
            Cell Phone:
            <h:outputText value="#{phoneBean.cellPhone}"/>
        </div>
    </h:form>
</h:body>
</html>

Managed Bean

@ManagedBean
@ViewScoped
public class PhoneBean {
    private String workPhone;
    private String cellPhone;

    public String getWorkPhone() {
        return workPhone;
    }

    public void setWorkPhone(String workPhone) {
        this.workPhone = workPhone;
    }

    public String getCellPhone() {
        return cellPhone;
    }

    public void setCellPhone(String cellPhone) {
        this.cellPhone = cellPhone;
    }
}

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

Output

Submitting invalid patterns for phone number:

Submitting a valid patterns:

Example Project

Dependencies and Technologies Used:

  • jsf-api 2.2.14: This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.
  • jsf-impl 2.2.14: This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.
  • JDK 1.8
  • Maven 3.3.9

JSF Custom Validator Example Select All Download
  • custom-validator-tag
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • PhoneValidator.java
          • webapp
            • WEB-INF

    See Also