20

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.
  • 9,111
  • 3
  • 21
  • 41
Rahul
  • 493
  • 3
  • 7
  • 25
  • 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

4 Answers4

17

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.
  • 9,111
  • 3
  • 21
  • 41
9

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
  • 14,226
  • 4
  • 44
  • 89
5

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

A. Lefaux
  • 101
  • 8
3

Description

  1. In my case, I define 1 parent class A has 3 sub class B, C, D such as:

public A { private B bCommand; private C cCommand; private D dCommand; }

  1. I annotated @NotNull, @NotBlank for some fields in 3 sub class. In Controller, I have put @Valid for function like that:

@PostMapping() public ResponseEntity create(@RequestBody @Valid A
command){ }

Solution

  1. I put @Valid for sub class which has field(s) need to check constraint.
  2. Example: Class B, C have some fields which have constraint like not null

public A { @Valid private B bCommand; @Valid private C cCommand; private D dCommand; }

nguyen
  • 41
  • 4