Sumit Monapara
Sumit Monapara

Reputation: 840

@Valid Not working @PostMapping spring boot

I am learning spring boot, I am adding Validation for @PostMapping, but somehow it always create a object even with non-valid value.

Hospital.java

public class Hospital {
    private Integer id;
    @Size(min = 2)
    private String name;
    @Size(min = 2)
    private String city;

    public Hospital(Integer id, String name, String city) {
        this.id = id;
        this.name = name;
        this.city = city;
    }

Controller

@Autowired
    HospitalData data;
...
@PostMapping("/hospital")
    public ResponseEntity<Hospital> addHospital(@Valid @RequestBody Hospital hospital){
        Hospital newHospital = data.addHospital(hospital);

        URI location = ServletUriComponentsBuilder
        .fromCurrentRequest()
        .path("/{id}")
        .buildAndExpand(newHospital.getId()).toUri();

        return ResponseEntity.created(location).build();
    }

pom.xml

<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>

And previously I have added below dependency as I am using Spring 2.3.10 RELEASE, but it doesn't work, so I have added above dependency.

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

Upvotes: 0

Views: 2098

Answers (2)

Clijsters
Clijsters

Reputation: 4256

I created a Test Application reproducing the state of your code. As stated under the comments, the code you provided should definitely work. You definitely don't neet to provide a BindingResult to the method. Spring Boot throws a MethodArgumentNotValidException and therefore returns a bad request http status if the validation fails.

I created a project with following content:

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.5</version>
</parent>
<properties>
    <java.version>11</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

DemoEntity:

public class DemoEntity {
    @NotNull
    public String name;
    @Size(min = 3)
    public String greeting;
}

DemoController:

@Controller
public class DemoController {
    @PostMapping("/post")
    public ResponseEntity<DemoEntity> put(@Valid @RequestBody DemoEntity demoEntity) {
        return ResponseEntity.ok(demoEntity);
    }
}

Now, that's what happens with my requests:

Name Greeting Result
Peter Mr 400
Stephen Monsieur 200
Clara null 200
Jenny Madamme 200

As you see from the table above, when greeting is null the result is an ok status. If you want to guarantee that the string is at least min characters long and not null, you need to declare this explicitely.

That's, for example, if you want to validate optional fields like a mobile number. You know, it should be n numbers long and contain only numbers, but you don't want to make it mandatory. Like I showed with the greeting above.

Upvotes: 2

Deadron
Deadron

Reputation: 5289

You need to inject the BindingResult object as the param immediately following your form object and then manually check if there were any errors.

See https://spring.io/guides/gs/validating-form-input/ Create a Web Controller for a good example of how this should be done in your controller.

Upvotes: 0

Related Questions