I was looking for something like annotations driven validation for Groovy. Something like JSR-175 but... without JSR-175. Maybe something like Spring Validator would be nice but... without Spring.
Something like this:
class FooBeanWithValidations {
@NotEmpty
String id
}
I have reviewed some options, but i was looking for somthing very simple and plain...so, finally, i have to write it by myself...
First I defined the annotation class:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NotEmpty {
}
And then i writed a Validation class which handles the annotations and performs validation logic:
class Validator {
/**
* Helper method for apply a closure over all annotated bean properties
*/
protected static def forEachAnnotatedField(def clazz, def annotationClass, def closure) {
if (clazz in [Object, GroovyObject]) {
return
}
def properties = clazz.declaredFields
def annotated = []
annotated.addAll(properties.findAll {field ->
def annot = field.annotations.find {annotation->
return (annotationClass.isAssignableFrom(annotation.class))
}
if (annot){
closure(field, annot, clazz)
}
})
forEachAnnotatedField(clazz.superclass, annotationClass, closure)
}
/**
* Perform NonEmpty validations
*/
static def validateNotEmpty(def bean) {
forEachAnnotatedField (bean.class, NotEmpty.class) {field, annotation, clazz ->
def value = bean."${field.name}"
//Be aware with boolean values. False value are not empties!!
if (value instanceof Boolean) {
return
}
if (!value){
throw new ValidationException(bean, field.name, null)
}
}
}
static def validate(def bean) {
//Call other validation methods
validateNotEmpty(bean)
}
}
And voila... you can call validate method over any bean using Groovy Categories:
def bean = new FooBeanWithValidations()
use(Validator) {
bean.validate()
}
Or you can inject a validation method int bean's MetaClass
FooBeanWithValidations.metaClass.validate = {Validator.validate(this)}