Pavel Skála
Pavel Skála

Reputation: 11

Annotation for validating a parameter in a record constructor is not working when @Target is specified as RECORD_COMPONENT

The ElementType.RECORD_COMPONENT, when applied to annotation for constructor parameter of a record does not work as I would anticipate. I have this record:

public record MyRecord (
    MultipartFile document
) {}

I want to ensure that document is file type application/pdf. So I created the annotation:

@Documented
@Target({ElementType.RECORD_COMPONENT})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PdfValidator.class)
public @interface ValidPdf {
    String message() default "MultipartFile must be application/pdf type";

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

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

the validator:

public class PdfValidator implements ConstraintValidator<ValidPdf, MultipartFile> {
    @Override
    public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
        if (file == null) {
            return false;
        }
        return "application/pdf".equals(file.getContentType());
    }
}

and applied it to the record:

public record MyRecord (
    @ValidPdf
    MultipartFile document
) {}

This however doesn't work, the validator is never called. After a few tries I managed to make it work by changing the @Target in PdfValid interface from RECORD_COMPONENT to FIELD.

@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PdfValidator.class)
public @interface ValidPdf {
    String message() default "MultipartFile must be application/pdf type";

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

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

Now it works. But why? Isn't document in MyRecord literally a record component? Why is FIELD the correct value here?

Upvotes: 1

Views: 1220

Answers (0)

Related Questions