es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Creando un validador de restricciones para una anotación externa de terceros.

Tengo una anotación de una biblioteca de terceros a la que me gustaría agregar una implementación de validador personalizado. Llamémosla @Requirement y defínala de la siguiente manera:

@Target({PACKAGE, TYPE, METHOD, FIELD})
@Retention(RUNTIME)
@interface Requirement {}

Ahora me gustaría agregar un validador de restricciones sin agregar mi propia anotación a la mezcla. No puedo hacer esto con la configuración basada en XML (META-INF/validation.xml), la configuración del cargador de servicios (un archivo javax.validation.ConstraintValidator con mi validador) ni tampoco puedo hacerlo agregando mapeos personalizados a HibernateValidatorConfiguration usando LocalValidatorFactoryBean: todas estas posibilidades mencionadas anteriormente terminan verificando @Constraint tarde o temprano también.

¿Existe alguna manera de agregar una anotación sin @Constraint con una implementación de validador?

En mi caso específico, estoy utilizando Java 8 y Spring Boot 2.6.1 (que a su vez utiliza Hibernate Validator 6.2.0 y javax.validation:validation-api 2.0.1), pero (por supuesto) estoy abierto a información que utilice cualquier versión de Java y Spring.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Desafortunadamente, no es posible agregar un validador de restricciones a una anotación sin agregar la anotación @Constraint a la misma. Esto se debe a que el sistema de validación en Java se basa en la anotación @Constraint para identificar la anotación como una restricción y para identificar la implementación ConstraintValidator asociada.

    Si no puede modificar la anotación de la biblioteca de terceros para agregar la anotación @Constraint, deberá crear su propia anotación personalizada que incluya la anotación @Constraint y se vincule a la anotación de terceros.

    Por ejemplo, podría crear una nueva anotación llamada @MyRequirement que incluya la anotación @Constraint y se vincule a la anotación @Requirement de la biblioteca de terceros, de la siguiente manera:

    @Target({PACKAGE, TYPE, METHOD, FIELD})
    @Retention(RUNTIME)
    @Constraint(validatedBy = MyRequirementValidator.class)
    @Documented
    public @interface MyRequirement {
        String message() default "Fallo de validación";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
        @Target({PACKAGE, TYPE, METHOD, FIELD})
        @Retention(RUNTIME)
        @interface List {
            MyRequirement[] value();
        }
    }
    
    @SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT)
    public class MyRequirementValidator implements ConstraintValidator<myrequirement, annotatedelement=""> {
    
        private final RequirementValidator delegate = new RequirementValidator();
    
        @Override
        public void initialize(MyRequirement constraintAnnotation) {}
    
        @Override
        public boolean isValid(AnnotatedElement value, ConstraintValidatorContext context) {
            return delegate.isValid(value, context);
        }
    }
    

    Tenga en cuenta que el MyRequirementValidator simplemente delega en la implementación de RequirementValidator de terceros.

    Luego puede utilizar la anotación @MyRequirement en lugar de la anotación @Requirement en su código, y se utilizará MyRequirementValidator para validar la anotación.</myrequirement,>

Comments are closed.