Sometimes it is necessary to validate one property or multiple properties of a class at one time or in relation to each other, but you want to add a constraint violation to the specific property. The solution will described in this post
You have your model:
@ValidateFieldIfFlag
public class Model {
    @Id
    @GeneratedValue
    private int id;
    private boolean flag;
    private String field;
    ... // getter and setter following
}
As you see the class uses a custom validator ValidateFieldIfFlag to validate a Model instance.
So you have the annotation:
@Constraint(validatedBy = {ValidateFieldIfFlagValidator.class})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface ValidateFieldIfFlagValidator
{
	String message() default "my error message";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}
And your validator:
public class ValidateFieldIfFlagValidator implements ConstraintValidator<ValidateFieldIfFlagValidator, Model>
{
    public boolean isValid(Model model, ConstraintValidatorContext context) {
        if (!model.isFlag()) return true;
        //if flag is set, field should be nonEmpty      
        return model.getField() != null && !model.getField().isEmpty();
    }
}
The validator will validate the field to be non empty, if the flag is set. Unfortunately you will receive a ConstraintViolationException for the whole instance and not only for the field. To change this, you have to modify the validator:
public class ValidateFieldIfFlagValidator implements ConstraintValidator<ValidateFieldIfFlagValidator, Model>
{
    public boolean isValid(Model model, ConstraintValidatorContext context) {
        if (!model.isFlag()) return true;
        //if flag is set, field should be nonEmpty      
        if (model.getField() != null && !model.getField().isEmpty()) return true;
        ConstraintValidatorContext.ConstraintViolationBuilder constraintViolationBuilder = context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate());
        constraintViolationBuilder.addPropertyNode("field").addConstraintViolation();
        context.disableDefaultConstraintViolation();        
        return false;
    }
}
This suppress the default, class matched ConstraintViolationException, and creates a ConstraintViolationException matching the property “field”.
