x Java Java 8 JUnit JSON
  • XML
  • JDBC Spring Boot Microservices React Contact Us

    Spring Boot validate request body

    When we expose any endpoint using Spring Controllers, it is important to validate the input request body. It not only helps in avoiding unnecessary service/db hit from controller layer, but also prevents security attacks like SQL injection. We can easily validate request body using Java Bean validation annotations. These annotations are present in javax.validation.constraints.* package. You need to add spring-boot-starter-validation dependency in pom.xml file.

    Step 1) Add below dependencies in pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
            </dependency>
    </dependencies>   

    Step 2) Create User, UserController, UserExceptionHandler, UserApplication classes

    Note that for user name we are using @NotEmpty & @Size annotations while for phone number we are using @NotNull annotation to validate request body which contains the user information.

    import javax.validation.constraints.NotEmpty;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    
    public class User {
    
        @NotEmpty(message = "user name can't be empty")
        @Size(min=1, max=128)
        private String name;
    
        @NotNull(message = "phone number can't be null")
        private Long phoneNumber;
    
        public User() {
        }
    
        public User(String name, Long phoneNumber) {
            this.name = name;
            this.phoneNumber = phoneNumber;
        }
        
        // removed getter & setters
    }  

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    
    import javax.validation.Valid;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/users")
    public class UserController {
    
        private List<User> users = new ArrayList<>();
    
        public UserController() {
            users.add(new User("John", Long.valueOf(5417543010l)));
        }
    
        @GetMapping("/{id}")
        public Optional<User> getUser(@PathVariable("id") String id) {
            return users.stream().filter(user -> user.getName().equalsIgnoreCase(id)).findAny();
        }
    
        @PostMapping("/")
        public User addUser(@Valid @RequestBody User user) {
            users.add(user);
            return user;
        }
    
    } 

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class UserApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(UserApplication.class, args);
        }
    }  

    Step 3) Running UserApplication

    Run the UserApplication and post a request to create a new User either using curl utility or POSTMAN. You will see that UserApplication returns 400 response code since we didn't pass any phoneNumber and hence request body validation fails in the UserApplication.

    basic

    basic
















    Since we do not get any useful information about request failure, we need to write a custom ExceptionHandler as shown below to return meaningful error message back to caller.

    Step 4) Create UserExceptionHandler classes

    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.context.request.WebRequest;
    import org.springframework.web.servlet.mvc.method.annotation
    .ResponseEntityExceptionHandler;
    
    @ControllerAdvice
    public class UserExceptionHandler extends ResponseEntityExceptionHandler {
    
        @Override
        protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
    
            Map<String, Object> body = new HashMap<>();
            List<String> errorList = ex.getBindingResult()
                    .getFieldErrors()
                    .stream()
                    .map(x -> x.getDefaultMessage())
                    .collect(Collectors.toList());
    
            body.put("errors", errorList);
    
            return new ResponseEntity<>(body, headers, status);
        }
    
    } 

    Step 5) Running UserApplication

    Now if you post the request, you will see below error message in response.

    basic

    basic

















    basic

    basic

















    Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *











    Share This