Search code examples
javadtobean-validation

Javax validation for List<String> throws exception


I am trying to include a @Pattern validation for string elements inside a list using javax validation. Below is the simplified example:

public class ProgramRQDTO implements Serializable {

    private static final long serialVersionUID = -1L;

    @Size(min = 2, max= 5)
    private String lang;

    private List<@Pattern(regexp="^[a-zA-Z_]+$") String> destinations;

    ...getters/setters

}

This DTO is used as the body of a POST request in which the @Valid annotation is used.

@POST
@Produces({ MediaType.APPLICATION_JSON })
public Response method(@Valid @RequestBody MyDTO requestDto) {

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<MyDTO>> violations = validator.validate(requestDto);

    ...

}

This method, validator.validate(requestDto), throws an exception.

javax.validation.ValidationException: HV000187: When using type annotation constraints on parameterized iterables or map @Valid must be used. Check com.example.MyDTO#destinations

Is it possible to validate a List inside a DTO without having to make a wrapper class for that list? Is there something I am doing wrong?

Any help is appreciated.

I have tried to include the @Valid annotation in the DTO at different points but I have not been able to get rid of this error.

UPDATE:

All of the following give the same result:

@Valid
private List<@Pattern(regexp="^[a-zA-Z_]+$") String> destinations;

private List<@Valid @Pattern(regexp="^[a-zA-Z_]+$") String> destinations;

@Valid
private List<@Valid@Pattern(regexp="^[a-zA-Z_]+$") String> destinations;


Solution

  • I would just follow the error message and add the @Valid annotation to the field destinations in your DTO. I guess it was necessary in older versions of Java validation. Prior to Jakarta Bean Validation 3.O

    Solution

    Try this:

    public class ProgramRQDTO implements Serializable {
    
        @Valid
        private List<@Pattern(regexp="^[a-zA-Z_]+$") String> destinations;
    
    }
    

    EDIT what I found on the net:

    @Getter(onMethod = @__(@Valid))
    @Setter(onParam = @__(@Valid))
    @Valid
    public class ProgramRQDTO implements Serializable {
    
        @Valid
        private List<@Pattern(regexp="^[a-zA-Z_]+$") String> destinations;
    
    }
    

    EDIT 2

    I have just tested it with the newest versions of Spring Boot Starters and it works without any issues. No need of additional annotations. Following dependencies did the trick:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>