Custom annotation isn't validating method parameter

Mestru :

I created a custom annotation

@Documented
@Constraint(validatedBy = CheckGranularityValidator.class)
@Target( { ElementType.PARAMETER} )
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckGranularity {
    String message() default "Duration has to be a multiple of granularity";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

With a validator like so

public class CheckGranularityValidator implements ConstraintValidator<CheckGranularity, AssetCostsRequest> {

    @Override
    public void initialize(final CheckGranularity constraintAnnotation) {

    }

    @Override
    public boolean isValid(final AssetCostsRequest value, final ConstraintValidatorContext context) {
        return value.getRange().getDuration() % value.getGranularity() == 0;
    }
}

I tried using it in my RestController

@RestController
public class CalcApiController extends CalcApi {

@Override
public ResponseEntity<String> calcProfitability(@Valid @CheckGranularity @RequestBody final AssetCostsRequest assetCostsRequest) {
    return ResponseEntity.ok("Works");
}

I tried using this annotation by writing a test:

@Test
public void calcTest() {
    final AssetCostsRequest request = new AssetCostsRequest()
        .setRange(new TimeRange(100L, 200L))
        .setGranularity(26L);

    given()
        .contentType(ContentType.JSON)
        .body(request)
    .when()
        .post("/calc")
    .then()
        .statusCode(HttpStatus.SC_BAD_REQUEST);
}

Relevant part of AssetCostsRequest:

public class AssetCostsRequest {

    @JsonProperty
    @NotNull
    private TimeRange range;

    @JsonProperty
    @NotNull
    private Long granularity = 30L;

    ...getters & setters
}

Test method returns with 200. When I try to set a breakpoint in isValid method, it isn't hit when I run the test. I tried changing order of annotations, getting rid of @Valid, changing @Target in CheckGranularity class, nothing helped. I'm using RestAssured for testing.

How do I make it, so my annotation is properly validating a parameter?

Bartosz M. :

Change CheckGranularity's target to ElementType.TYPE and add @CheckGranularity directly on AssetCostsRequest. Also remove @CheckGranularity from endpoint definition.

How it works. By adding @Valid on endpoint's parameter you tell spring to validate it. Adding validation like @CheckGranularity won't work on the same level as Valid. It has to be added somewhere inside parameters class.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=154453&siteId=1