I’ve been writing a bit about Google Web Toolkit lately. It undeniably is disrupting traditional browser-based RIA development. But it does lack some features out of the box that most developers have grown accustomed to from frameworks like Flex and Ext. Field validation is one such feature. While the gwt-validation project exists to solve this very problem, an approach leveraging a good chunk of the existing GWT infrastructure can give you a robust, test-driven, and MVP-friendly approach for validation.

To get started, let’s break down our validation needs along the standard lines that we see in frameworks today.  Widgets need to be able to be Validatable.  That is to say, Widgets must be able to be externally seen as having the capability to execute logic which validates their current state.  In my approach, I’ve chosen to strategize my widgets rather than visit them in order to validate their data.  This decision is largely to enforce contract-driven development and ensure a high level of testability.

Validatable

package com.ryannorris.gwt.validation.client;
 
public interface Validatable {
	/**
	 * Execute validation on the implementing component
	 *
	 * @return true if validation succeeded, false if validation failed
	 */
	public boolean validate();
}

We also now need an interface that will provide the rules for how validation logic should occur.  Something that is Validatable should be able to validate itself with multiple sets of rules.  Our Validator interface gives us this flexible cardinality, and has a familiar ring to it.

Validator

package com.ryannorris.gwt.validation.client;
 
public interface Validator {
	/**
	 * Execute the implemented validation logic
	 *
	 * @return true if validation succeeded, false otherwise
	 */
	public boolean validate();
}

Yes, these two interfaces are the same besides their name. They are both command interfaces, allowing us to abstract logic behind a single method that we can cope with polymorphically. The idea remember is that Validatable components can re-use many different Validator implementations.

So let’s write a simple Validator and Validatable interface.  In this case, we’ll be validating date input.

DateFormatValidator

package com.ryannorris.gwt.validation.client.validator;
 
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.HasValue;
import com.ryannorris.gwt.validation.client.Validator;
 
public class DateFormatValidator implements Validator {
 
	private HasValue<String> _value;
	private DateTimeFormat _format;
 
	/**
	 * Create a validator that will verify that the given string is compliant
	 * with the pattern
	 *
	 * @param format
	 *            The format to validate against, per the specification in
	 *            {@link DateTimeFormat}
	 * @param value
	 *            The value to validate
	 */
	public DateFormatValidator(String pattern, HasValue<String> value) {
		_format = DateTimeFormat.getFormat(pattern);
	}
 
	/**
	 * Set the value to be validated
	 *
	 * @param value a string, nominally representing a date
	 */
	public void setValue(HasValue<String> value) {
		_value = value;
	}
 
	/*
	 * (non-Javadoc)
	 *
	 * @see com.ryannorris.gwt.validation.client.Validator#validate()
	 */
	@Override
	public boolean validate() {
		try {
			_format.parse(_value.getValue());
		} catch (IllegalArgumentException e) {
			// the value couldn't be parsed by the pattern, return false
			return false;
		}
 
		return true;
	}
}

So, now I have a Validator. How do I now make a widget, let’s say a simple TextBox, Validatable?

Harkon back earlier when I said I was chosing to strategize my Widgets.  That’s only partially true.  Because we’re aiming for good TDD, and hence we want to rely on dependency injection – we will in fact be decorating them as well.  We will strategize around their ability to be validated, while we will decorate them with the Validators that interest us.  This is important, as we wouldn’t want to have 20 different TextBox implementations that handle various Validation permutations.  We would rather one, decoratable TextBox that can be managed by the presenter in our MVP implementation.  So what does our initial stab at a ValidatableTextBox look like?

ValidatableTextBox

package com.ryannorris.gwt.validation.client.widget;
 
import com.google.gwt.user.client.ui.TextBox;
import com.ryannorris.gwt.validation.client.Validatable;
import com.ryannorris.gwt.validation.client.validator.DateFormatValidator;
 
public class ValidatableTextBox extends TextBox implements Validatable {
 
	@Override
	public boolean validate() {
		DateFormatValidator validator = new DateFormatValidator("mm/DD/yyyy",
				getText());
		return validator.validate();
	}
}

Wait, you say.  This isn’t at all what you just described!  This is a text box that will only execute one validator for one date pattern! Well, you’re right.  We need to find a way to enable decoration of our TextBox in a way that can be nicely tested and extensible.  GWT makes extensive use of decorator pattern, and really strives for testability.  We see this in the various Has interfaces, which are added to classes to give them additional behaviors (such as HasText or HasClickHandler).  So, we will follow suit and create our decorator interface HasValidators.

