Thursday, April 01, 2010

Grails like Validation plugin for Griffon

Recently I am working on a Griffon powered Swing application in one of my open source project Hydra Cache. While really love the convention over configuration setup and the grooviness of swing builder, soon I realized one tool I rely on frequently in Grails is missing in Griffon. Griffon does not tie the model to database via GORM as Grails does, which makes perfect sense since when building rich client application in many cases your model layer is not (or some will argue should not) directly tie to the database, after all that's why the 3-tier architecture was invented in the first place. That's when I start thinking if the convenient declaration based constraint and validation support in Grails can live without GORM but be applied on simple POGO model classes in Griffon. After writing validation listeners on the view a couple of times, my laziness pushed me to create a plugin to do just that. After a few positive and encouraging email exchange on dev@griffon.codehaus.org mail list and a few late night coding session, the first release of GValidation plugin is now ready for your evaluation. The plugin is implemented without dependency on Spring framework and purely implemented in Groovy.

To install the plugin use:

griffon install-plugin validation

Once the plugin is installed the following field and method will be automatically injected into your model classes:


Errors errors
boolean hasErrors()
boolean validation()


Here error field is a Groovy clone of Spring Validation Errors class in order to retain certain API consistency when compared with Grails validation support. Now in a typical scenario you can achieve the generic validation by first declare your constraints in the model:


class PersonModel {
@Bindable String name
@Bindable String email
@Bindable String blog

static constraints = {
name(blank: false)
email(blank: false, email: true)
blog(url: true)
}
}

Then perform the validation, usually in a controller action:



def doSomething = {evt = null ->
if (!model.validate()) {
doLater {
// display error messages
}
} else {
doLater {
// clear error messages
}

doOutside {
// do something interesting
}
}
}


You can also check and manipulate the errors generated by validation method using the errors object directly:



model.validate()
// do something else
..
if(model.hasErrors()){
model.errors.each{error->
// do something with the error
}
}

The only validators that are not ported from Grails are:
  • scale
  • unique
Since they are largely there to influence database schema generation rather than performing actual validation. A new validator inetAddress is introduced to ensure the field is a valid host name or IP address. For a complete list of the built-in validator shipped with this plugin please see the GValidation Wiki.

Just like Grails constraints, you can also implement your custom validator using Groovy closure:



// Simple custom validator
even( validator: {
return (it % 2) == 0
})


// Custom validator with access to the object under validation
password1( validator: {
val, obj ->
obj.properties['password2'] == val
})


// Custom validator with custom error
magicNumber( validator: {
val, obj ->
def result = checkMagicNumber()
if(!result)
obj.errors.rejectValue('magicNumber', 'customErrorCode')
return result
})




And last but not least once installed, GValidation allows you to enhance any POGO object in your application to have validation support, just simply use the ValidationEnhancer with your object:



import net.sourceforge.gvalidation.ValidationEnhancer

ValidationEnhancer.enhance(pogo)

pogo.validate()

poso.errors.each{
println it
}

For more information please check out the Wiki page, and feel free to send me your feedback or suggestion. For bug report please use the Bug Tracker.

1 comment:

w3c said...

Nice information, I really appreciate the way you presented.Thanks for sharing..

http://www.w3cvalidation.net/