Spring Framework Spring core Validator#validate method performs validations on the provided target object. In this core (not MVC) example we are using low-level DataBinder to initiate validation process and collect error information. package com.logicbig.example;
import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.DataBinder; import java.math.BigDecimal; import java.util.Locale;
public class ValidatorExample {
public static void main(String[] args) { Order order = new Order(); order.setPrice(BigDecimal.ZERO);
DataBinder dataBinder = new DataBinder(order); dataBinder.addValidators(new OrderValidator()); dataBinder.validate();
if (dataBinder.getBindingResult().hasErrors()) { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("ValidationMessages");
System.err.println(messageSource.getMessage("order.invalid", null, Locale.US)); dataBinder.getBindingResult().getAllErrors().stream() .forEach(e -> System.err.println(messageSource.getMessage(e, Locale.US))); } else { System.out.println("No Validation errors"); } }
}
OutputOrder has validation errors: Date cannot be empty Price should be more than zero
package com.logicbig.example;
import java.math.BigDecimal; import java.util.Date;
public class Order { private Date date; private BigDecimal price;
public void setDate(Date date) { this.date = date; }
public void setPrice(BigDecimal price) { this.price = price; }
public Date getDate() { return date; }
public BigDecimal getPrice() { return price; }
@Override public String toString() { return "Order{'date='" + date + "', price=" + price + '}'; } }
package com.logicbig.example;
import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import java.math.BigDecimal;
public class OrderValidator implements Validator {
@Override public boolean supports(Class<?> clazz) { return Order.class == clazz; }
@Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "date", "date.empty"); ValidationUtils.rejectIfEmpty(errors, "price", "price.empty"); Order order = (Order) target; if (order.getPrice() != null && order.getPrice().compareTo(BigDecimal.ZERO) <= 0) { errors.rejectValue("price", "price.invalid"); } } }
Original Post
In this example we are using ValidationUtils#invokeValidator to perform validation. package com.logicbig.example;
import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.ValidationUtils; import java.math.BigDecimal; import java.util.Locale;
public class ValidatorExample2 {
public static void main(String[] args) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("ValidationMessages");
Order order = new Order(); order.setPrice(BigDecimal.ZERO); BeanPropertyBindingResult result = new BeanPropertyBindingResult(order, "order"); ValidationUtils.invokeValidator(new OrderValidator(), order, result); if (result.getAllErrors().size() > 0) { result.getAllErrors().stream(). forEach(e -> System.err.println(messageSource.getMessage(e, Locale.US))); } else { System.out.println("No Validation errors"); } } }
OutputDate cannot be empty Price should be more than zero
package com.logicbig.example;
import java.math.BigDecimal; import java.util.Date;
public class Order { private Date date; private BigDecimal price;
public void setDate(Date date) { this.date = date; }
public void setPrice(BigDecimal price) { this.price = price; }
public Date getDate() { return date; }
public BigDecimal getPrice() { return price; }
@Override public String toString() { return "Order{'date='" + date + "', price=" + price + '}'; } }
package com.logicbig.example;
import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import java.math.BigDecimal;
public class OrderValidator implements Validator {
@Override public boolean supports(Class<?> clazz) { return Order.class == clazz; }
@Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "date", "date.empty"); ValidationUtils.rejectIfEmpty(errors, "price", "price.empty"); Order order = (Order) target; if (order.getPrice() != null && order.getPrice().compareTo(BigDecimal.ZERO) <= 0) { errors.rejectValue("price", "price.invalid"); } } }
Original Post
This example uses both org.springframework.validation.Validator and JSR 349/303 based validation annotation to perform validation. package com.logicbig.example;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ValidationMixedExample {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
ClientBean clientBean = context.getBean(ClientBean.class); Order order = new Order(); // order.setPrice(BigDecimal.TEN); // order.setDate(new Date(System.currentTimeMillis() + 100000)); order.setCustomerId("111"); clientBean.processOrder(order); }
}
OutputOrder has validation errors: Date cannot be empty No customer found with id 111 Price cannot be empty
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;
String customerId;
public void setDate(Date date) { this.date = date; }
public void setPrice(BigDecimal price) { this.price = price; }
public Date getDate() { return date; }
public BigDecimal getPrice() { return price; }
public String getCustomerId() { return customerId; }
public void setCustomerId(String customerId) { this.customerId = customerId; }
@Override public String toString() { return "Order{ date=" + date + ", price=" + price + ", customerId='" + customerId + "'}"; } }
package com.logicbig.example;
import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator;
public class OrderValidator implements Validator {
@Override public boolean supports(Class<?> clazz) { return Order.class == clazz; }
@Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "customerId", "customerId.empty");
Order order = (Order) target; if (order.getCustomerId() != null) { Customer customer = getCustomerById(order.getCustomerId()); if (customer == null) { errors.reject("customer.id.invalid", new Object[]{order.getCustomerId()}, "Customer id is not valid"); } } }
private Customer getCustomerById(String customerId) { //just for test returning null. // in real example the customer could be loop up in database etc. return null; } }
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.BindingResult; import org.springframework.validation.DataBinder; import org.springframework.validation.ObjectError; import org.springframework.validation.Validator; import jakarta.validation.ConstraintViolation; import java.awt.print.Book; import java.util.Comparator; import java.util.Locale; import java.util.Map; import java.util.Set;
public class GenericValidator {
@Autowired ApplicationContext context;
/** * This is a framework style generic method which can * validate any object given that the corresponding * validator is register as bean. */ public boolean validateObject(Object objectToValidate) {
Map<String, Validator> validatorMap = context.getBeansOfType(Validator.class); if (validatorMap == null) { return true; }
DataBinder binder = new DataBinder(objectToValidate);
//in this example two validators are register OrderValidator // and LocalValidatorFactoryBean which will do JSR 349 validations. for (Validator validator : validatorMap.values()) {
if (validator.supports(objectToValidate.getClass())) { binder.addValidators(validator); } }
binder.validate(); BindingResult bindingResult = binder.getBindingResult(); if (bindingResult.hasErrors()) { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("ValidationMessages");
System.err.println(messageSource.getMessage("object.invalid", new Object[]{objectToValidate.getClass().getSimpleName()}, Locale.US));
bindingResult.getAllErrors() .stream() .map(e -> messageSource.getMessage(e, Locale.US)) .sorted(Comparator.naturalOrder()) .forEach(System.err::println); return false; }
return true; } }
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
public class ClientBean {
@Autowired private GenericValidator genericValidator;
public void processOrder(Order order) { if (genericValidator.validateObject(order)) { System.out.println("processing " + order); } } }
package com.logicbig.example;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration public class Config {
@Bean public ClientBean clientBean() { return new ClientBean(); }
@Bean public Validator validatorFactory() { return new LocalValidatorFactoryBean(); }
@Bean public OrderValidator orderValidator() { return new OrderValidator(); }
@Bean public GenericValidator genericValidator() { return new GenericValidator(); } }
Original Post
Validator#forInstanceOf return a Validator that checks whether the target object's class is identical to targetClass, applying the given delegate to populate Errors if it is. package com.logicbig.example;
import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.validation.Errors; import org.springframework.validation.Validator;
import java.math.BigDecimal;
public class ValidatorForInstanceOfExample {
public static void main(String[] args) { Validator validator = Validator.forInstanceOf(Number.class, (number, errors) -> { if (number.doubleValue() < 0) { errors.reject("number.negative", String.format("Number (%s) cannot be negative. Found: %s", number.getClass(), number)); } });
if (validator.supports(Integer.class)) { Errors errors = validator.validateObject(Integer.valueOf(-1)); errors.getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .forEach(System.out::println); } if (validator.supports(BigDecimal.class)) { Errors errors = validator.validateObject(BigDecimal.valueOf(-10)); errors.getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .forEach(System.out::println); } } }
OutputNumber (class java.lang.Integer) cannot be negative. Found: -1 Number (class java.math.BigDecimal) cannot be negative. Found: -10
Original PostValidator#forInstanceOf return a Validator that checks whether the target object is an instance of targetClass, applying the given delegate to populate Errors if it is. package com.logicbig.example;
import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.validation.Errors; import org.springframework.validation.Validator;
import java.math.BigDecimal;
public class ValidatorForTypeExample {
public static void main(String[] args) { Validator validator = Validator.forType(Integer.class, (number, errors) -> { if (number.doubleValue() < 0) { errors.reject("number.negative", String.format("Number (%s) cannot be negative. Found: %s", number.getClass(), number)); } });
if (validator.supports(Integer.class)) { Errors errors = validator.validateObject(Integer.valueOf(-1)); errors.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).forEach(System.out::println); } if (validator.supports(BigDecimal.class)) { Errors errors = validator.validateObject(BigDecimal.valueOf(-10)); errors.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).forEach(System.out::println); } } }
OutputNumber (class java.lang.Integer) cannot be negative. Found: -1
Original Post
|
|