Creating a custom validator
Explains how to write and integrate custom validators for Tapestry 4 and 5
Tapestry 5.0
Author: Sebastian Hennebrueder, Date: August 2009 There are 3 steps:
- Create a validator
- Create a resource file for validation messages
- Register both in your application
Create a validator
The following validator check if the value is not 'foo' because foo is really a bad value. It expects a String and no configuration parameter. The MinLength
validator uses a configuration parameter to define the minimum length. The validation error messages has the key foo-not-allowed
. You might check the source code of the existing validators for further inspiration.
import org.apache.tapestry5.validator.AbstractValidator; // ... some more imports here public class FooValidator extends AbstractValidator<Void, String> { public FooValidator() { super(null, String.class, "foo-not-allowed"); } public void validate(Field field, Void constraintValue, MessageFormatter formatter, String value) throws ValidationException { if ("foo". equals(value)) throw new ValidationException(buildMessage(formatter, field, constraintValue)); } private String buildMessage(MessageFormatter formatter, Field field, Void constraintValue) { return formatter.format(constraintValue, field.getLabel()); } public void render(Field field, Void constraintValue, MessageFormatter formatter, MarkupWriter writer, FormSupport formSupport) { formSupport.addValidation(field, "foo", buildMessage(formatter, field, constraintValue), null); } }
Create a resource file for validation messages
File ValidationMessages.properties
foo-not-allowed=Foo is not allowed
Register both in your application
A Tapestry application is configured by a AppModule class (See the Tapestry Guide). In the AppModule
class add the following methods:
public static void contributeValidationMessagesSource(OrderedConfiguration<String> configuration) { configuration.add("Default", "de/laliluna/example/components/ValidationMessages", "before:*"); } public static void contributeFieldValidatorSource(MappedConfiguration<String, Validator> configuration) { configuration.add("foo", new FooValidator()); }
That's it.
Tapestry 4.0
this is a revised copy of a posing to the users mailing list by Scott F. Walter
1. implementing a validator
Create a class that extends org.apache.tapestry.form.validator.BaseValidator
(note, this is not org.apache.tapestry.valid.BaseValidator
)
Override the validate
method.
If you want a parameter to be passed into your validator:
- create a constructor that takes a String
- add a (non abstract) property (setXXX, getXXX) where XXX will be the name of your validator. E.g. if the validator is called
mustBe
, use getMustBe()
, setMustBe(String)
. Later on you will reference the validator using: mustBe=tapestry
Here is an example:
package dummy; import org.apache.tapestry.form.IFormComponent; import org.apache.tapestry.form.ValidationMessages; import org.apache.tapestry.form.validator.BaseValidator; import org.apache.tapestry.valid.ValidatorException; /** * @author scott/ron */ public class MustBeValidator extends BaseValidator { private String _mustBe; public MustBeValidator() { super(); } public MustBeValidator(String string) { super(string); } public void setMustBe(String s) { _mustBe = s; } public String getMustBe() { return _mustBe; } public void validate(IFormComponent field, ValidationMessages messages, java.lang.Object object) throws ValidatorException { if (!equal(object,_mustBe) { throw new ValidatorException(messages.formatValidationMessage(getMessage(), "invalid-format", null)); } } private boolean equal(Object o1, Object o2) { if (o1 == null && o2 == null) return true; if (o1 == null || o2 == null) return false; return o1.equals(o2); } }
configuration
Provide a contribution to tapestry.form.validator.Validators in hivemodule.xml (stored in your WEB-INF directory)
{{{<?xml version="1.0"?>
<module id="myApplicationName" version="1.0.0">
<contribution configuration-id="tapestry.form.validator.Validators">
<validator name="mustBe" configurable="true" class="dummy.MustBeValidator"/>
</contribution>
</module>
}}}
Note: If your validator does not take any parameters set configurable to "false" here
Using
Inside the specification file, use the new validator as follows:
<component id="firstNameField" type="TextField"> <binding name="value" value="ognl:person.firstName"/> <binding name="validators" value="required,minLength=3,mustBe=Scott"/> <binding name="displayName" value="First Name"/> </component>