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.