Announcing Grails Constraints Custom Domain Constraint Plugin

I’ve released my first public Grails Plugin today.

The Grails Constraint plugin gives you the ability to create custom Constraints that you can apply to your Domain classes to validate them. These are applied and act just like the built in Domain class constraints.

Why would you want this?

Grails provides two generic, catch-all Constraints in the core application:

  • validator – a generic closure mechanism for validation
  • matches – a regular expression mechanism

While those work, I find myself often wanting to use the same Constraints on multiple Domain classes (think Social Security Number, Phone Number, Zipcode, etc.) and I don’t like to repeat those regular expressions or validations all over the place.

What does this plugin do?

With the Grails Constraints plugin, you can write a custom Constraint class, drop it in /grails-app/utils/ and it will automatically be available to all of your domain classes.

Example

I create a new constrain by hand in /grails-app/utils/ComparisonConstraint.groovy. (You can also use the provided create-constraint script like grails create-constraint com.foo.MyConstraint)

class ComparisonConstraint {

static name = "compareTo"
static expectsParams = true

def validate = { val, target ->
def compareVal = target."$params"
if (null == val || null == compareVal)
return false

return val.compareTo(compareVal) == 0
}
}

Then you can apply your constraint to your Domain class:

class Login {
String password
String confirm

static constraints = {
password(compareTo: 'confirm')
}
}

See Grails Custom Constraints Plugin for the full documentation on what all of the above means and the source code.

6 thoughts on “Announcing Grails Constraints Custom Domain Constraint Plugin”

  1. I love this idea, but unfortunately, it behaves very erritically for me. Sometimes the validate closure gets called, sometimes it doesn’t, and there doesn’t seem to be any predictability in whether it gets called or not. Sometimes I’ve got it working, then kill the server, clean, restart, and then it fails (as in: the validate closure doesn’t get called).

    And it fails silently. It doesn’t complain that it can’t find the constrain class or anything like that, it just ignores it completely.

    It’s a real shame, because this plugin promises to do exactly what I need: make lots of custom validators easy to maintain and re-use.

    Is there any way I can help you fix this?

  2. @mcv, the most help would be to make a repeatable test case. If that’s not possible, do you mind sending me some of your Constraints so I can take a look at them?

  3. @fabien7474,
    Yes, I think it’s still relevant with Grails 1.2. Grails 1.2 allows you to create named constraints based on the existing constraints and then apply them to multiple classes. e.g.:

    grails.gorm.default.constraints = {
    myConstraints(nullable:true, blank:false, size:1..20)
    }

    static constraints = {
    myProperty shared:"myConstraints"
    }

    The constraints plugin allows you to create fundamentally new constraints. It also allows you to supply parameters to those custom constraints to change the behavior, something that the default constraints setup doesn’t do. This is important, for example, in a constraint that relies on the value of another property (see the CompareToConstraint example above). In that scenario you need to configure the constraint by passing the name of that other property.

    The new feature in Grails 1.2 is really about applying defaults and a way of clustering common constraints together. That’s great for what it is. The plugin is about creating fundamentally new constraints.

  4. I’m having the same problems as mvc; was his issue ever resolved? I’ve followed the directions, and moving from a validator closure (that works) to a named custom constraint using the plugin is causing me trouble – the custom validation is never called, no errors to the console, no errors to the browser, none of the debug printlns I stuck in the validate closure appear on the console.

    Here’s a fake-up of what I’m trying to do:


    class MyDomain {
    Double oneSmallVal
    Double anotherSmallVal

    static constraints = {
    anotherSmallVal(smallEnough:true)
    }
    }

    class SmallEnoughConstraint {

    def validator = { val, obj ->
    if (obj.oneSmallVal && val) {
    return (val + obj.oneSmallVal < 1)
    } else {
    return false
    }
    }
    }

    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>