HasValidators

public interface HasValidators {
	/**
	 * Add a validator to the decorated component
	 *
	 * @param validator The validator to be added
	 */
	public void addValidator(Validator validator);
}

And now our updated ValidatableTextBox.

package com.ryannorris.gwt.validation.client.widget;
 
import java.util.Set;
 
import com.google.gwt.user.client.ui.TextBox;
import com.ryannorris.gwt.validation.client.HasValidators;
import com.ryannorris.gwt.validation.client.Validatable;
import com.ryannorris.gwt.validation.client.Validator;
 
public class ValidatableTextBox extends TextBox implements Validatable, HasValidators {
 
	private Set _validators;
 
	@Override
	public void addValidator(Validator validator) {
		_validators.add(validator);
	}
 
	@Override
	public boolean validate() {
		boolean valid = true;
 
		for(Validator validator : _validators) {
			if(! validator.validate()) {
				valid = false;
			}
		}
 
		return valid;
	}
}

So, that’s pretty sweet. I have a collection of Validators as a member of the component – in fact I have a set of them as to ensure no Validator exists more than once on the component.  My validate method now loops through the set of validators and maintains the local state of the validation, allowing the entire validation to fail if any one Validator fails.

A highly testable passive view implementation with this component may look something like:

MySampleValidatableView

/**
 * 
 */
package com.ryannorris.gwt.validation.client;
 
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.user.client.ui.HasValue;
 
/**
 * @author ryan
 * 
 */
public interface MySampleValidatableView {
	/**
	 * Get the {@link HasValidators} behavior of the date box.
	 * 
	 * @return a {@link HasValidators} behavior
	 */
	public HasValidators getDateValidators();
 
	/**
	 * Get the {@link Validatable} behavior of the date box.
	 * 
	 * @return a {@link Validatable} behavior
	 */
	public Validatable getDateValidatable();
 
	/**
	 * Return the {@link HasValue} behavior of the date box. This allows us to
	 * access the value of the control.
	 * 
	 * @return a {@link HasValue} behavior
	 */
	public HasValue<String> getDate();
 
	/**
	 * Return the {@link HasKeyPressHandlers} behavior of the date box. When the
	 * user types a key in the field, we will use this event to validate the
	 * current value;
	 * 
	 * @return
	 */
	public HasKeyPressHandlers getDateKeyUp();
 
	/**
	 * Toggle the visual state of the date box so the user receives feedback
	 * when their date is valid
	 * 
	 * @param valid
	 *            Whether or not the control should reflect a valid date entry
	 *            (true) or an invalid one (false)
	 */
	public void toggleValidDateBox(boolean valid);
 
}

A lot going on here, and it’s seems verbose – but it’s not, it’s just highly testable! We need to be able to access the various behaviors of our text box so that we can test how our presenter collaborates with these behaviors.  We also need to be able to push the passive display functionality back to our view implementation so that our unit tests don’t inadvertently require a hosted environment to run.  So our presenter needs to be built to:

  1. Create a DateFormatValidator with the appropriate pattern and a reference to the component holding the text value to validate;
  2. Decorate the component in the view through the HasValidators behavior;
  3. Execute validation whenever the user changes the value of the widget through the HasKeyPressHandlers interface;
  4. Alter the visual display of the component by calling the toggleValidDateBox method.

So last but not least, our presenter:

MySamplePresenter

package com.ryannorris.gwt.validation.client;
 
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.ryannorris.gwt.validation.client.validator.DateFormatValidator;
 
public class MySamplePresenter {
 
	public MySamplePresenter(final MySampleValidatableView view) {
 
		DateFormatValidator validator = new DateFormatValidator("mm/DD/yyyy",
				view.getDate());
		view.getDateValidators().addValidator(validator);
 
		view.getDateKeyUp().addKeyPressHandler(new KeyPressHandler() {
 
			@Override
			public void onKeyPress(KeyPressEvent event) {
				view.toggleValidDateBox(view.getDateValidatable().validate());
			}
		});
	}
}

So there you have it – a highly testable base for validation in a GWT application using MVP.

In my next post, I’ll add an event framework to validation, allowing asynchronous validation and abstraction between overall error handling and validation.