12

Below is my DTO class.

public class AbstractDTO extends BaseDTO {

    private Integer createdBy;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DATE_FORMAT)
    @NotNull(message = "createdDate may not be null")
    private LocalDateTime createdDate;

    private Integer lastModifiedBy;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DATE_FORMAT)
    private LocalDateTime lastModifiedDate;

    private Boolean isActive;

    // getter & setters
}

Here I am trying to annotate createdDate field as @NotNull but is it not working. It is allowing in request body and after executing the service in postman not getting any error.

I have tried below options but no luck.

1) Tried to add maven dependency.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2) Tried to annotate DTO class as @Validated

3) Tried to annotate createdDate field @Valid with @NotNull but still not luck.

Please help me out with this issue.

Anish B.
  • 7,985
  • 3
  • 16
  • 39
Rahul
  • 343
  • 2
  • 5
  • 18
  • Did you try to annotate the DTO class as @Validated in the controller method signature ? something like `void foo(@Validated MyDTO dto)` – Arnaud Denoyelle Oct 01 '19 at 10:10
  • @ArnaudDenoyelle This DTO has been used in multiple location more than 25 files, Do I have to make changes in every file? Is there any other solution? – Rahul Oct 01 '19 at 10:18
  • Does you app has starter - spring-boot-starter-web which will load hibernate Validator to dependency. Which will validate the bean. Please go through this link - https://stackoverflow.com/questions/48200444/spring-validation-vs-hibernate-validation?rq=1 – Sujay Mohan Oct 01 '19 at 11:45
  • Check my answer, it should resolve your issue. But if `@NotNull` does not work while `@JsonPattern` works, then it might be the case with the wrong `@NotNull` being used. Otherwise it seems you forgot adding `@Valid` on your controller method. – buræquete Oct 18 '19 at 07:34

3 Answers3

13

Your DTO class is correct. You have to use @Valid annotation.

For example :

@Controller
public class Controller {

    @PostMapping("/")
    public String checkPersonInfo(@Valid AbstractDTO abstractDTO, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            return "some-page";
        }
        return "some-other-page";
    }
}

Refer to this Spring Boot Example On Validating Form Input for reference.

Why to use @Valid annotation ?

This allows you to validate the set of constraints applied on the data members of a class.


However, if you have XML based configuration in your project, then you have to add this below in the applicationContext.xml given below. (Source : here)

<bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean
            class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
        </bean>
    </property>
</bean> 

    <bean id="validator"
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    </bean>
Anish B.
  • 7,985
  • 3
  • 16
  • 39
7

You have an endpoint with some request body like;

@RestController
public class TheController {

    @PostMapping(path = "/doSomething", consumes = "application/json", produces = "application/json")
    public void post(@Valid @RequestBody AbstractDTO request) {
        //code
    }
}

You need to have @Valid annotation for the request object. Only with this you'd have validation enabled for AbstractDTO for /doSomething endpoint.

Check here, for more in depth details

buræquete
  • 13,529
  • 4
  • 40
  • 81
3

Have you got the right import ?
I use import javax.validation.constraints.NotNull;

A. Lefaux
  • 81
  • 8