7 Validation - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
Table of Contents
7 Validation
Grails validation capability is built on Spring's Validator API and data binding capabilities. However Grails takes this further and provides a unified way to define validation "constraints" with its constraints mechanism.
La capacidad de validacion de Grails esta integrada en Spring's Validator API y en las capacidades de data binding. Sin embargo Grails lleva esto mas alla y provee una forma unificada para definir la validacion de "restricciones" con su propio mecanismo de restricciones.
Constraints in Grails are a way to declaratively specify validation rules. Most commonly they are applied to domain classes, however URL Mappings and Command Objects also support constraints.
Las restricciones en Grails son una forma de especificar reglas de validacion declarativamente. Comunmente son aplicadas a domain classes, sin embargo URL Mappings y Command Objects tambien soportan restricciones.
7.1 Declaring Constraints
Within a domain class constraints are defined with the constraints property that is assigned a code block:class User {
String login
String password
String email
Integer age static constraints = {
…
}
}class User {
... static constraints = {
login size: 5..15, blank: false, unique: true
password size: 5..15, blank: false
email email: true, blank: false
age min: 18
}
}login property must be between 5 and 15 characters long, it cannot be blank and must be unique. We've also applied other constraints to the password, email and age properties.
By default, all domain class properties are not nullable (i.e. they have an implicit nullable: false constraint). The same is not true for command object properties, which are nullable by default.
A complete reference for the available constraints can be found in the Quick Reference section under the Constraints heading.A word of warning - referencing domain class properties from constraints
It's very easy to attempt to reference instance variables from the static constraints block, but this isn't legal in Groovy (or Java). If you do so, you will get aMissingPropertyException for your trouble. For example, you may try
class Response {
Survey survey
Answer answer static constraints = {
survey blank: false
answer blank: false, inList: survey.answers
}
}inList constraint references the instance property survey? That won't work. Instead, use a custom validator:class Response {
…
static constraints = {
survey blank: false
answer blank: false, validator: { val, obj -> val in obj.survey.answers }
}
}obj argument to the custom validator is the domain instance that is being validated, so we can access its survey property and return a boolean to indicate whether the new value for the answer property, val, is valid.
7.2 Validating Constraints
Validation Basics
Basicos de Validacion
Call the validate method to validate a domain class instance:
Llame al metodo validate para validar la instancia de una clase de dominio:def user = new User(params)if (user.validate()) { // do something with user } else { user.errors.allErrors.each { println it } }
The
La propiedad errors property on domain classes is an instance of the Spring Errors interface. The Errors interface provides methods to navigate the validation errors and also retrieve the original values.
errors en las clases de dominio es una instancia de la interfaz Errors de Spring. La interfaz Errors provee metodos para navegar por los errores de validacion y tambien obtener los valores originales.Validation Phases
Fases de Validacion
Within Grails there are two phases of validation, the first one being data binding which occurs when you bind request parameters onto an instance such as:
Dentro de Grails existen dos fases de validacion, la primera siendo data binding la cual ocurre cuando se ligan los parametros de la peticion dentro de una instancia tal como:def user = new User(params)
At this point you may already have errors in the
En este punto puede ya haber errores en la propiedad errors property due to type conversion (such as converting Strings to Dates). You can check these and obtain the original input value using the Errors API:
errors por el tipo de conversion (tal como convertir cadenas en fechas). Puede checar estos y obtener el valor original que se introdujo usando la API de Errors:if (user.hasErrors()) { if (user.errors.hasFieldErrors("login")) { println user.errors.getFieldError("login").rejectedValue } }
The second phase of validation happens when you call validate or save. This is when Grails will validate the bound values againts the constraints you defined. For example, by default the save method calls
La segunda fase de validacion ocurre cuando se llama a validate o save. Aqui es cuando Grails validara los valores obligados contra las constraints que usted definio. Por ejemplo, por defecto el metodo save llama a validate before executing, allowing you to write code like:
validate antes de ejecutarlo, permitiendole escribir codigo como:if (user.save()) { return user } else { user.errors.allErrors.each { println it } }
7.3 Validation on the Client
Displaying Errors
Typically if you get a validation error you redirect back to the view for rendering. Once there you need some way of displaying errors. Grails supports a rich set of tags for dealing with errors. To render the errors as a list you can use renderErrors:<g:renderErrors bean="${user}" /><g:hasErrors bean="${user}"> <ul> <g:eachError var="err" bean="${user}"> <li>${err}</li> </g:eachError> </ul> </g:hasErrors>
Highlighting Errors
It is often useful to highlight using a red box or some indicator when a field has been incorrectly input. This can also be done with the hasErrors by invoking it as a method. For example:<div class='value ${hasErrors(bean:user,field:'login','errors')}'> <input type="text" name="login" value="${fieldValue(bean:user,field:'login')}"/> </div>
login field of the user bean has any errors and if so it adds an errors CSS class to the div, allowing you to use CSS rules to highlight the div.Retrieving Input Values
Each error is actually an instance of the FieldError class in Spring, which retains the original input value within it. This is useful as you can use the error object to restore the value input by the user using the fieldValue tag:<input type="text" name="login" value="${fieldValue(bean:user,field:'login')}"/>FieldError in the User bean and if there is obtain the originally input value for the login field.
7.4 Validation and Internationalization
Another important thing to note about errors in Grails is that error messages are not hard coded anywhere. The FieldError class in Spring resolves messages from message bundles using Grails' i18n support.Constraints and Message Codes
The codes themselves are dictated by a convention. For example consider the constraints we looked at earlier:package com.mycompany.myappclass User { ... static constraints = { login size: 5..15, blank: false, unique: true password size: 5..15, blank: false email email: true, blank: false age min: 18 } }
[Class Name].[Property Name].[Constraint Code]blank constraint this would be user.login.blank so you would need a message such as the following in your grails-app/i18n/messages.properties file:user.login.blank=Your login name must be specified!
Displaying Messages
The renderErrors tag will automatically look up messages for you using the message tag. If you need more control of rendering you can handle this yourself:<g:hasErrors bean="${user}"> <ul> <g:eachError var="err" bean="${user}"> <li><g:message error="${err}" /></li> </g:eachError> </ul> </g:hasErrors>
error argument to read the message for the given error.
7.5 Validation Non Domain and Command Object Classes
Domain classes and command objects support validation by default. Other classes may be made validateable by defining the staticconstraints property in the class (as described above) and then telling the framework about them. It is important that the application register the validateable classes with the framework. Simply defining the constraints property is not sufficient.The Validateable Annotation
Classes which define the staticconstraints property and are annotated with @Validateable can be made validateable by the framework. Consider this example:// src/groovy/com/mycompany/myapp/User.groovy package com.mycompany.myappimport grails.validation.Validateable@Validateable class User { ... static constraints = { login size: 5..15, blank: false, unique: true password size: 5..15, blank: false email email: true, blank: false age min: 18 } }
Registering Validateable Classes
If a class is not marked withValidateable, it may still be made validateable by the framework. The steps required to do this are to define the static constraints property in the class (as described above) and then telling the framework about the class by assigning a value to the grails.validateable.classes property in Config.groovy@:grails.validateable.classes = [com.mycompany.myapp.User, com.mycompany.dto.Account]

