Home > other >  Spring boot @Valid does not work properly
Spring boot @Valid does not work properly

Time:09-17

I'm facing a problem with Spring boot validation. Currently, I'm using Oracle JDK 11.0.12 and Spring boot 2.5.4 to build my project. I added constraints to validate the fields but it does not work. My code here:

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

@Data
public class LoginFormDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    @NotBlank(message = "Login must not be blank")
    private String login;

    @NotNull(message = "Password must be provided")
    private String password;

    private boolean rememberMe = false;
}
@RestController
@RequestMapping("/api")
public class AccountResource {

    // Logger and autowired components

    @PostMapping("/authenticate")
    @ResponseBody
    public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginFormDTO account) {
        // Some code lines
        return ResponseEntity.ok().body(new JWTToken(jwt));
    }
}

Dependencies in pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <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>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web-services</artifactId>
    </dependency>
    <dependency>
        <groupId>org.liquibase</groupId>
        <artifactId>liquibase-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.googlecode.libphonenumber</groupId>
        <artifactId>libphonenumber</artifactId>
        <version>8.12.31</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-boot-starter</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-bean-validators</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

I expect when I send POST request with body

{
  "login": null, // or empty string "", or blank string "    "
  "password": "string",
  "rememberMe": true
}

then the server should validate fields then throw exceptions or errors (because of null constraint violation) before executing code in my authorize(@Valid @RequestBody LoginFormDTO account) function, but it does not. So what's wrong with spring validation or am I missing something?

CodePudding user response:

You can simplify your Controller. You have way too many annotations doing the same thing and even some weird stuff (you return ResponseEntity but then you tell Spring that the return of the method should be the Response Body).

This may not fix the @Valid issue but for sure will make it simpler:

@RestController
@RequestMapping("/api")
public class AccountResource {

    // Logger and autowired components

    @PostMapping("/authenticate")
    @ResponseStatus(HttpStatus.OK)
    public JWTToken authorize(@Valid @RequestBody LoginFormDTO account) {
        // Some code lines
        return new JWTToken(jwt);
    }
}

@RestController is itself annotated with @Controller and @ResponseBody, which means that @RequestMapping methods assume @ResponseBody semantics by default, so you don't need to explicitly add it.

CodePudding user response:

I found out that my SwaggerConfig class should use BeanValidatorPluginsConfiguration.class instead of SpringValidatorAdapter.class in @Import({}). Now my validator works normally. Thank João Dias for supporting me in figuring it out.

  • Related