12.5 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:

  1. package com.mycompany.myapp
  2. class User {
  3. ...
  4. static constraints = {
  5. login size: 5..15, blank: false, unique: true
  6. password size: 5..15, blank: false
  7. email email: true, blank: false
  8. age min: 18
  9. }
  10. }

If a constraint is violated, Grails looks by convention for a message code:

ConstraintError Code
blankclassName.propertyName.blank
creditCardclassName.propertyName.creditCard.invalid
emailclassName.propertyName.email.invalid
inListclassName.propertyName.not.inList
matchesclassName.propertyName.matches.invalid
maxclassName.propertyName.max.exceeded
maxSizeclassName.propertyName.maxSize.exceeded
minclassName.propertyName.min.notmet
minSizeclassName.propertyName.minSize.notmet
notEqualclassName.propertyName.notEqual
nullableclassName.propertyName.nullable
rangeclassName.propertyName.range.toosmall or className.propertyName.range.toobig
sizeclassName.propertyName.size.toosmall or className.propertyName.size.toobig
uniqueclassName.propertyName.unique
urlclassName.propertyName.url.invalid
validatorclassname.propertyName. + String returned by Closure

In the case of the 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:

  1. user.login.blank=Your login name must be specified!

The class name is looked for both with and without a package, with the packaged version taking precedence. So for example, com.mycompany.myapp.User.login.blank will be used before user.login.blank. This allows for cases where your domain class message codes clash with a plugin’s.

For a reference on what codes are for which constraints refer to the reference guide for each constraint (e.g. blank).

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:

  1. <g:hasErrors bean="${user}">
  2. <ul>
  3. <g:eachError var="err" bean="${user}">
  4. <li><g:message error="${err}" /></li>
  5. </g:eachError>
  6. </ul>
  7. </g:hasErrors>

In this example within the body of the eachError tag we use the message tag in combination with its error argument to read the message for the given error.