Wednesday, 23 September 2009

Custom Validation Messages in Grails

Grails stores its validation messages in a set of external files that can be found in the grails-app/i18n directory - there are several files, with each file targeting a different language.

This means you can internationalise your application with relative ease, by adding messages to these files in the appropriate language and having Grails select the appropriate language at runtime (or per session).

You can also add bespoke validation messages that override the 'default' messages provided. For example, the messages.properties file contains lines such as:

default.blank.message=Property [{0}] of class [{1}] cannot be blank

This means that if one of your classes fails validation because a field is empty, then a message saying something like the following is added to its errors property (and typically displayed through a flash message):

Property [password] of class [user] cannot be blank

This is OK during development, but is not going to be particularly friendly for your average user - thankfully you can override these default messages on a class-by-class basis, so you user sees messages such as:

Password required

However, it can be very difficult to find documentation on what the 'identifiers' of these messages should be (the bit on the left-hand side in message.properties).

The format of each identifier is:

${class}.${property}.${error}

Unfortunately the ${error} section does not directly match the existing contents of the messages.properties file or the labels used within the contraints section of your domain class.

The list below shows the available ${error} properties to use when defining your own validation messages:
  • blank
  • email.invalid
  • not.inList
  • matches.invalid
  • maxSize.exceeded
  • minSize.notmet
  • nullable
  • size.toobig
  • size.toosmall
  • unique
  • url.invalid
  • validator.error
Consider the following domain-class as an example:

package com.example.myapp

class User {
String username
String password
String emailAddress

static constraints = {
username(blank:false, unique:true)
password(blank:false, minSize:6)
emailAddress(blank:false, email:true)
}
}

This means that we can define bespoke messages in message.properties as follows:

user.username.blank=Username required
user.username.unique=Username must be unique
user.password.blank=Password required
user.password.minSize.notmet=Password is too short
user.emailAddress.blank=Email required
user.emailAddress.email.invalid=Email not recognised

One final note: If your class is declared within a package, you do not need to specify the full class name.

7 comments:

  1. Hey i tried adding user.username.blank to my message.properties file but it was of no use..I have the same domain class as urs...Anything i missed out? I am trying to create a sample application in groovy on grails

    ReplyDelete
  2. Hi Prabha - I've just tested this here (Grails 1.1.1) and it works fine.

    I wondered if it might be the package (com.example.myapp) that was catching you out, but in both cases you simply need the following in 'messages.properties':

    user.username.blank=Whatever

    Could it be a typo or the case of the 'username' property?

    They have to be spot on otherwise no match is found and you simply get the default message...

    ReplyDelete
  3. I didn't know this Grails feature. I will try it. Thx for this great article.
    Fabien.

    ReplyDelete
  4. Hi! This is a great article, but I was wondering what how to set messages to custon validators? A clue?

    ReplyDelete