How to Customize Default Error Message in Spring Boot Validation


In the spring boot, the @valid annotation is used to validate the spring boot bean. When the validation fails, the default error message will be returned to the client. The default error message is a generic error message that does not make sense in certain api calls. The message must be tailored for a particular api request.

In another situation, the validation error is not an error. The error is required to be ignored and continue as normal. For example, the id value is mandatory in the database update, whereas the id value is not available in the database insert. The same bean object is used in both cases. In this case, if you validate in the rest controller class, you have to create two beans.

In this post, we’ll see how to customize the default error message for an api call. Customization is done using the rest controller method. Here, we’ll see how to ignore a @valid error message, how to convert a default @valid error message to a custom error message, how to convert a default @valid error message to a response message.



Pom.xml file and dependency

The pom.xml file contains all the configurations of the dependency. This dependency includes all the jar files required for validation.

The “spring-boot-starter-validation” dependency will include all the jars needed for the validation of the request body. The web application needs the dependence of “spring-boot-starter-browser.” This will allow the tomcat server and start as a web application. The default “spring-boot-starter-test” test dependency will be applied to pom.xml for the unit testing.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.5.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.yawintutor</groupId>
	<artifactId>Spring-Application</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringBootValidation</name>
	<description>Spring Boot Project</description>

	<properties>
		<java.version>1.8</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>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>


Spring Boot Bean class to validate

The spring boot bean class is required to store the value obtained from the client or browser in json format. A spring boot bean class contains private variables and getter and setter method. The bean class has annotation for validating the data. In this example the annotation @Min is used to validate a student age.

Student.java

package com.yawintutor;

import javax.validation.constraints.Min;

public class Student {

	@Min(5)
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}


How to Ignore the Default Error Message in @Valid validation

In the Student Class, the minimum age is 5. The @Min annotation is used to validate the minimum check. If this validation has to be ignored, you may need to duplicate the bean class without this annotation. Instead, the code below will help to ignore the specific controller method.

TestController.java

package com.yawintutor;

import javax.validation.Valid;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	
	@PostMapping("/student/")
	ResponseEntity<String> student(@Valid @RequestBody Student student, Errors errors) {
		if (errors.hasErrors()) {
			System.out.println("Errors count : " + errors.getErrorCount());
			for (ObjectError objectError : errors.getAllErrors()) {
				System.out.println("errors : " + objectError.getDefaultMessage());
			}

			if(errors.hasFieldErrors("age")) {
				; // Ignore the min validation in age field.
			} else {
				return ResponseEntity.badRequest().body(errors.getAllErrors().toString());
			}
		}

		return ResponseEntity.ok("Your age is " + student.getAge());
	}
}
curl -X POST \
  http://localhost:8080/student/ \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: a3a5d66e-2b98-4b7d-8400-9be137b01504' \
  -d '{"age":"3"}'

Output

Your age is 3


How to Customize the Default Error Message in @Valid validation

The default error message in the @Min annotation is tailored to the age of the student class. The custom error message is shown as below

TestController.java

package com.yawintutor;

import javax.validation.ConstraintViolationException;
import javax.validation.Valid;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	
	@PostMapping("/student/")
	ResponseEntity<String> student(@Valid @RequestBody Student student, Errors errors) {
		if (errors.hasErrors()) {
			System.out.println("Errors count : " + errors.getErrorCount());
			for (ObjectError objectError : errors.getAllErrors()) {
				System.out.println("errors : " + objectError.getDefaultMessage());
			}

			if(errors.hasFieldErrors("age")) {
				throw new ConstraintViolationException("Your age is " + student.getAge()+" which is less than 5",null);
			} else {
				return ResponseEntity.badRequest().body(errors.getAllErrors().toString());
			}
		}

		return ResponseEntity.ok("Your age is " + student.getAge());
	}
	
}

Curl command

curl -X POST \
  http://localhost:8080/student/ \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: a3a5d66e-2b98-4b7d-8400-9be137b01504' \
  -d '{"age":"3"}'

Output

{
    "timestamp": "2020-03-29T07:55:26.370+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Your age is 3 which is less than 5",
    "path": "/student/"
}


How to Convert Default Error Message to Response Message in @Valid validation

The code below shows how to convert a default error message to a response message in @valid validation. The error message is converted to a valid client response message.

TestController.java

package com.yawintutor;

import javax.validation.ConstraintViolationException;
import javax.validation.Valid;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	
	@PostMapping("/student/")
	ResponseEntity<String> student(@Valid @RequestBody Student student, Errors errors) {
		if (errors.hasErrors()) {
			System.out.println("Errors count : " + errors.getErrorCount());
			for (ObjectError objectError : errors.getAllErrors()) {
				System.out.println("errors : " + objectError.getDefaultMessage());
			}

			if(errors.hasFieldErrors("age")) {
				return ResponseEntity.ok("Your age is " + student.getAge()+" which is less than 5");
			} else {
				return ResponseEntity.badRequest().body(errors.getAllErrors().toString());
			}
		}

		return ResponseEntity.ok("Your age is " + student.getAge());
	}
	
}

Curl command

curl -X POST \
  http://localhost:8080/student/ \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: a3a5d66e-2b98-4b7d-8400-9be137b01504' \
  -d '{"age":"3"}'

Output

Your age is 3 which is less than 5



Related Articles

Leave a Reply

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