简体   繁体   中英

Java: custom enum validator annotation not triggered in Spring RestControllerAdvice exception handler

A custom enum validator annotation interface:

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = PanTypeSubSetValidator.class)
public @interface PanTypeSubset {
    PanType[] anyOf();
    String message() default "must be any of {anyOf}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

and the actual implementation:

public class PanTypeSubSetValidator implements ConstraintValidator<PanTypeSubset, PanType> {
    private PanType[] subset;

    @Override
    public void initialize(PanTypeSubset constraint) {
        this.subset = constraint.anyOf();
    }

    @Override
    public boolean isValid(PanType value, ConstraintValidatorContext context) {
        return value == null || Arrays.asList(subset).contains(value);
    }
}

and the usage inside a request DTO:

@SuperBuilder
@Data
@NoArgsConstructor
public class PanBaseRequestDto {

    @NotNull(message = "'PANTYPE' cannot be empty or null")
    @PanTypeSubset(anyOf = {PanType.PAN, PanType.TOKEN}, message = "yesssss")
    private PanType panType;

}

The problem is that this annotation never seems to be triggered. I get another exception kick in in the @RestControllerAdvice DefaultExceptionHandler implementation before this actual validation:

Handling generic exception: (Invalid JSON input: Cannot deserialize value of type `...pantoken.PanType` from String "PAN1": not one of the values accepted for Enum class: [TOKEN, PAN]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `...pantoken.PanType` from String "PAN1": not one of the values accepted for Enum class: [TOKEN, PAN]

Solved it by creating a custom @JsonCreator function inside the ENUM class. Not the best approach, as we loose the value that user has submitted when displaying error to the end client, but it's ok for me.

@JsonCreator
public static PanType create(String value) {
    if (Objects.isNull(value)) {
        return null;
    }

    return Arrays.stream(PanType.values())
            .filter(v -> value.equals(v.getType()))
            .findFirst()
            .orElse(PanType.UNKNOWN);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM