How to Bind Custom Validation Message in Spring
Validation is an essential aspect of any application that handles user input. Spring Boot provides a validation framework that integrates seamlessly with Jakarta Bean Validation (JSR-380) and Hibernate Validator. While Spring Boot provides default error messages, customising them allows us to create user-friendly, context-specific feedback. In this article, we explore how to bind custom validation messages in Spring Boot and simplify validation feedback handling.
1. Setting Up Validation in Spring Boot
To enable validation in a Spring Boot project, we need to include the appropriate dependency in our Maven pom.xml file.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
This starter automatically brings in the Jakarta Bean Validation API (jakarta.validation) and Hibernate Validator, the default implementation used by Spring Boot.
2. Understanding Spring Boot’s Validation Mechanism
Spring Boot utilizes the jakarta.validation API (formerly javax.validation) together with a validator implementation, such as Hibernate Validator, for declarative validation. Common annotations such as @NotNull, @Size, @Min, and @Email can be applied directly to entity fields or DTOs. For example:
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
public class ProductDTO {
@NotBlank
@Size(min = 3, max = 50)
private String name;
@NotNull
@Min(value = 1)
private Double price;
// getters and setters
}
By default, validation errors generate generic messages like “must not be blank” or “size must be between 3 and 50.” While functional, these messages may not suit our application’s tone or context. Spring Boot allows us to bind custom messages either directly in annotations or through a centralized message source.
3. Configuring Custom Validation Messages
3.1 Using the message Attribute
The simplest approach is to define a custom message directly in the annotation:
@NotBlank(message = "Product name cannot be empty")
@Size(min = 3, max = 50, message = "Product name must be between 3 and 50 characters")
private String name;
@NotNull(message = "Product price cannot be null")
@Min(value = 1, message = "Product price must be at least 1")
private Double price;
Although this approach works for small projects, it spreads messages throughout the code, making them harder to maintain.
3.2 Externalizing Messages with ValidationMessages.properties
Spring Boot allows us to externalize validation messages in a ValidationMessages.properties file, promoting maintainability and localization. Create the file under src/main/resources:
product.name.notblank=Product name cannot be empty
product.name.size=Product name must be between {min} and {max} characters
product.price.notnull=Product price cannot be null
product.price.min=Product price must be at least {value}
We can then reference these keys in annotations:
@NotBlank(message = "{product.name.notblank}")
@Size(min = 3, max = 50, message = "{product.name.size}")
private String name;
@NotNull(message = "{product.price.notnull}")
@Min(value = 1, message = "{product.price.min}")
private Double price;
Spring Boot automatically loads ValidationMessages.properties if present. For custom locations or filenames, configure a MessageSource bean:
@Configuration
public class ValidationConfig {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("file:/path/to/file/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
Note: Remember to omit the .properties suffix when setting the base name. For example, if your file is named messages.properties, configure it as follows:messageSource.setBasename("file:/path/to/file/messages").
4. Handling Validation Errors in Spring Controllers
When working with validation, simply adding constraints is not enough. We also need a clean way to capture and present validation errors. In Spring Boot, the most common approach is to use the @Valid annotation alongside BindingResult. This combination allows us to intercept validation errors directly within our controller methods and format them into meaningful, user-friendly responses.
@PostMapping
public String addProduct(@Valid @RequestBody ProductDTO productDTO, BindingResult result) {
if (result.hasErrors()) {
StringBuilder errors = new StringBuilder();
result.getFieldErrors().forEach(error
-> errors.append(error.getField())
.append(": ")
.append(error.getDefaultMessage())
.append("; ")
);
return errors.toString();
}
return "Product added successfully: " + productDTO.getName() + " ($" + productDTO.getPrice() + ")";
}
In this example, the BindingResult object captures all validation issues detected by the @Valid annotation. Each error is extracted, formatted, and returned as a descriptive message. This approach provides immediate feedback for invalid input while keeping our controller logic simple and easy to maintain. For larger applications, we can further refine this logic by moving validation error handling into a centralized @ControllerAdvice class.
5. Enabling Multi-Language Support for Validation Messages
In many applications, users come from different regions and speak different languages. To make validation messages accessible and user-friendly for everyone, Spring Boot makes it easy to configure localization support. Alongside our default ValidationMessages.properties file, create additional message files for each supported language. For example:
src/main/resources/messages.properties src/main/resources/ValidationMessages_fr.properties src/main/resources/ValidationMessages_es.properties
Spring Boot automatically detects the locale from the Accept-Language HTTP header and resolves the appropriate message file based on the user’s locale, which browser settings, request headers, or application configuration can determine.
6. Conclusion
In this article, we explored how to bind custom validation messages in Spring Boot, from adding validation dependencies and configuring message sources to handling validation errors effectively within controllers. We also looked at how to support multiple languages, allowing applications to deliver localized feedback based on the user’s locale.
7. Download the Source Code
This article discussed how to bind a custom validation message in Spring (Java).
You can download the full source code of this example here: Sign up




