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.1.2 (Spring Context)
Version Compatibility: 3.2.3.RELEASE - 6.1.2 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 17
- Maven 3.8.1
|