Currently only in beta-status, an xwork-tiger project exists that is starting to add some basic J2SE 5 ("Tiger") support to WebWork. Currently, the only Java 5 implementation in xwork-tiger.jar is a Map and Collection support using generics.
In short, instead of specifying the types found in collections and maps as documented in Type Conversion, the collection's generic type is used. This means you most likely don't need any ClassName-conversion.properties files.
Work in progress
This is a work in progress and not yet finished! More complex examples will follow. For now, have a look at the unit tests within the xwork-tiger project path.
Create XXX-conversion.properties via "ant apt" target
This is an example for the apt ant target:
<target name="apt"> <mkdir dir="${build}/generated"/> <path id="classpath"> <pathelement path="${basedir}/build/java"/> <pathelement path="${basedir}/build/test"/> <!-- xwork.jar and xwork-tiger.jar must be in one of the following lib dirs --> <fileset dir="${basedir}/lib/build" includes="*.jar"/> <fileset dir="${basedir}/lib/default" includes="*.jar"/> <fileset dir="${basedir}/lib/spring" includes="*.jar"/> </path> <property name="pclasspath" refid="classpath"/> <!-- Change the includes attribute value to match your annotated java files --> <fileset id="sources" dir="." includes="src/test/**/*.java" /> <pathconvert pathsep=" " property="sourcefiles" refid="sources"/> <echo> CLASSPATH ${pclasspath} SOURCES: ${sourcefiles} </echo> <exec executable="apt" > <arg value="-s"/> <arg value="${build}/generated"/> <arg value="-classpath"/> <arg pathref="classpath"/> <arg value="-nocompile"/> <arg value="-factory"/> <arg value="com.opensymphony.xwork.apt.XWorkProcessorFactory"/> <arg line="${sourcefiles}"/> </exec> </target>
Type Conversion Annotations
If you want to use annotation based type conversion, you have to annotate the class or interface with the Conversion Annotation.
Currently runtime evaluation for these annotations is not supported. This feature will be added in the near future.
For now you have to run the apt target via ant (TODO: not yet in CVS).
Annotation |
Description |
---|---|
Marker annotation for type conversions at Type level. |
|
Used for class and application wide conversion rules. |
Interceptor Annotations
Annotation |
Description |
---|---|
Marks a action method that needs to be executed before the result. |
|
Marks a action method that needs to be executed before the main action method. |
|
Marks a action method that needs to be executed before the result. |
Validation Annotations
If you want to use annotation based validation, you have to annotate the class or interface with Validation Annotation.
These are the standard validator annotations that come with XWork-tiger:
Annotation |
Description |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Validations
If you want to use several annotations of the same type, these annotation must be nested within the @Validations() annotation.
The possible parameters for @Validations() are as followed:
Parameter |
Required |
Notes |
---|---|---|
requiredFields |
no |
Add list of RequiredFieldValidators |
customValidators |
no |
Add list of CustomValidators |
conversionErrorFields |
no |
Add list of ConversionErrorFieldValidators |
dateRangeFields |
no |
Add list of DateRangeFieldValidators |
emails |
no |
Add list of EmailValidators |
fieldExpressions |
no |
Add list of FieldExpressionValidators |
intRangeFields |
no |
Add list of IntRangeFieldValidators |
requiredFields |
no |
Add list of RequiredFieldValidators |
requiredStrings |
no |
Add list of RequiredStringValidators |
stringLengthFields |
no |
Add list of StringLengthFieldValidators |
urls |
no |
Add list of UrlValidators |
visitorFields |
no |
Add list of VisitorFieldValidators |
stringRegexs |
no |
Add list of StringRegexValidator |
regexFields |
no |
Add list of RegexFieldValidator |
expressions |
no |
Add list of ExpressionValidator |
@Validations( requiredFields = {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "customfield", message = "You must enter a value for field.")}, requiredStrings = {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "stringisrequired", message = "You must enter a value for string.")}, emails = { @EmailValidator(type = ValidatorType.SIMPLE, fieldName = "emailaddress", message = "You must enter a value for email.")}, urls = { @UrlValidator(type = ValidatorType.SIMPLE, fieldName = "hreflocation", message = "You must enter a value for email.")}, stringLengthFields = {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")}, intRangeFields = { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, dateRangeFields = {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "datefield", min = "-1", max = "99", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, expressions = { @ExpressionValidator(expression = "foo > 1", message = "Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 2", message = "Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 3", message = "Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 4", message = "Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 5", message = "Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.") } ) public String execute() throws Exception { return SUCCESS; }
@RequiredFieldValidator
This validator checks that a field is non-null.
Example:
@RequiredFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
@RequiredStringValidator
This validator checks that a String field is not empty (i.e. non-null with a length > 0).
Parameter |
Required |
Default |
Notes |
---|---|---|---|
trim |
no |
true |
Boolean property. Determines whether the String is trimmed before performing the length check. |
Example:
@RequiredStringValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true)
@StringLengthFieldValidator
This validator checks that a String field is of the right length. It assumes that the field is a String.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
trim |
no |
true |
Boolean property. Determines whether the String is trimmed before performing the length check. |
minLength |
no |
|
Integer property. The minimum length the String must be. |
maxLength |
no |
|
Integer property. The maximum length the String can be. |
If neither minLength nor maxLength is set, nothing will be done.
Example:
@StringLengthFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true, minLength = "5", maxLength = "12")
@StringRegexValidator
This validator checks that a String field matches a configure Regular Expression, if it is not an empty String.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
regex |
yes |
"." |
String property. The Regular Expression for which to check a match. |
caseSensitive |
no |
true |
Whether the matching of alpha characters in the expression should be done case-sensitively. |
Example:
@StringRegexValidator(message = "Default message", key = "i18n.key", shortCircuit = true, regex = "a regular expression", caseSensitive = true)
@EmailValidator
This validator checks that a field is a valid e-mail address if it contains a non-empty String.
Example:
@EmailValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
@UrlValidator
This validator checks that a field is a valid URL.
Example:
@UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
@IntRangeFieldValidator
This validator checks that a numeric field has a value within a specified range.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
min |
no |
|
Integer property. The minimum the number must be. |
max |
no |
|
Integer property. The maximum number can be. |
If neither min nor max is set, nothing will be done.
The values for min and max must be inserted as String values so that "0" can be handled as a possible value.
Example:
@IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42")
@DateRangeFieldValidator
This validator checks that a date field has a value within a specified range.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
min |
no |
|
Date property. The minimum the date must be. |
max |
no |
|
Date property. The maximum date can be. |
If neither min nor max is set, nothing will be done.
Example:
@DateRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "2005/01/01", max = "2005/12/31")
@ConversionErrorFieldValidator
This validator checks if there are any conversion errors for a field and applies them if they exist. See Type Conversion Error Handling for details.
Example:
@ConversionErrorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
@ExpressionValidator
This validator uses an OGNL expression to perform its validation. The error message will be added to the action if the expression returns false when it is evaluated against the value stack.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
expression |
yes |
|
An OGNL expression that returns a boolean value. |
Example:
@ExpressionValidator(message = "Default message", key = "i18n.key", shortCircuit = true, expression = "an OGNL expression" )
@FieldExpressionValidator
This validator uses an OGNL expression to perform its validation. The error message will be added to the field if the expression returns false when it is evaluated against the value stack.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
expression |
yes |
|
An OGNL expression that returns a boolean value. |
Example:
@FieldExpressionValidator(message = "Default message", key = "i18n.key", shortCircuit = true, expression = "an OGNL expression")
@VisitorFieldValidator
The validator allows you to forward validation to object properties of your action using the objects own validation files. This allows you to use the ModelDriven development pattern and manage your validations for your models in one place, where they belong, next to your model classes. The VisitorFieldValidator can handle either simple Object properties, Collections of Objects, or Arrays.
The error message for the VisitorFieldValidator will be appended in front of validation messages added by the validations for the Object message.
Parameter |
Required |
Default |
Notes |
---|---|---|---|
context |
no |
action alias |
Determines the context to use for validating the Object property. If not defined, the context of the Action validation is propogated to the Object property validation. In the case of Action validation, this context is the Action alias. |
appendPrefix |
no |
true |
Determines whether the field name of this field validator should be prepended to the field name of the visited field to determine the full field name when an error occurs. For example, suppose that the bean being validated has a "name" property. If appendPrefix is true, then the field error will be stored under the field "bean.name". If appendPrefix is false, then the field error will be stored under the field "name". |
Example:
@VisitorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, context = "action alias", appendPrefix = true)
Here we see the context being overridden in the validator mapping, so the action alias context will not be propogated.
ModelDriven example:
@VisitorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, context = "action alias", appendPrefix = true)
This will use the model's validation rules and any errors messages will be applied directly (nothing is prefixed because of the empty message).
More Complex Examples
An Annotated Interface
- Mark the interface with @Validation()
- Apply standard or custom annoations at method level
@Validation() public interface AnnotationDataAware { void setBarObj(Bar b); Bar getBarObj(); @RequiredFieldValidator(message = "You must enter a value for data.") @RequiredStringValidator(message = "You must enter a value for data.") void setData(String data); String getData(); }
An Annotated Class
@Validation() public class SimpleAnnotationAction extends ActionSupport { @RequiredFieldValidator(type = ValidatorType.FIELD, message = "You must enter a value for bar.") @IntRangeFieldValidator(type = ValidatorType.FIELD, min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.") public void setBar(int bar) { this.bar = bar; } public int getBar() { return bar; } @Validations( requiredFields = {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "customfield", message = "You must enter a value for field.")}, requiredStrings = {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "stringisrequired", message = "You must enter a value for string.")}, emails = { @EmailValidator(type = ValidatorType.SIMPLE, fieldName = "emailaddress", message = "You must enter a value for email.")}, urls = { @UrlValidator(type = ValidatorType.SIMPLE, fieldName = "hreflocation", message = "You must enter a value for email.")}, stringLengthFields = {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")}, intRangeFields = { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, dateRangeFields = {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "datefield", min = "-1", max = "99", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, expressions = { @ExpressionValidator(expression = "foo > 1", message = "Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 2", message = "Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 3", message = "Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 4", message = "Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 5", message = "Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.") } ) public String execute() throws Exception { return SUCCESS; } }