How to override attributes in validation annotation in Hibernate?

I have a custom annotation like:

@Documented
@Constraint(validatedBy = MyValidator.class)
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String message() default "message";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

      

And a validator to check the material:

public class MyValidator implements ConstraintValidator<MyAnnotation, String> {

    @Override
    public void initialize(MyAnnotation myAnnotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        ConstraintValidatorContextImpl con = (ConstraintValidatorContextImpl)context;

        String diff = getDiff(value, cleanForHTMLContext(value));
        if(diff.isEmpty()){
            return true;
        }
        return false;
    }

    private cleanForHTMLContext(String value) {
       // Some stuff to clean up value
    }

    private String getDiff(String value, String cleanedValue) {
       // Some stuff to compare values
    }
}

      

My goal is to add "diff" to the annotation attributes and then be able to resolve the message using the key and attributes from the ResourceBundle.

As an example, when the usage type is invalid, it should see the following message:

The data is invalid because it contains this text: {diff}. ... Where diff will be the result of a runtime comparison between two lines that will be evaluated in the isValid () method .

I tried to override the value from the map arguments like this:

ConstraintValidatorContextImpl con = (ConstraintValidatorContextImpl)context;
con.getConstraintDescriptor().getAttributes().put("diff", value);

      

But unfortunately I got an exception regarding the unmodifiable map created in ConstraintDescriptorImpl

Is there another option to add custom attributes that will be resolved with an error code?

+3


source to share


1 answer


Just tried it yourself, the solution below works if you are using Hibernate Validator. Note that your message must include ${}

to denote variable parts, not {}

.

private MyAnnotation annotation;

@Override
public void initialize(MyAnnotation a)
{
    this.annotation = a;
}

@Override
public boolean isValid(String value, ConstraintValidatorContext ctx)
{
    String diff = getDiff(value, cleanForHTMLContext(value));
    if (diff.isEmpty())
        return true;

    String message = annotation.message();
    HibernateConstraintValidatorContext hctx = ctx.unwrap(HibernateConstraintValidatorContext.class);

    ctx.disableDefaultConstraintViolation();
    ctx.addExpressionVariable("diff", diff)
       .buildConstraintViolationWithTemplate(message)
       .addConstraintViolation();
    return false;
}

      



Please note that your post should contain ${diff}

as a template, not {diff}

.

...
public @interface MyAnnotation {
    String message() default "Data invalid, because contain this text: ${diff}.";
...

      

+4


source







All Articles