'Is It Possible to Have a Constraint Annotation That Targets an Interface Instead of a Type?

Is it possible to create a constraint annotation, that targets an interface but can be used to validate any concrete implementation that implements said interface?

For example, we have interface Identifiable:

public interface Identifiable {
    String getId();
}

I'd like to create a constraint, that targets List<Identifiable>:

@Documented
@Constraint(validatedBy = IdentifiablesValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Identifiables {
    // ...Constraint properties...
}

public class IdentifiablesValidator implements ConstraintValidator<Identifiables, List<Identifiable>> {
    // ...Validator logic...
}

And then apply the constraint to a target that implements the interface:

public class SomeExampleCase {
   @Identifiables()
   List<IdentifiableImpl> sut;
}

But at runtime this results in an error:

javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'com.example.Identifiables' validating type 'java.util.List<com.example.IdentifiableImpl>'. Check configuration for 'identifiables'

The constraint does work for validation, when applied to a list of the interface (e.g. List<Identifiable>). But this forces the target class (e.g. SomeExampleCase) to use the interface, rather than an implementation - which gets in the way of all types of things (e.g. Marshalling/Unmarshalling).

Is there a way to get the validator to work with an actual List<Identifiable>, without rewriting it to target `List?

Thanks in advance!

Update 1: The same issue occurs when the interface is turned into an abstract class.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source