In this tutorial we will see how to perform JSR 349/303 annotation based validation in a Spring application.
Please check out our Java EE Bean Validation tutorials if not already familiar with it.
The Spring specific class LocalValidatorFactoryBean implements jakarta.validation.Validator (formerly javax.validation.Validator), jakarta.validation.ValidatorFactory (formerly javax.validation.ValidatorFactory) and org.springframework.validation.Validator interfaces. This class wraps standard JSR 349/303 bean validation bootstrapping process and also wraps the access around org.springframework.validation.Validator. LocalValidatorFactoryBean allows as to inject jakarta.validation.Validator . We can also inject org.springframework.validation.Validator instead of jakarta.validation.Validator and then in that case we will be using Spring validation API to perform validation.
Example
A bean using validation annotations
package com.logicbig.example;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
public class Order {
@NotNull(message = "{date.empty}")
@Future(message = "{date.future}")
private Date date;
@NotNull(message = "{price.empty}")
@DecimalMin(value = "0", inclusive = false, message = "{price.invalid}")
private BigDecimal price;
.............
}
Spring configuration
package com.logicbig.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import jakarta.validation.Validator;
@Configuration
public class Config {
@Bean
public ClientBean clientBean() {
return new ClientBean();
}
@Bean
public Validator validatorFactory() {
return new LocalValidatorFactoryBean();
}
}
Performing Validation
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import java.util.Comparator;
import java.util.Locale;
import java.util.Set;
public class ClientBean {
@Autowired
Validator validator;
public void processOrder(Order order) {
if (validateOrder(order)) {
System.out.println("processing " + order);
}
}
private boolean validateOrder(Order order) {
Locale.setDefault(Locale.US);
Set<ConstraintViolation<Order>> c = validator.validate(order);
if (c.size() > 0) {
System.err.println("Order validation errors:");
c.stream().sorted(Comparator.comparing(v->v.getPropertyPath().toString()))
.map(v -> v.getMessage()).forEach(System.err::println);
return false;
}
return true;
}
}
Main class
package com.logicbig.example;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Calendar;
public class ValidationJSR349Example {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
Order order = new Order();
//order.setPrice(BigDecimal.TEN);
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(2021,1,1, 0,0,0);
order.setDate(calendar.getTime());
ClientBean bean = context.getBean(ClientBean.class);
bean.processOrder(order);
}
}
OutputOrder validation errors: Date must be in future Price cannot be empty
Example ProjectDependencies and Technologies Used: - spring-context 6.2.12 (Spring Context)
Version Compatibility: 3.2.3.RELEASE - 6.2.12 Version compatibilities of spring-context with this example: Versions in green have been tested.
- hibernate-validator 8.0.1.Final (Hibernate's Jakarta Bean Validation reference implementation)
- expressly 5.0.0 (Jakarta Expression Language Implementation)
- JDK 25
- Maven 3.8.1
|