Search code examples
grailsgrails-orm

Custom error message not working in gorm with grails


Can't seem to get custom validation messages working on Grails 2.3.7.

class Team {
   int id
   String email

   static mapping = {
     id     column:'TEAM_ID', generator:'native'
     email  column:'TEAM_EMAIL' 
   }
   static constraints = { 
     email  unique:true
   }

messages.properties (tried all of these...)

team.email.unique=Email already used!
Team.email.unique=Email already used!
my.package.Team.email.unique=Email already used!

Validation problems are picked up by my service, but the custom error message is never used:

Team t = new Team(...)
if(!t.validate())
   println t.errors

outputs...

Field error in object 'Team' on field 'email': rejected value.... ...
default message [Property [{0}] of class [{1}] with value [{2}] must be unique]

Not sure what's the issue, according to docs the convention is:

[Class Name].[Property Name].[Constraint Code]

Extra Configuration

BuildConfig

dependencies {
    compile('com.oracle:ojdbc6:11.2.0')
}
plugins {
    build ":tomcat:7.0.52.1"
    runtime ":hibernate:3.6.10.9"
}

DataSource

 dialect  =  "org.hibernate.dialect.Oracle10gDialect"
 hibernate {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
    singleSession = false 
}

Solution

  • It's className.propertyName.unique according to the unique constraint doc page at http://grails.org/doc/2.3.7/ref/Constraints/unique.html but println t.errors will always look like what you're seeing - the toString() result isn't very useful. To see resolved/translated messages you can test what you're doing in a test or test app, and you can use this to display the resolved messages:

    // dependency injection in controller/service/etc.
    def messageSource
    
    ...
    
    Locale locale = Locale.getDefault()
    def stringsByField = [:].withDefault { [] }
    
    for (fieldErrors in t.errors) {
       for (error in fieldErrors.allErrors) {
          String message = messageSource.getMessage(error, locale)
          stringsByField[error.field] << message
       }
    }
    
    println stringsByField