How to handle/catch a framework specific exception in Spring WebFlux

Viewed 183

I have a Spring WebFlux app whee I'm using @JsonTypeInfo annotation to handle polymorphic types. In the same time I'm using ConstraintValidator for the same key which is responsible for polymorphic type.

Here is some example:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Child.class, name = "CUSTOM_TYPE")
})
abstract class Parent<T> {

  @Setter
  @Getter
  @NotEmpty
  @ValueOfEnum(enumClass = MyEnum.class)
  private String type;

  public abstract void setValue(T value);
  public abstract T getValue();
}

@Data
class Child extends Parent<Integer> {

  private Integer value;
}

And ConstraintValidator:

public class ValueOfEnumValidator implements ConstraintValidator<ValueOfEnum, CharSequence> {

  private Set<String> acceptedValues;

  @Override
  public void initialize(ValueOfEnum constraintAnnotation) {
    acceptedValues = Stream.of(constraintAnnotation.enumClass().getEnumConstants())
        .map(Enum::name)
        .collect(Collectors.toSet());
  }

  @Override
  public boolean isValid(CharSequence charSequence,
                         ConstraintValidatorContext constraintValidatorContext) {
    if (Objects.isNull(charSequence) || charSequence.toString().trim().isEmpty()) {
      return true;
    }

    return acceptedValues.contains(charSequence.toString());
  }

}

If incorrect type is passed to my functional-endpoint, then I can't validate it and return the appropriate error message I would like. So Jackson's validation is happening before my own validation.

App also has global exception handling:

public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler {
//some staff here
}

But what is strange that the error I'm getting inside global exception handler is ServerWebInputException but actual exception is InvalidTypeIdException.

for now the only thing I can do is to parse json manually:

    String id = request.pathVariable("id");
    request
//        .bodyToMono(Parent.class)
        .bodyToMono(String.class)
        .map(this::mapStringToParent)
        .doOnNext(this::validate)
        // etc...

private Parent mapStringToParent(String str) {
    try {
      return objectMapper.readValue(str, Parent.class);
    } catch (InvalidTypeIdException e) {
      throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid typeId exception");
    } catch (JsonProcessingException ex) {
      throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Json processing exception: " + ex.getMessage());
    }
  }

So my question: is there a way to catch some specific exception like InvalidTypeIdException in Spring WebFlux application, or even better, possibility to create @ValueOfEnum like validator for Jackson.

0 Answers
Related