Search code examples
javaspringspring-bootapplication.propertiesjavax.validation

How to use application.properties values in javax.validation annotations


I have a variable called notification.max-time-to-live in application.yaml file and want to use this as the value of javax.validation.constraints.@Max() annotation.

I've tried in many ways (using env.getProperty(), @Value, etc) and it says it must be a constant value, is there any way to do this?


Solution

  • I know this does not directly answer my question and as M. Deinum already said the answer is no. Nonetheless it's a simple workaround.

    It's true that @Max and other javax annotations do not let us use dynamic values, however, we can create a custom annotation (as M. Deinum suggested) that uses values from application.yaml with spring @Value.

    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = ValidTimeToLiveValidator.class)
    public @interface ValidTimeToLive {
    
        String message() default "must be less than or equal to %s";
    
        Class<?>[] groups() default { };
    
        Class<? extends Payload>[] payload() default { };
    }
    

    And the respective validator.

    public class ValidTimeToLiveValidator implements ConstraintValidator<ValidTimeToLive, Integer> {
    
        @Value("${notification.max-time-to-live}")
        private int maxTimeToLive;
    
        @Override
        public boolean isValid(Integer value, ConstraintValidatorContext context) {
            // leave null-checking to @NotNull
            if (value == null) {
                return true;
            }
            formatMessage(context);
            return value <= maxTimeToLive;
        }
    
        private void formatMessage(ConstraintValidatorContext context) {
            String msg = context.getDefaultConstraintMessageTemplate();
            String formattedMsg = String.format(msg, this.maxTimeToLive);
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(formattedMsg)
                   .addConstraintViolation();
        }
    }
    

    Now we just need to add this custom annotation in the respective class.

    public class Notification {
    
        private String id;
     
        @ValidTimeToLive
        private Integer timeToLive;
    
        // ...
    }