Tuesday, 5 August 2008

Struts 2 Validation using Annotations

I was pleasantly surprised how easy it was to get fairly complex server side validation working with Struts 2 by just using annotations. No XML whatsoever. Going into this task I was pretty sure annotations would let me down by having a shortcoming which could only be compensated for by writing validation files, but unlike my attempt at using all annotations for action configuration, this endeavor was successful.

I had written a java.net article about WebWork Validation and everything said there applies here too with the major add-on that we can now use annotations. So let’s get to an example of visitor field validation where we annotate the properties of a Java bean and have it’s validation rules apply to a form written using . Note that in the same manner we annotate the bean, we an also annotate the actual action class, the concept is similar.

The form has three fields:

  • name: text input
  • gender: select box
  • favoriteTeams: checkbox

This translates to the following HTML form written using Struts tags:



list="#{'M':'Male', 'F':'Female'}" />
list="#{'RAP':'Raptors', 'ARS':'Arsenal'}"
label="'Teams'"/>
value="'Submit'"/>

In the action class PersonAction, just the following is needed:

@Validation
public class PersonAction extends ActionSupport {

private Person person;

// don't provide message, it is supplied by
// annotations in Person class
@VisitorFieldValidator(message="")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}

public String execute() {
// do processing
return SUCCESS;
}
}

Two annotations are needed, the @Validation annotation is needed to tell Struts that actions in this class might need to be validated. The @VisitorFieldValidator is telling Struts that the person object properties need validation. If you had multiple actions mapped to the same action class, all actions would be validated. Now this might not be desirable because if you had say two actions called viewForm and submitForm, you would only want to validate the latter. To get around this problem while still using annotations all we have to do is add the @SkipValidation annotation on the action method:

@SkipValidation
public String viewForm() {
return SUCCESS;
}

As the name suggests @SkipValidation will bypass validation for calls to this method.

Now we must specify the actual rules for the properties to be validated. This must be done in the Java bean:

@Validation
public class Person {
private String name;
private String gender;
private String[] favoriteTeams;

@RequiredStringValidator(message="Supply name")
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@RequiredStringValidator(message="Supply gender")
public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

@RequiredFieldValidator(message="Supply a team")
public String[] getFavoriteTeams() {
return favoriteTeams;
}

public void setFavoriteTeams(String[] favoriteTeams) {
this.favoriteTeams = favoriteTeams;
}

}

It’s a fairly straightforward class where @RequiredStringValidator is used for both the text input and the select box since they can only hold a singular value. The interesting part of this bean is how favoriteTeams is validated. We specify a String[] instead of a String as multiple checkboxes can be selected, Struts is smart enough to populate it properly. The other difference is that @RequiredFieldValidator is specified which enforces at least one checkbox to be selected. As a side-note, when using a radio button you would still use @RequiredStringValidator since only a single value is passed through. A multiple select box would require the use of an array and @RequiredFieldValidator.

A small quirk that I noticed is that even though the @*Validator annotations have a message and a key attribute to specify a message or a resource key, the message attribute is mandatory. So even if you’re specifying a resource key for your validation message, you still have to specify message=”".
The benefit of using visitor field validation is that the same properties can be validated in different actions without writing any new rules. Since the rules (annotations) reside in the Java bean, the Java bean can be specified as a property in different action classes to the same effect.

If you’re looking to perform client-side validation, check out Really easy field validation by Dexagogo, a powerful JavaScript library that’s based on Prototype and happens to be super-easy to use.

This entry was written by Arsenalist and posted on August 6th, 2008 and filed under java, struts, tech.