10

I have a hard time believing I'm the only one who wants to do this, but I can't find any references to help me over my hurdle. Using Spring MVC and annotation-based validation (I'm using framework 4.0 and Java 1.7), consider a simple class hierarchy, as follows:

abstract class Foo {

    @Size(max=10, message = "The name has to be 10 characters or less.")
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Bar extends Foo {

}

class Bang extends Foo {

}

If I put a name in an instance of either Bar or Bang that's greater than 10 characters, I get the validation error I'm expecting. Let's suppose, though, that I still want Bar and Bang to be derived from the abstract base class Foo, but that I want the name attribute of the child classes to have different validations.

How do I annotate Bar and Bang so that Bar.name has a max length of, say, 12 characters while Bang.name has a max length of 8 characters?

Thanks much, Rob

RobAllen
  • 103
  • 1
  • 1
  • 4
  • [a similar one](http://stackoverflow.com/questions/9067420/can-i-override-a-jsr-303-validation-annotation) – gadget Feb 17 '14 at 23:27
  • I saw that. I tried the "cumulative" thing on the overridden getter method with NO validation on the base class. What happens is that the validation doesn't happen at all. I've tried peppering @Valid around in various places and I still can't get the validator to fire on the overridden getter. Do I have to set a '@Size' validator on the base class and then constrain it further on the extended class? Like max=1000 on the base class and then max=12 on the extension to take advantage of the "cumulative" nature of validation by annotation? – RobAllen Feb 17 '14 at 23:46
  • the point is that because of this cumulative nature overriding is not possible with JSR303 annotations. – gadget Feb 17 '14 at 23:54
  • I guess I have to accept that answer even if I don't like it. :-/ Thanks, @gadget. – RobAllen Feb 18 '14 at 00:09

3 Answers3

4

The short answer is that it is not possible in Bean Validation to disable constraints in super classes. There is a feature request here https://hibernate.atlassian.net/browse/BVAL-256 suggesting the introduction of annotations of the type @OverrideConstraint or @IgnoreInheritedConstraint. As of now, it is not possible to do this though.

See also http://lists.jboss.org/pipermail/beanvalidation-dev/2012-January/000128.html and https://hibernate.atlassian.net/browse/HV-548.

Hardy
  • 18,659
  • 3
  • 49
  • 65
1

Create a new field in the derived classes and override the methods.

class Bar extends Foo {
    @Size(max=12, message = "The name has to be 12 characters or less.")
    private String name;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }
}
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • 1
    Thanks, but doesn't that kind of defeat the purpose of having the abstract base class? – RobAllen Feb 17 '14 at 23:43
  • If your only using the abstract class to hold the `name` field, yes it does. If the abstract class contains other common fields, methods, etc it could be worth it. – Kevin Bowersox Feb 17 '14 at 23:44
  • I see your point. Stepping away from my over-simplified "Foo Bar Bang" example, it's basically an abstract Person class that holds all the common attributes that more specific kinds of people can extend. – RobAllen Feb 18 '14 at 00:01
1

you can put @Size(max=12, message = "The name has to be 12 characters or less.") annotation on getter method as well.

So just override the name field and put your personalized annotation on getter method. It will work same as putting the validation annotation on field. see example below:

class Bar extends Foo 
{
    @Override 
    @Size(max=12, message = "The name has to be 12 characters or less.")
    public void getName(String name)
        {
            this.name = name;
        }
}
Vikas Kumar
  • 159
  • 1
  • 12
  • This solution seems incorrect! First of all, Bar does not have name field since it is private in the super class. Second of all, a Getter method is not a Setter method!! – madz Mar 30 '19 at 17:13
  • It's setter, not getter, getter serializes, setter works during deserialization when validation works. – improbable Jun 20 '20 at 20:12