views:

1283

answers:

2

If have a Java class with some fields I want to validate using Hibernate Validator. Now I want my users to be able to configure at runtime which validations take place.

For example:

public class MyPojo {
    ...

    @NotEmpty
    String void getMyField() {
        ... 
    }

    ...
}

Let's say I want to remove the NotEmpty check or replace it with Email or CreditCardNumber, how can I do it? Is it even possible? I guess it comes down to changing annotations at runtime...

A: 

I don't think you'll be able to remove or change the annotation, it's part of the class definition. You can build a new class, which is possible at runtime but a little involved. Hibernate may support programmatic access to the validations and allow you to override the annotation, I don't know the API that well. Hibernate does a bit of runtime class building itself... that might be a good place to learn how to do it if you're interested.

CurtainDog
Overriding the annotation _wont_ work. One way to customize hibernate validator is to write your own annotations, but that won't work for what DR is trying to do either, b/c you don't have access to dynamic values at runtime, except for the field the annotation is attached to. Any inputs into the annotation to configure it must be constants. For something that will work, check out my answer below.
Justin Standard
+2  A: 

You can't do it normally.

Here's what I've done to get more dynamic validations working via Hibernate Validator.

  1. Extend the ClassValidator class.
  2. Override the getInvalidVaues(Object myObj) method. First, call super.getInvalidValues(myObj), then add the hook to your customized validation.
  3. Instantiate your custom validator and call getInvalidValues to validate. Any hibernate annotated validations will kick off at this point, and your custom dynamic validations (anything not supported by annotations) will kick off as well.

Example:

public class MyObjectValidator extends ClassValidator<MyObject>
{
    public MyObjectValidator()
    {
         super(MyObject.class);
    }

    public InvalidValue[] getInvalidValues(MyObject myObj)
    {
        List<InvalidValue> invalids = new ArrayList<InvalidValue>();
        invalids.addAll(Arrays.asList(super.getInvalidValues(myObj)));

        // add custom validations here
        invalids.addAll(validateDynamicStuff(myObj));

        InvalidValue[] results = new InvalidValue[invalids.size()];
        return invalids.toArray(results);
    }

    private List<InvalidValue> validateDynamicStuff(MyObject myObj)
    {
        // ... whatever validations you want ...
    }

}

So your custom validation code can contain logic like "Do this validation, if the user configured it, otherwise do that one", etc. You may or may not be able to leverage the same code that powers the hibernate validations, but either way, what you are doing is more involved that the 'normal' use case for hibernate validator.

Justin Standard