Overview
OVal is a pragmatic and extensible validation framework for any kind of Java objects (not only JavaBeans). Constraints can be declared with annotations (@NotNull, @MaxLength), POJOs or XML.Custom constraints can be expressed as custom Java classes or by using scripting languages such as JavaScript, Groovy, BeanShell, OGNL or MVEL.
The OVal plugin provides support for using the OVal Validation Framework
Interceptors
The plugin defines the interceptor "ovalValidation" and the interceptor stack "ovalValidationStack" in the "oval-default" package. To use this interceptor, extend the "oval-default" package and apply the interceptor to your action, like:
<struts> <package namespace="/myactions" name="myactions" extends="oval-default"> <action name="simpleFieldsXMLChild" class="org.apache.struts2.interceptor.SimpleFieldsXMLChild"> <interceptor-ref name="ovalValidationStack"/> <result type="void"></result> </action> </package> </struts>
Annotations
OVal provides many annotations for validations that can be used out of the box (custom validators can also be defined). Once the "ovalValidation" interceptor is applied to an action, you can annotate it:
public class SimpleField extends ActionSupport{ @NotNull() @NotEmpty @Length(max = 3) private String name; ... }
Use the @AssertValid annotation to validate nested objects, like
public class MemberObject extends ActionSupport { @AssertValid private Person person = new Person(); public Person getPerson() { return person; } }
XML Configuration
OVal provides support for defining the validation via XML. Validation files must end in "-validation.xml" and the rules to find them, are the same rules used to find the validation XML files used by the regular validation mechanisms (default validation in xwork):
- Per Action class: in a file named ActionName-validation.xml
- Per Action alias: in a file named ActionName-alias-validation.xml
- Inheritance hierarchy and interfaces implemented by Action class: The plugin searches up the inheritance tree of the action to find default validations for parent classes of the Action and interfaces implemented
Here is an example of an XML validation file:
<?xml version="1.0" encoding="UTF-8"?> <oval xmlns="http://oval.sf.net/oval-configuration" xmlns:xsi="http://http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://oval.sf.net/oval-configuration http://oval.sourceforge.net/oval-configuration-1.3.xsd"> <class type="org.apache.struts2.interceptor.SimpleFieldsXML" overwrite="false" applyFieldConstraintsToSetters="true"> <field name="firstName"> <notNull/> </field> </class> </oval>
Profiles
A profile is a set of validations, that can be enabled for a method in an action, for example:
import org.apache.struts2.validation.Profiles; public class FieldsWithProfiles extends ActionSupport { @NotNull(profiles = "1") private String firstName; @NotNull(profiles = "2") private String middleName; @NotNull(profiles = "3") private String lastName; @Profiles({"1", "3"}) public String firstAndLast() { return SUCCESS; } @Profiles({"2"}) public void middle() { return SUCCESS; } }
In this example, when firstAndLast() is executed, the fields firstName and lastName will be validated. When middle() is executed, only middleName will be validated. When a method is annotated with the Profiles annotation, only the validations in the specified profiles will be performed. If no profile is specified for an action method, all the validations in the class will be evaluated.
Internationalization of messages
The OVal annotations (and corresponding XML tags) have a message attribute that can be used to specify either the error message, or the key of the error message. If a key is found in a property file, matching the value of the massage attribute, it will be used as the message, otherwise the value will be used as a literal string. For example, given this property file:
notnull.field=${field.name} cannot be null field.too.long=${field.name} value is too long, allowed length is ${max}
and this class:
public class BookActionextends ActionSupport { @NotNull(message = "notnull.field") @Length(max = 3, message = "field.too.long") private String title; @NotNull(message = "You must enter a valid ISBN") private String isbn; ... }
When that action is validated, the field errors would be:
- "title cannot be null"
- "You must enter a valid ISBN"
- "title value is too long, allowed length is 3"
The current OVal "context" object is pushed into the stack for each validator, so it can be accessed from the property file to build the error message. See the OVal javadoc for more properties available in the FieldContext class.
The OVal Validation Interceptor
This interceptor runs the action through the standard validation framework, which in turn checks the action against any validation rules (found in files such as ActionClass-validation.xml) and adds field-level and action-level error messages (provided that the action implements com.opensymphony.xwork2.ValidationAware). This interceptor is often one of the last (or second to last) interceptors applied in a stack, as it assumes that all values have already been set on the action.
This interceptor does nothing if the name of the method being invoked is specified in the excludeMethods parameter. excludeMethods accepts a comma-delimited list of method names. For example, requests to foo!input.action and foo!back.action will be skipped by this interceptor if you set the excludeMethods parameter to "input, back".
Note that this has nothing to do with the com.opensymphony.xwork2.Validateable interface and simply adds error messages to the action. The workflow of the action request does not change due to this interceptor. Rather, this interceptor is often used in conjuction with the workflow interceptor.
NOTE: As this method extends off MethodFilterInterceptor, it is capable of deciding if it is applicable only to selective methods in the action class. See MethodFilterInterceptor for more info.
The param alwaysInvokeValidate (default to true), will make the interceptor invoke validate() on the action, if the action implements Validateable.
The param programmatic (defaults to true), will make the plugin call validateX() where X is the name of the method that will be invoked in the action. If this param is set to false, alwaysInvokeValidate is ignored and validate() won't be invoked.
Installation
The jar plugin needs to be added to the lib directory of your application as well as other dependencies. If you are using XML validation, XStream needs to be included. Here is the maven dependency example:
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.3.1</version> </dependency>
Configuration reference
Add a constant element to your struts config file to change the value of a configuration setting, like:
<constant name="struts.oval.validateJPAAnnotations" value="true" />
Name |
Default Value |
Description |
---|---|---|
struts.oval.validateJPAAnnotations |
false |