Matelutex
Matelutex

Reputation: 2210

Spring Boot - request body validation also for parameter TYPE

I wonder how to add validation for parameter type: I have endpoint:

    @PostMapping(consumes = "application/json", path = "/v2/tw")
    @ResponseStatus(HttpStatus.CREATED)
    public TwDto add(
            Authentication auth,
            @Validated(TwDto.New.class) @RequestBody TwDto twDto,
            BindingResult bindingResult) {

TwDto has inside

    @Valid
    @PositiveOrZero
    @Pattern(regexp = "[0-9]", message = "id must be a number")
    private Long storeId;

When I set storeId = "123someString" then I get alwasy 400 error without any message.

I want to send to the client eg. 404 eror code with some message - how to do that? I tried many optiosn and I get always 400 BAD REQUEST...

Or maybe I should do custom validation, eg go through some dto fields and in try catch check if storeId is number or not and then throw some error that will be catched in ExceptionHandler?

@Pattern(regexp = "[0-9]", message = "id must be a number") doesn't work, I dont see any message that should be returned with the error

Upvotes: 0

Views: 2270

Answers (1)

gere
gere

Reputation: 1730

If you want to maintain automatic validation you may need to change the type of storeId to String:

@Valid
@Pattern(regexp = "[0-9]*", message = "id must be a number")
private String storeId; 

and then validation will work:

public class TwDtoTest {
    @Test
    void invalid_store_test() {
        TwDto twDto = new TwDto();
        twDto.setStoreId("aaaa");
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<TwDto>> violations = validator.validate(twDto);

        assertThat(violations.size()).isEqualTo(1);
        violations.forEach(violation -> assertThat(
            violation.getMessage()).isEqualTo("id must be a number")
        );
    }

    @Test
    void valid_store_test() {
        TwDto twDto = new TwDto();
        twDto.setStoreId("10");
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<TwDto>> violations = validator.validate(twDto);

        assertThat(violations.size()).isEqualTo(0);
    }
}

Of course, down the line, if you need to save or use the storeId as a Long you would need to convert it: Long.parseLong(storeId)

Upvotes: 1

Related Questions