0

I have a bunch of Java classes that I would like to use as command classes in my Grails contollers. A typical example is:

class Person {
    String name
    Integer age

    public String getName() {return name;}
    public String getAge() {return age;}
    public void setName(String name) {this.name = name;}
    public void setAge(Integer age) {this.age = age;}
}

I would like to able to specify constraints for this class such that I can call validate() on it, and any validation errors will be stored in theerrors property. In other words, it will behave just like a regular Grails command class.

Obviously I can't declare the constraints closure directly in the .java source file, because Java doesn't support closures. Is there some way I can modify these classes (at runtime), to add Grails command behaviour?

Dónal
  • 185,044
  • 174
  • 569
  • 824

2 Answers2

2

I haven't tried this but you could use Groovy's meta-programming capabilities to achieve this. In your Bootstrap.groovy you could add the static contraints closure to all the Java classes that you want to validate. Also annotate your classes with @Validateable. Here's an example:

Person.metaClass.static.constraints = { name blank: false }

Afterwards treat these classes like Command classes to validate them.

Benjamin Muschko
  • 32,442
  • 9
  • 61
  • 82
  • In theory it seems like that should work, though I find with Groovy/Grails some things that should work in theory, don't in practice. I'll accept this answer after I've tested it out. – Dónal Apr 08 '11 at 08:12
  • One problem I can forsee with this is testing. Bootstrap.init doesn't get invoked before unit testing constraints, so any unit tests that test the constraints probably won't work – Dónal Apr 08 '11 at 08:13
  • Yeah, you'd probably have to put this initialization code into a separate class and call it from `Bootstrap.groovy` and your test code. You could call that code from a method in a test base class annotated with `@BeforeClass`. Another option would be to write an implementation of `BlockJUnit4ClassRunner`. You can then pick and choose to which unit test you want to apply your extensions using the `@RunWith` annotation. – Benjamin Muschko Apr 08 '11 at 13:34
  • @Don: Any luck with that approach? – Benjamin Muschko Apr 13 '11 at 18:51
0

In fact Groovy supports "attaching" constraints to Java domain classes, as described by Peter Ledbrook (SpringSource):

http://blog.springsource.com/2010/08/26/reuse-your-hibernatejpa-domain-model-with-grails/

As described in the blog post, you obviously can't define a constraints closure in the Java class. But you can attach constraint meta-data by creating a Groovy class following this naming convention:

[package.to.your.dc.MyDomainClass]Constraints.groovy

and place this in the src/java folder.

Take a look at the blog post mentioned above, it's a very good introduction to this topic.

Andre Steingress
  • 4,381
  • 28
  • 28