Monday, February 15, 2010

Accessing Grails domain constraints at runtime

Grails (well GORM, Grails Object Relational Mapping) makes the validation of persistable objects easy. Take the following domain class.
class User {

String username
String passwd

static constraints = {
username(blank:false, unique: true)
passwd(blank:false, minSize:7)
}

}
The above domain class defines a "User" that contains a user name and password. The user name must not be blank and must be unique. The password must not be blank and must be a minimum of 7 characters in length.

I recently stumbled upon a use case where I was required to automatically generate a password, and of course this password needed to conform to the validation constraints defined in the "User" domain class. I didn't want to hard code the minimum size of the password because there is always a chance it will change in the future. What I needed was a way to obtain the "minSize" constraint value of the "passwd" property.

Here is how I did it
def constrainedProperty = User.constraints.passwd
def minSizeConstraint = constrainedProperty.getAppliedConstraint('minSize')
def length = minSizeConstraint.getMinSize()
The above code snippet first obtains an instance of org.codehaus.groovy.grails.validation.ConstrainedProperty which is an under the hood class that provides the ability to set constraints against a property of a domain class (in this case "user.passwd"). I then call the "ConstrainedProperty" instance to get the applied constraint of "minSize" which then returns an instance of org.codehaus.groovy.grails.validation.MinSizeConstraint. The "MinSizeConstraint" class is the class that is charged with performing the actual validation of the "minSize" constraint, and so therefore also contains the value of the minimum size of the "passwd" field I am concerned with. I can now easily generate a password that is greater in length than the "length" variable, currently 7.

Easy peasy

3 comments:

Anonymous said...

Fine! Under grails 1.3.6 it is working. But can you explain why under grails script (my own) this like code does not working! And exact same code in bootstrap.groovy is working as except!!
Seems that classloader does not do the same things for classes, because def constrainedProperty = Kuulo.constraints.nimi and cls.constraints."$propname" are not working under script. I have used both: this.class.classLoader.rootLoader.addURL(classLoadPath) def clsName = ... def cls = Class.forName(clsName); or boolean resolve = true
Class cls = this.class.classLoader.loadClass(clsName, resolve)
And used: import ...

Anonymous said...

Earlier comment was: tuomas.kassila@gmail.com
Thanks in advance!

Chris said...

Under Grails 1.3.5 I have been simply able to use "User.constraints.passwd.minSize" without having to go via constrainedProperty

Post a Comment