Close

JavaBean Validation - Creating custom constraint Examples

JavaBean Validation JAVA EE 

This example creates a new constraint annotation to validate constructor return value.

package com.logicbig.example;

import javax.validation.*;
import javax.validation.executable.ExecutableValidator;
import java.lang.annotation.*;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Set;

public class ConstructorReturnValidationExample {

public static class Order {
private final BigDecimal price;
private final BigDecimal quantity;

@ValidOrder
public Order (BigDecimal price, BigDecimal quantity) {
this.price = price;
this.quantity = quantity;
}

public BigDecimal getPrice () {
return price;
}

public BigDecimal getQuantity () {
return quantity;
}

public BigDecimal getTotalPrice () {
return (price != null && quantity != null ?
price.multiply(quantity) : BigDecimal.ZERO)
.setScale(2, RoundingMode.CEILING);
}
}

public static void main (String[] args) throws NoSuchMethodException {
Order order = new Order(new BigDecimal(4.5), new BigDecimal(10));
Constructor<Order> constructor =
Order.class.getConstructor(BigDecimal.class, BigDecimal.class);

Validator validator = getValidator();
ExecutableValidator executableValidator = validator.forExecutables();
Set<ConstraintViolation<Order>> constraintViolations =
executableValidator.validateConstructorReturnValue(constructor, order);

if (constraintViolations.size() > 0) {
constraintViolations.stream().forEach(
ConstructorReturnValidationExample::printError);
} else {
//proceed using order
System.out.println(order);
}
}

private static Validator getValidator(){
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
Validator validator = factory.getValidator();
factory.close();
return validator;
}

private static void printError (
ConstraintViolation<Order> violation) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}


@Target({ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = OrderValidator.class)
@Documented
public static @interface ValidOrder {
String message () default "total price must be 50 or greater for online order. " +
"Found: ${validatedValue.totalPrice}";

Class<?>[] groups () default {};

Class<? extends Payload>[] payload () default {};
}


public static class OrderValidator implements ConstraintValidator<ValidOrder, Order> {
@Override
public void initialize (ValidOrder constraintAnnotation) {
}

@Override
public boolean isValid (Order order, ConstraintValidatorContext context) {
if (order.getPrice() == null || order.getQuantity() == null) {
return false;
}
return order.getTotalPrice()
.compareTo(new BigDecimal(50)) >= 0;

}
}
}

Output

Order.<return value> total price must be 50 or greater for online order. Found: 45.00
Original Post




This example creates a new constraint annotation 'Language' and a corresponding 'LanguageValidator' which implements ConstraintValidator interface.

package com.logicbig.example;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = LanguageValidator.class)
@Documented
public @interface Language {
String message() default "must be a valid language display name." +
" found: ${validatedValue}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}
package com.logicbig.example;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Locale;

public class LanguageValidator implements ConstraintValidator<Language, String> {

@Override
public void initialize(Language constraintAnnotation) {
}

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
for (Locale locale : Locale.getAvailableLocales()) {
if (locale.getDisplayLanguage().equalsIgnoreCase(value)) {
return true;
}
}

return false;
}
}
package com.logicbig.example;

class TestBean {
@Language
private String language;

public String getLanguage() {
return language;
}

public void setLanguage(String language) {
this.language = language;
}
}

package com.logicbig.example;

import javax.validation.*;

public class CustomConstraintExample {
private static final Validator validator;

static {
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
validator = factory.getValidator();
factory.close();
}

public static void main(String[] args) {
TestBean testBean = new TestBean();
testBean.setLanguage("englis");
validator.validate(testBean).stream().forEach(CustomConstraintExample::printError);
}

private static void printError(ConstraintViolation<TestBean> violation) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}

}

Output

language must be a valid language display name. found: englis
Original Post




See Also