4

I am accepting an enum parameter to my API but when I use an invalid param via Postman I get blank 400 Bad Request response. I want a meaningful error message like : "invalid Type please insert ..."

 public ResponseEntity<JsonNode> getForType(

    @Parameter(name = "type") @Valid @RequestParam @EnumString(enumClass =  RequestParams.Type.class) RequestParams.Type type,
...

EnumString.java:

public @interface EnumString {
    Class<? extends Enum<?>> enumClass();
    String message() default "must be any of enum {enumClass}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

EnumStringValidator.java:

public class EnumStringValidator implements ConstraintValidator<EnumString, Enum> {
    private List<String> acceptedValues;

    @Override
    public void initialize(EnumString annotation) {
        acceptedValues = Stream.of(annotation.enumClass().getEnumConstants())
                .map(Enum::name)
                .collect(Collectors.toList());
    }

    @Override
    public boolean isValid(Enum value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }

        return acceptedValues.contains(value.name());
    }
}
}

I created a custom validator EnumString and EnumStringValidator but the type does not even get to the validator. If it is an invalid type then it doesn't even get into the validation. How can I keep the parameter as an Enum of Type and also throw an error message if a user passes an invalid one?

Gojo
  • 151
  • 7
  • If I remember correctly, you need to add JsonValue to your enum, supported by [this answer](https://stackoverflow.com/a/20421494/3393379) and from there you can handle the validation. seems like or would create some repetition, though. – thinkgruen Jun 28 '22 at 20:53
  • 1
    Maybe could try creating your own exception handler? – Lekan Swansons Jun 28 '22 at 20:59
  • I was able to dig up [this answer](https://stackoverflow.com/a/18209990/3393379) as well – thinkgruen Jun 28 '22 at 21:00

2 Answers2

1

I ended up changing to the input parameter as a String instead of Type enum. I also used @Schema(implementation = RequestParams.Type.class) to maintain the dropdown in swagger. Then I added some validation in the java code to check if it matches the enum to throw a proper error message.

@Parameter(name = "type") @Valid @RequestParam @Schema(implementation = RequestParams.Type.class) String type
Gojo
  • 151
  • 7
0

Your enumeration code misses some important meta-information.

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=EnumStringValidator.class)
public @interface EnumString {
    Class<? extends Enum<?>> enumClass();
    String message() default "must be any of enum {enumClass}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
Panagiotis Bougioukos
  • 15,955
  • 2
  • 30
  • 47