1

I'm using javax.validation.constraints and have already checked the package usage but still can't find what I'd like to do. https://javaee.github.io/javaee-spec/javadocs/javax/validation/constraints/package-summary.html

Here are the two of the variables being sent from the request body

  @NotNull
  @PositiveOrZero
  @Digits(integer = 9, fraction = 0)
  private BigDecimal valueA;

  @NotNull
  @PositiveOrZero
  @Digits(integer = 9, fraction = 0)
  private BigDecimal valueB;

is it possible to restrict valueB to be not more than 50% of valueA by annotation only? (valueB <= valueA/2)

3 Answers 3

2

there are 2 approach to do that:

  1. you can insert @AssertTrue method to validate it
    @AssertTrue
    public boolean isFiftyPercent(){
        //your logic to compare value a and value b
    }
  1. or you can make your own annotation validation for global setting. see here: https://www.baeldung.com/spring-mvc-custom-validator
Sign up to request clarification or add additional context in comments.

Comments

2

what you are looking for is using Cross-Parameter Constraints. some basic guide can be found here chapter 2.x https://www.baeldung.com/javax-validation-method-constraints

1 Comment

small tip: when you put a link, you also add a small description of the content or some small example, so that, in the event, at some point, the link no longer works, the reader still has some element to think about.
1

You need to have a class level annotation for this. Field level annotations only access value of the fields.

Here is an example:

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

// Custom annotation
@Target({ TYPE })
@Retention(RUNTIME)
@Repeatable(NotGreaterThans.class)
@Documented
@Constraint(validatedBy = { NotGreaterThanValidator.class }) // Explicitly define validator
public @interface NotGreaterThan {
    
    String source();

    String target();
    
    double percentage()
    
    String message() default "Default message ..";

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

    @Target({ TYPE })
    @Retention(RUNTIME)
    @Documented
    @interface NotGreaterThans {
        
        NotGreaterThan[] value();
    }
}


import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;


// Validator accesses both annotation and object value
public class NotGreaterThanValidator implements ConstraintValidator<NotGreaterThan, Object> {
    
    private String source;
    private String target;
    private double percentage;
    
    @Override
    public void initialize(NotGreaterThan notGreaterThan) {
        this.source = notGreaterThan.source();
        this.target = notGreaterThan.target();
        this.percentage = notGreaterThan.percentage();
    }
    
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        
        BigDecimal sourceValue = customMethodToGetFieldValue(source, value);
        BigDecimal targetValue = customMethodToGetFieldValue(target, value);

        return source.compareTo(target.multiply(percentage)) <= 0;
    }

    private BigDecimal customMethodToGetFieldValue(String fieldName, Object object) {
        return ....
    }
}

// Define your annotation on type
@NotGreaterThan(source ="a", target="b", percentage =50.0)
public class MyCustomBodyClass {
    private BigDecimal a;
    private BigDecimal b;
}

I haven't tested this, but should give you a head start.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.