views:

781

answers:

2

I was reviewing the following link and found out that javax.faces.webapp.ValidatorTag is deprecated and replaced by ValidatorELTag, however I can't seem to find any good information about this.

I want to create a Regular Expression Validator which takes input: regex and error message.

Meaning I would want to have a control like this:

<regexValidator for="myControl" check="([a-Z]^)" errorMessage="Your input contained incorrect characters" />

Now the given link above shows how to do a little part of this, but a whole lot has changed since that was written and methods are deprecated, how do i approach this problem?

+2  A: 

See Creating a Custom Validator in the JEE5 Tutorial. The Creating a Custom Tag section details how to implement your ValidatorELTag class.


for="myControl"

I doubt you'll need this attribute (I'm not sure how you'd make use of it). The validator will be set on the parent control. for attributes are usually only used when one control refers to another, as in the label component.


EDIT: I misread the question; the answer above applies to JSPs (those tag-related classes in core JSF 1.2 are for JSPs only; Facelets has its own tag system; the good news is that you don't need a Java class specifically for defining the tag).

Sample validator:

public class RegexValidator implements Validator, StateHolder {
  private boolean isTransient;
  private String regex;

  public String getRegex() { return regex; }
  public void setRegex(String regex) { this.regex = regex; }

  public void validate(FacesContext context, UIComponent component, Object value)
      throws ValidatorException {
    //TODO: throw ValidatorException if not valid
  }

  //TODO: implement remaining StateHolder methods...
}

This validator is then registered in the faces-config.xml:

  <validator>
    <validator-id>regex.validator</validator-id>
    <validator-class>val.RegexValidator</validator-class>
  </validator>

You then add a tag library to the app (e.g. WEB-INF/facelets/foo.taglib.xml):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd"&gt;
<facelet-taglib xmlns="http://java.sun.com/JSF/Facelet"&gt;
  <namespace>http://demo&lt;/namespace&gt;
  <tag>
    <tag-name>regexValidator</tag-name>
    <validator>
      <validator-id>regex.validator</validator-id>
    </validator>
  </tag>
</facelet-taglib>

Add a xmlns:demo="http://demo" declaration to any Facelets views you want to use the tag library in; your validator tag will start in the form <demo:regexValidator ...; attributes will be picked up through introspection of the validator class.

McDowell
It doesn't find <demo:regexValidator = error on line 87 at column 30: Namespace prefix demo on regexValidator is not defined.
Filip Ekberg
Also, why do you implement StateHolder ?
Filip Ekberg
The error is an XML parsing error - the `demo` namespace prefix is defined by adding the `xmlns:demo="<namespace>"` where `<namespace>` matches the namespace of the tag library. As to `StateHolder`, the view components (and their attributes) may not be kept in RAM between requests, so property values must be saved via the `StateManager` - in the demo code, the value of `regex` would need to be saved or it would be `null` when the view was restored when the form was submitted; it would _not_ be set again from the XML definition.
McDowell
A: 

Here's the piece I forgot to add to my code that tripped me up...

<context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/WEB-INF/faces/foo.taglib.xml</param-value>
</context-param>

You'll also want to change check="([a-Z]^)" to regex="..."

I like this approach because there's no need to extend ValidatorELTag. I'm a very big fan of facelets and this is one more cool feature.

Nadine M