Home > Software engineering >  How to throw a meaningful error message from an invalid enum request param in spring boot?
How to throw a meaningful error message from an invalid enum request param in spring boot?

Time:06-30

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?

CodePudding user response:

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 {};
}

CodePudding user response:

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
  • Related