0

I have a trait and the following domain classes:

trait Named {

  String name

  static constraints = {
    name blank:false, unique:true
  }
}

@Entity
class Person implements Named {

  String fullName

  static constraints = {
    fullName nullable:true
  }

}

@Entity
class Category implements Named {

}

In this setup the Named.constraints are working fine for Category, but are ignored for Person.

How can I include the constrains from a trait in a constraints block of an implementing domain class?

injecteer
  • 20,038
  • 4
  • 45
  • 89

2 Answers2

1

How can I include the constrains from a trait in a constraints block of an implementing domain class?

The framework doesn't support it.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • does constraints inheritance work for proper class inheritance (w/o traits)? – injecteer Aug 20 '19 at 14:14
  • @injecteer Not implicitly, but see https://stackoverflow.com/a/24978696/3181392 - wonder if that works with a trait too – cfrick Aug 20 '19 at 15:30
  • @cfrick FYI... There are aspects of the solutions mentioned in that post you linked to which will not work. For example, `bindable` is going to be problematic in some of those scenarios. – Jeff Scott Brown Aug 20 '19 at 15:51
  • @cfrick what do you think about my answer? – injecteer Aug 21 '19 at 09:19
  • @injecteer I know you are asking cfrick and not me but be aware that the compilation time handling of constraints are going to be problematic for that approach. Some things will work. Not all will. – Jeff Scott Brown Aug 21 '19 at 14:33
  • @JeffScottBrown I was asking you as well. SO does not allow to mention more than 1 poster in a comment – injecteer Aug 21 '19 at 14:34
  • @JeffScottBrown The approach I shown is not the ideal, although if used with caution lets the validation be re-used accross a large code base – injecteer Aug 21 '19 at 14:37
  • One point to be aware of is that approach is a potential security vulnerability because of the `bindable` handling. I would not advocate folks do that unless they have an understanding of the implications, and are sure no one is going to come along later and copy that pattern into a context that creates a security problem. – Jeff Scott Brown Aug 21 '19 at 14:39
-1

I found the least painful way to re-use the constraints.

I added a new class:

class CommonConstraints {

  static name = {
    name blank:false, unique:true
  }
}

Then instead of importFrom Named which didn't work, I sprinkle some groovy magic:

@Entity
class Person implements Named {

  String imgUrl

  String fullName

  static constraints = {
    CommonConstraints.name.delegate = delegate
    CommonConstraints.name()
    fullName blank:false, unique:true
    imgUrl url:true
  }

}

And it works like charm.

Yes, the solution not consistent with inheritance/implementation model, but gets the job of code reuse done.

For the less tricky cases, where the domain class does not have it's own constraints, the ones from a trait will be used, like in my original question.

injecteer
  • 20,038
  • 4
  • 45
  • 89