Dashboard > Stripes > ... > References > Validation Reference > Information > Page Comparison
Validation Reference Log In | Sign Up   View a printable version of the current page.

compared with
Current by Aaron Porter
on May 27, 2010 21:03.

 
Key
These lines were removed. This word was removed.
These lines were added. This word was added.

View page history


There are 7 changes. View first change.

 This document describes how valiation works in Stripes, how you specify validations, and how ActionBeans interact with validation. It includes the following sections:
 {toc:anchor=true|layout=list|minLevel=2}
  
 h2. Overview
  
 Validation is conceptually broken into three areas in Stripes:
 * Annotation Driven Validation
 * Type Converstion
 * Custom Validation
  
 Annotation Driven Validation is named thusly because the way the validation rules are specified is through annotations in the ActionBean. These Validations apply to single fields in the form/ActionBean, and encapsulate common and often used validations.
  
 Type Conversion is the process of converting a single form field input from the String value in the HttpServletRequest into a Java object (of any Class, including String). Type conversion is a core part of the validation process, and is easy to extend to new or custom types.
  
 Custom Validation is the name given to the validation performed by arbitrary Java code in one or more validation methods in an ActionBean. An ActionBean can define zero, one or many validation methods and apply them in different scenarios.
  
 h3. Validation Processing Flow
  
 Given the different kinds of validation on offer, one might ask how they are applied, and what happens when errors are produced at any stage. The following is the general flow:
 # Required field validation is run first
 # For fields that have no errors after required field validation
 ## Perform minimum/maximum length and mask validations
 ## If the field still has no errors, convert to the target type and bind the property to the ActionBean
 ## If the field converted without errors, run any min/max _value_ checks (for numbers)
 # For fields that have no errors, evaluate expression based validations
 # If there are still no errors, run custom validation (unless overridden to run with errors)
  
 This strategy is designed to catch the largest possible number of validation errors possible in a single pass. Thus if the user forgets to enter one value, and mis-types another, they will be presented with both errors the first time they submit the form - but they will not be presented with any additional (e.g. minimum length violation) errors for the field that was required but not supplied. Lastly it should be noted that the reason custom validation is run only when other validations succeed is so that it can rely on the ActionBean being in a well defined. This is, however, configurable (see the [Configuration Reference|Configuration Reference#Validation Properties]).
  
 As we will see in the sections [Selectively Disabling Validation] and [Changing Validation Outcomes] this is not the whole story, but it's good enough for now.
  
 h2. Validation Error Classes
  
 Before we go much further, a quick tour of the different validation error classes is in order. We'll be seeing a lot about validation errors in the next few sections, so it is worthwhile to understand the different types available, and how they are used.
  
 [ValidationError|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/ValidationError.html] is an interface that specifies the methods that all validation error types must support. This makes it easy to have multiple different error classes that offer different functionality. It also means that you can write your own error classes easily if you are not satisfied with the ones that Stripes supplies (hopefully that won't be the case).
  
 [SimpleError|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/SimpleError.html] is, as it says, a simple implementation or {{ValidationError}}. It allows a hard-coded message (or one supplied at construction time) to be used, and provides the ability to insert the name and value of the field (and other arbitrary bits of information) into the message.
  
 [LocalizableError|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/LocalizableError.html] extends {{SimpleError}} with the capability to look up the error message in an external resource bundle. The name of the bundle can be configured - to do this take a look at the [Configuration Reference|Configuration Reference#LocalizationBundleFactory]. Looks twice, once with the key prefixed with the action path of the ActionBean being used, and once with the exact key provided.
  
 [ScopedLocalizableError|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/ScopedLocalizableError.html] extends {{LocalizableError}} and provides the ability to perform "scoped searches" for an error message. In reality this just means looking for error messages in the resource bundle with names corresponding to:
 - {{<actionPath>.<fieldName>.<errorName>}}
 - {{<actionPath>.<fieldName>.errorMessage}}
 - {{<fieldName>.<errorName>}}
 - {{<fieldName>.errorMessage}}
 - {{<actionPath>.<errorName>}}
 - {{<defaultScope>.<errorName>}}
  
 In the descriptions below you will see reference to "default scope" and "error name", which refer to how a {{ScopedLocalizableError}} is found. All the built in validations in Stripes use {{ScopedLocalizableError}}, so that you can specify fairly generic messages at a high level and override them as you see fit.
  
 All of the error messages in Stripes use [java.text.MessageFormat|http://java.sun.com/j2se/1.5.0/docs/api/java/text/MessageFormat.html] which allows you to provide parameters to be merged in to the message. The first two parameters (0 and 1 respectively) are always the field name and field value respectively. An example follows, but check the individual error class javadocs, and the javadoc for {{MessageFormat}} for more details:
 {code:title=Example error message specification}
 myCustomError={0} must be formatted mm/dd/yy. {1} is not a valid date.
 {code}
  
 h2. Annotation Driven Validation
  
 There are two annotations for adding validations to fields. The {{@Validate}} annotation is used to specify validations for scalar or simple properties within an ActionBean. The {{@ValidateNestedProperties}} annotation is used to aggregate one or more {{@Validate}} annotations in order to specify validations for nested properties of complex types. The annotations can be attached to either the getter or setter methods on the ActionBean. They can also be attached directly to the properties (even private ones).
  
 Each {{@Validate}} can specify multiple validations for a single property. The following example demonstrates how to use the annotations:
 {code:title=Using Validation Annotations}
 @Validate(required=true, minvalue=13, maxvalue=120)
 private int age; // annotated right on the field
  
 @ValidateNestedProperties({
  @Validate(field="line1", required=true, minlength=5, maxlength=50),
  @Validate(field="line2", minlength=5, maxlength=50),
  @Validate(field="zip", required=true, mask="\\d{5}(-\\d{4})?")
 })
 public Address getAddress() { ... }
 {code}
 The following sections walk through the syntax of each validation that can be specified with the {{@Validate}} annotation.
  
 h3. @Validate(field="...")
  
 The field property is used only when the {{@Validate}} annotation is nested within a {{@ValidateNestedProperties}} annotation. It is used to specify the property of the complex type to which the validation applies.
  
 h3. @Validate(required=true/false)
  
 Specifies whether or not the annotated field is required when the form is submitted. Defaults to false (so it's never necessary to write required=false even though you can). If a required field is not supplied a single error is generated. The "default scope" is specified as {{validation.required}} and the error name is {{valueNotPresent}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueNotPresent
 - actionPath.fieldName.errorMessage
 - fieldName.valueNotPresent
 - fieldName.errorMessage
 - actionPath.valueNotPresent
 - validation.required.valueNotPresent
  
 h3. @Validate(on="...")
  
 The 'on' attribute of the {{@Validate}} annotation does not perfom any validation itself, but restricts the application of the {{required}} check. To reiterate: it modifies when the {{required}} check is applied - not other validations specified at the same time.
  
 By default required field validation is applied to all events not marked with {{@DontValidate}}. However, by specifying one or more event names in the 'on' attribute it can be restricted to just those events. For example:
 {code}
 @Validate(required=true, on={"save", "update"}) private String description;
 @Validate(required=true, on="delete") private boolean confirm;
 {code}
  
 The list can also be inverted by supplying event names prefixed with '!'s, for example:
 {code}
 @Validate(required=true, on="!delete") private String description;
 @Validate(required=true, on="delete") private boolean confirm;
 {code}
  
 Note: you *cannot* mix event names with and without '!'s for the same property, e.g. \{"!delete", "save"\}.
  
 h3. @Validate(minlength=##)
  
 Specifies the minimum length that the pre-conversion String must be. For example you might specify that a password field must have a minimum length of 6. Doing so would require the password to be six characters in length or greater. If a field fails the minimum length test a single validation error is generated. The default scope is {{validation.minlength}} and the error name is {{valueTooShort}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueTooShort
 - actionPath.fieldName.errorMessage
 - fieldName.valueTooShort
 - fieldName.errorMessage
 - actionPath.valueTooShort
 - validation.minlength.valueTooShort
  
 The error message is supplied with an additional parameter (which can be used as \{2\} in the message text) which is the minimum length constraint that was violated - e.g. 6 in the example above.
  
 h3. @Validate(maxlength=##)
  
 Specifies the maximum length that the pre-conversion String may be. For example you might specify that a username field may have a maximum length of 25. Doing so would require the username to be twenty-five characters in length or less. If a field fails the maximum length test a single validation error is generated. The default scope is {{validation.maxlength}} and the error name is {{valueTooLong}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueTooLong
 - actionPath.fieldName.errorMessage
 - fieldName.valueTooLong
 - fieldName.errorMessage
 - actionPath.valueTooLong
 - validation.maxlength.valueTooLong
  
 The error message is supplied with an additional parameter (which can be used as \{2\} in the message text) which is the maximum length constraint that was violated - e.g. 25 in the example above.
  
 h3. @Validate(minvalue=##)
  
 Specifies the minimum value for a numeric type (after it has been converted to a number). For example you might specify an age field has a minvalue of 0 to enforce non-negative ages\! If a field fails the minimum value test a single validation error is generated. The default scope is {{validation.minvalue}} and the error name is {{valueBelowMinimum}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueBelowMinimum
 - actionPath.fieldName.errorMessage
 - fieldName.valueBelowMinimum
 - fieldName.errorMessage
 - actionPath.valueBelowMinimum
 - validation.minvalue.valueBelowMinimum
  
 The error message is supplied with an additional parameter (which can be used as \{2\} in the message text) which is the minimum value constraint that was violated - e.g. 0 in the example above.
  
 h3. @Validate(maxvalue=##)
  
 Specifies the maximum value for a numeric type (after it has been converted to a number). If a field fails the maximum value test a single validation error is generated. The default scope is {{validation.maxvalue}} and the error name is {{valueAboveMaximum}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueAboveMaximum
 - actionPath.fieldName.errorMessage
 - fieldName.valueAboveMaximum
 - fieldName.errorMessage
 - actionPath.valueAboveMaximum
 - validation.maxvalue.valueAboveMaximum
  
 The error message is supplied with an additional parameter (which can be used as \{2\} in the message text) which is the maximum value constraint that was violated.
  
 h3. @Validate(mask=".*")
  
 Specifies a regular expression that the user's input must match. The mask is compiled using [java.util.regex.Pattern|http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html] \- if you are not familiar with regular expressions, the documentation for the Pattern class provides a good introduction to the syntax. The entire String submitted must match the mask/pattern supplied, as specified by {{Pattern.matcher(input).matches()}}.
  
 If the input does not match the mask, a single validation error is output with the default scope {{validation.mask}} and the error name {{valueDoesNotMatch}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueDoesNotMatch
 - actionPath.fieldName.errorMessage
 - fieldName.valueDoesNotMatch
 - fieldName.errorMessage
 - actionPath.valueDoesNotMatch
 - validation.mask.valueDoesNotMatch
  
 h3. @Validate(expression="$\{true\}")
  
 Specifies an expression using the JSP Expression Language (EL) to be evaluated. Expressions must return a boolean value. Expression validation is run after all form properties (that have passed validation so far) have been bound into the ActionBean. As a result expressions have access to all the values in the ActionBean!
  
 The value being validated is also available (of course) under the name 'this'. Other named values in the expression are resolved first by looking for an ActionBean property of the same name, and if one is not found, then by then a value is looked for in the request scope, and then the session scope. All the usual EL builtins are available, so it is also possible to access the request parameters etc.
  
 Care should be taken because, while expression validation will not be executed on null or empty values, other values referenced by the expression could still be null. Given the EL's penchant for safely handling nulls, and converting types as needed, this may lead to unexpected outcomes!
  
 Some examples are in order:
 {code}
 // Validate that a number is odd
 @Validate(expression="this % 2 == 1") private int oddNumber;
  
 // Validate that this number is bigger than the odd number
 @Validate(expression="oddNumber != null && this > oddNumber") private long biggerNumber;
  
 // Validate that a username is the current user's, or the current user is 'root'
 @Validate(expression="context.user.name=='root' || this==context.user.name") private String name;
 {code}
  
 If the expression does not evaluate to true an error is created with the default scope {{validation.expression}} and the error name {{valueFailedExpression}}. This results in an attempt to find error messages in the resource bundle with the following keys:
 - actionPath.fieldName.valueFailedExpression
 - actionPath.fieldName.errorMessage
 - fieldName.valueFailedExpression
 - fieldName.errorMessage
 - actionPath.valueFailedExpression
 - validation.expression.valueFailedExpression
  
 h3. @Validate(converter=PercentageTypeConverter.class)
  
 Specifies the [TypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/TypeConverter.html] that should be used to convert this field. This is not usually necessary as in most cases Stripes will use the right converter for the target type. Two common cases where this is useful are:
 # When you are using formats that modify the meaning of the data. E.g. formatting numbers as percentages causes 0.95 to be written as 95%. Using the default Double/Float type converter in this case would result in the value being multipled by 100 every time the user edited the value. In this case you could tell Stripes to use the PercentageTypeConverter which does the right thing.
 # When you are converting to custom types, and have decided not to write your own (very simple) [TypeConverterFactory|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/TypeConverterFactory.html]. More on this in the next section.
  
 Since this is not strictly a validation, but a way of modifying the type conversion, it does not produce any error messages.
  
 h2. Type Conversion
  
 Type conversion is quite simply the process of converting the String parameters that are supplied in the HttpServletRequest into the types of the corresponding ActionBean properties. The [TypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/TypeConverter.html] interface specifies how Stripes will interact with classes that perform type conversion. There are type converters in Stripes for most common types in Java, and adding support for additional types is as easy as coding up a new TypeConverter.
  
 Stripes gets to know about TypeConverters in one of two ways. If an {{@Validate}} annotation specifes a {{converter}} then that converter will be used, no questions asked. Otherwise Stripes will ask the configured [TypeConverterFactory|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/TypeConverterFactory.html] to supply the appropriate {{TypeConverter}} for the type being converted to. Extending the [DefaultTypeConverterFactory|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/DefaultTypeConverterFactory.html] is fairly straight-forward. See the [Configuration Reference|Configuration Reference#RuntimeConfiguration Properties] for details on how to configure Stripes to use your custom {{TypeConverterFactory}} implementation.
  
 The following sections document the individual type converters used in Stripes.
  
 h3. BooleanTypeConverter
  
 The [BooleanTypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/BooleanTypeConverter.html] determines that a value is "true" if it matches (ignoring case) any of the values "true", "t", "yes", "y" or "on" or if the value can be parsed as a number and does not equal zero.
  
 Please note that Stripes does not convert and bind parameters submitted in the request with the value "" (empty string). So while you might think that "" would convert to false, in fact conversion is never run, so the value on your ActionBean will be whatever default value is assigned to the property.
  
 Since any String can be converted to a boolean (either false or true), no validation errors are produced.
  
 h3. DateTypeConverter
  
 The [DateTypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/DateTypeConverter.html] employs a number of techniques to get the input to parse as a {{java.util.Date}}. If the input cannot be parsed into a Date then a single validation error is produced. The default scope is {{converter.date}} and the error name is {{invalidDate}}.
  
 h3. EmailTypeConverter
  
 The [EmailTypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/EmailTypeConverter.html], strictly speaking is not a _type_ converter. It uses [JavaMail|http://java.sun.com/products/javamail/index.jsp] to parse the String and return a well formatted email address _as a String_.
  
 A single validation error is produced if the address cannot be parsed. The default scope is {{converter.email}} and the error name is {{invalidEmail}}.
  
 h3. EnumeratedTypeConverter
  
 The [EnumeratedTypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/EnumeratedTypeConverter.html] converts Strings representing the names of enumerated type values, back into an instance of the enumerated type. If the value supplied does not match any of the values of the target enumerated type, a single validation error is produced. The default scope is {{converter.enum}} and the error name is {{notAnEnumeratedValue}}.
  
 h3. Number TypeConverters
  
 Stripes supplied a set of converters for converting to the Java numeric types: byte, short, int, long, float, double and their corresponding wrapper types as well as BigDecimal and BigInteger. They all operate similarly (using one or more [java.text.NumberFormat|http://java.sun.com/j2se/1.5.0/docs/api/java/text/NumberFormat.html]s). The converters make a best effort to parse a String as a number. They can handle the following without any additional effort:
 * additional white space
 * currency and non-currency numbers
 * use of the minus sign and parentheses to indicate negation
 * use of grouping characters and decimals (obviously)
  
 The number TypeConverters produce two types of error. The first error is common to all the number TypeConverters; it is generated when the String is not parsable as a number. The default scope is {{converter.number}} and the error name is {{invalidNumber}}.
  
 The second error is named differently for each number TypeConverter, but means the same; it is generated when the supplied number is out of the range for the target type. The default scope is {{converter.\[byte\|short\|integer\|float\]}} and the error name is {{outOfRange}}. For all outOfRange errors two additional parameters (\{2\} and \{3\}) are supplied to the error message. The parameters are the minimum and maximum allowable values for the type being converted to, e.g. Integer.MIN_VALUE and Integer.MAX_VALUE.
  
 h3. PercentageTypeConverter
  
 The [PercentageTypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/PercentageTypeConverter.html] converts numbers displayed as percentages (e.g. 95%) into decimal numbers (e.g. 0.95). It requires that the target type is either {{float}}, {{double}} (or the wrapper types) or {{BigDecimal}}. It produces the same error as other number classes, with a default scope of {{converter.number}} and the error name {{invalidNumber}}.
  
 h3. OneToManyTypeConverter
  
 The [OneToManyTypeConverter|http://stripes.sourceforge.net/docs/current/javadoc/index.html?net/sourceforge/stripes/validation/OneToManyTypeConverter.html] is a special type converter that converts a single value in the request into a List of values to be bound to the ActionBean. For example, if a user were to enter one or more numbers into a single field, '123, 456 789' that is converted using the {{OneToManyTypeConverter}}, a List would be bound to the ActionBean containing three numbers.
  
 The type of the elements in the List is determined based on the declared type in the ActionBean, so if you declare List<Long> you'll get Longs, if you declare List<Boolean> you'll get Booleans. Under the covers the {{OneToManyTypeConverter}} will request the appropriate type converter for the individual items, and hence will generate the same validation errors as the {{LongTypeConverter}}, {{BooleanTypeConverter}} etc.
  
 h2. Custom Validation
  
 Custom validation refers to the execution of arbitrary, custom, validation logic within the ActionBean. ActionBean classes may optionally include one or more validation methods. Validation methods are regular methods that are marked with the annotation [@ValidationMethod|http://stripes.sourceforge.net/docs/current/javadoc/index.html?net/sourceforge/stripes/validation/ValidationMethod.html]. These methods are invoked after all other validations have been run and all values have been converted and bound to the ActionBean.
  
 By default validation methods will not be invoked if preceeding validations resulted in errors. Since the ActionBean will be fully populated when validation methods are called it is safe to refer to any property of the ActionBean, or through the ActionBeanContext access values in the HttpServletRequest (though hopefully this will not be common since it makes the ActionBean less testable).
  
 It is possible to configure Stripes to, by default, invoke validation methods regardless of whether or not validation errors exist. To do this refer to the [Configuration Reference|Configuration Reference#Validation Properties]. Note that by doing this you are no longer guaranteed that all required fields have been supplied or that type conversions and binding succeeded before validation methods are called.
  
 The {{@ValidationMethod}} annotation has three attributes that allow the application of the method to be altered, all of which are completely optional. The first is the 'when' attribute which allows the developer to specify whether or not the method should be run when errors exist, regardless of the application default policy. E.g.
  
 {code}
 @ValidationMethod(when=ValidationState.ALWAYS) public void validateSomething { ... }
 @ValidationMethod(when=ValidationState.NO_ERRORS) public void validateSomethingElse { ... }
 {code}
  
 The 'on' attribute (similar to the 'on' attribute of {{@Validate}}) restricts the method to run only on certain events. By default validation methods are run without regard to the event being handled. The 'on' attribute can specify a single event, a list of events, or one or more events preceeded by '!'s. In the last case the meaning is inverted, and the method is executed on all events except those listed. E.g.
 {code}
 @ValidationMethod(on="create") public void one() { ... }
 @ValidationMethod(on="update") public void two() { ... }
 @ValidationMethod(on={"update","delete"}) public void three() { ... }
 @ValidationMethod(on="!delete") public void four() { ... }
 {code}
  
 The 'priority' attribute is useful only when multiple validation methods exist within an ActionBean and the order in which they are executed is important. Methods with lower (nearer to zero) values for the 'priority' attribute are run before those with higher values.
  
 Lastly, it should be noted that there are two ways to get access to the {{ValidationErrors}} object in order to save validation error messages. Firstly, as with any other method in the ActionBean, validation methods can call {{getContext().getValidationErrors()}} to retrieve the validation errors. However, they may also take the ValidationErrors objects as a parameter, in which case it will be supplied to the method. E.g.
  
 {code}
 @ValidationMethod public void validateSomething(ValidationErrors errors) { ... }
 {code}
  
 Lastly it should be noted that validation methods must be public, must take either zero parameters or one parameter of type ValidationErrors and may return any type, though returns will be ignored.
  
 h2. Performing Validation in Handler Methods
  
 Sometimes it's just not possible (or reasonable) to validate absolutely everything up front in validation methods. Maybe you don't have all the data you need, maybe you won't know if something really is valid until you try and do it\! For example, you might not be able to validate that a withdrawal from a bank account is valid until you do it due to concurrency issues (what if two threads check a $100 balance then allow $75 withdrawals?).
  
 In these situations you can create validation errors in your handler method, and send the user back to the page they came from (or elsewhere if you choose). The following is an example:
 {code}
 @HandlesEvent("Withdrawal")
 public Resolution withdrawFunds() {
  try {
  getAccount().withdraw( getAmount() );
  return new RedirectResolution("/account/summary.jsp");
  }
  catch (InsufficientBalanceException ibe) {
  ValidationErrors errors = new ValidationErrors();
  errors.add( "amount", new LocalizableError("/account/transaction.action.insufficientFunds") );
  getContext().setValidationErrors(errors);
  return getContext().getSourcePageResolution();
  }
 }
 {code}
  
 {anchor:Selectively Disabling Validation}
 h2. Selectively Disabling Validation
  
 Often is it desirable to have validation run for one or more events in an ActionBean, but not for others. For example the "save" method might require validation, as might the "add" method. But the "prepopulate" method might not. While usage of the 'on' attribute of {{@Validate}} and {{@ValidationMethod}} can acheive this, sometimes it's overly repetitive.
  
 Stripes uses the {{@DontValidate}} annotation to make this easier. Any handler method that is annotated with {{@DontValidate}} will be invoked directly skipping validation. Type conversion and binding are still executed, and may produce validation errors. However, it is expected that in most (all?) cases the {{@DontValidate}} annotation will be used with events whose only input is not user-input (e.g. hidden fields, select lists etc.).
  
 {anchor:Changing Validation Outcomes}
  
 h2. What Happens When There Are Errors?
  
 When one or more validation errors are registered during a request, Stripes will execute the {{Resolution}} returned by calling {{ActionBeanContext.getSourcePageResolution()}}. By default this returns a {{ForwardResolution}} which will forward the request to the same JSP page from which it originated. The page is identified by a request parameter called {{_sourcePage}} which is written as a hidden field by the Stripes form tag, and included as a parameter by the Stripes link tag.
  
 To change this behaviour at the global level it is possible to simply override the {{ActionBeanContext.getSourcePageResolution()}} method to return a different resolution.
  
 h2. Changing Validation Outcomes
  
 There are times when even the most flexible system cannot give you everything, and you want to manage the validation process at a more detailed level. You can do this by implementing the [ValidationErrorHandler|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/ValidationErrorHandler.html] interface in your ActionBean. The interface defines a single method {{handleValidationErrors(ValidationErrors errors)}} that is invoked when validation fails, but before determining what to do next.
  
 The ActionBean can manipulate the {{ValidationErrors}} in any way it sees fit and the changes will be taken into account before proceeding. If all errors are cleared out, it will be as if they never existed\! The ActionBean can also use this opportunity to undo any side-affects that might be caused by the binding process if necessary, or to substitute a different Resolution. Check out the [ValidationErrorHandler|http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/validation/ValidationErrorHandler.html] javadoc for more information.
  
 h2. Using field-metadata tag
  h2. Using the {{field-metadata}} tag
  
Stripes provides field meta data which can be used for client side validation, an example provided by Aaron Porter, using Jquery js framework:
  Stripes provides field meta data which can be used for client side validation and layout. Here is an example provided by Aaron Porter, using the jQuery JavaScript framework:
  
 (http://article.gmane.org/gmane.comp.java.stripes.user/7575)
  
(Required scripts available at http://stripes-stuff.svn.sourceforge.net/viewvc/stripes-stuff/JavaScript/trunk/scripts/jquery/)
  
 {code}
<s:field-metadata var="fieldMetadata">
 $(function(){applyStripesValidation('${fieldMetadata.formId}', ${fieldMetadata});});
 </s:field-metadata>
  <s:field-metadata var="fieldMetadata">
 $(function(){applyStripesValidation('${fieldMetadata.formId}', ${fieldMetadata});});
 </s:field-metadata>
 {code}
  
Tag outputs meta data for tags that form tag knows till the point where metadata tag is found, so normally you'll put it at the end of your form, just before closing form tag.
 (If you put it just below opening form tag, no field meta data will be printed)
 Also, if you have more than one form on your page, be sure to set form id yourself, otherwise you'll end up with duplicate form id on your page and validation will only work for one of them (if you use above mentioned jquery validation libraray from Aaron Porter)
  The {{field-metadata}} tag provides meta data for fields referenced by input tags. The tag can only provide meta data for fields referenced by tags that appear before its own position in the page code, so usually you'll put it at the end of your form, just before the closing form tag. (If you put it just below opening form tag, for example, no field meta data will be available.) Also, if you have more than one form on your page, be sure to set the form id yourself, otherwise you'll end up with a duplicated form id on your page and validation will only work for one of them.
  
Here is also example how to use it with Jquery validation plugin:
  The tag binds a block of Javascript (actually, JSON) code to a JSP variable, and generates an HTML {{script}} block around its body. The body therefore should be Javascript code that makes use of the meta data. Here is also an example of how to use the tag with a Jquery validation plugin:
 (http://machak.com/code.html)
  
 Note: visit above link for improvements, below code is a skeleton code:
  Note: visit the above link for updates and improvements. The code below is a skeletal example for illustration:
 {code}
 /**
  *
  * Jquery addapter class so we can use built in Jquery validator.
  * NOTE: this is only skeleton, implementing only small part of possible validation,
  * Usage:
  * &lt;s:field-metadata var="metaData"&gt;
  * $(function(){$.fn.stripesValidation('${metaData.formId}', ${metaData});});
  * &lt;/s:field-metadata&gt;
  * dependancies:
  * jquery.1.3.1
  * jquery.form
  * jquery.validate
  */
 (function($){
  
  /**
  * Processess Stripes meta data and converting it so jquery
  * validation plugin is used for client side validation
  * @param formId id of a form to be processed
  * @param metaData metadata that is produced by stripes tag
  */
  $.fn.stripesValidation = function(formId, metaData){
  var form = $('#' + formId);
  var mask_count = 0;
  for(var fieldName in metaData){
  var field = form.find('[name=' + fieldName + ']');
  addValidation(field, metaData[fieldName]);
  // run validation:
  form.validate();
  }
  function addValidation(field, obj){
  for(var prop in obj){
  debug(prop);
  switch(prop){
  case 'label':
  break;
  case 'required':
  if(obj[prop]){ // add only if true
  field.addClass(prop);
  }
  break;
  case 'minlength': // should already be there
  field.attr(prop, obj[prop]);
  break;
  case 'maxlength': // should already be there
  field.attr(prop, obj[prop]);
  break;
  case 'mask':
  setMask(field, obj[prop]);
  break;
  case 'typeConverter':
  setConverter(field, obj[prop]);
  break;
  default:
  debug('missing this:' + prop + ':' + [obj[prop]]);
  }
  }
  
  }
  
  /**
  * Adds regular expression validation
  * @param field field reference
  * @param mask regular expression mask
  */
  function setMask(field, mask){
  mask_count++;
  var methodRef = 'maskMethod' + mask_count;
  field.addClass(methodRef);
  $.validator.addClassRules({
  methodRef: {
  methodRef: true
  }
  });
  $.validator.addMethod(methodRef, function (value){
  return mask.test(value);
  }, 'Value is invalid');
  }
  
  /**
  * Add converter mappings
  * @param field field reference
  * @param converter converter used by stripes for given field
  */
  function setConverter(field, converter){
  if(converter == 'EmailTypeConverter'){
  field.addClass('email');
  }
  else{
  debug('missing converter mapping:' + converter);
  }
  }
  
  function debug(msg){
  if(window.console && window.console.log){
  window.console.log(msg);
  }
  }
  
  };
 })(jQuery);
  
 {code}
  
  
  
  
  
Hosting for this site is donated by the wonderful people at Contegix
Site running on a free Atlassian Confluence Open Source Project License granted to Stripes Framework. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.6.2 Build:#919 Nov 26, 2007) - Bug/feature request - Contact Administrators