Enterprise Java

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).

Download
You can download the full source code of this example here: Sign up

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button