Ya todos conocen los mecanismos para validar POJOs que provee JEE, para el que no tenga conocimiento puede ver la especificación de la primera versión aquí y la versión 1.1 aqui:
La idea es que mediante anotaciones se puedan definir las validaciones a realizar, ademas se provee un grupo de validaciones básicas pero muy útiles. En el caso de que ese grupo no cumpla nuestros requerimientos se pueden hacer validaciones a medida y eso es justamente una de las cosas que voy a mostrar en este POST.
Crear un validador custom.
Para crear un validador personalizados se deberán crear dos clases.
- La @interfaz (anotación) que define la anotación, su nombre, parámetros, donde puede ser usada, etc.
- La implementación del validador: Es propiamente el código que valida los atributos a los que se les anote con dicha anotación.
La interfaz, podría recibir parámetros como se muestra a continuación y luego el mismo estará disponible en la implementan de la validación.
La @interfaz quedaría definida así.
@Target({METHOD, FIELD, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = CustomValidatorImpl.class) @Documented public @interface CustomValidator { String message() default "ErrorMessage Custom Validator"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; long value(); }
La implementan tomara el valor definido en la @interfaz como el valor mínimo para el cual se deberá validar.
public class CustomValidatorImpl implements ConstraintValidator<CustomValidator, Long> { private long min; @Override public void initialize(CustomValidator constraintAnnotation) { this.min = constraintAnnotation.value(); } @Override public boolean isValid(Long object, ConstraintValidatorContext constraintContext) { if (object == null) { return false; } return object > min; } }
Luego si queremos utilizar la nueva validación realizamos lo siguiente:
public class Car { private String marca; private String modelo; @CustomValidator(2) private long puertas; @CustomValidator(2) private long ventanas; ..............
Interceptor para validar parámetros de entrada ( por ejemplo en WebServices SOAP)
Si el entorno donde se están usando los POJOs, no es un entorno administrado que valide automáticamente las anotaciones, siempre podrán validarlas de forma explicita.
Para facilitar dicha tarea, voy a crear un Interceptor que permita validar los parámetros antes de ejecutar la acción de un WebService
Creamos el Interceptor:
public class ValidationInterceptor { @AroundInvoke public Object intercept(InvocationContext context) throws Exception { for (Object param : context.getParameters()) { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set<ConstraintViolation<Object>> constraintViolations = validator.validate(param); for (ConstraintViolation<Object> viol : constraintViolations) { System.out.println("ERROR::::" + viol.getMessage() + " property:" + viol.getPropertyPath()); } } Object result = context.proceed(); System.out.println("ValidationInterceptor - Logging AFTER calling method :" + context.getMethod().getName()); return result; } }
Definimos el Interceptor por ejemplo en un WebService SOAP:
@WebService(serviceName = "BeanValidatonWs") @Interceptors(ValidationInterceptor.class) public class BeanValidatonWs { .....................
El código de ejemplo lo encuentran en mi cuenta de Github: aqui