Affects: \<5.3.22>

@RestControllerAdvice(annotations = Controller.class)
@Slf4j
public class RestBodyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return returnType.getDeclaringClass().getName().startsWith("xxx.xx.com")
                && (AnnotationUtils.findAnnotation(returnType.getDeclaringClass(), ResponseBody.class) != null
                || returnType.hasMethodAnnotation(ResponseBody.class));

    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        return new Msg<>(ExceptionCode.SUCCESS.getCode(), ExceptionCode.SUCCESS.getDescription(), body);
    }
}

An error is reported when the type of body is string

@RestController
@RequestMapping("/test")
public class TestController {
    @PostMapping("/test")
    public String test() {
        return "test";
    }
}

java.lang.ClassCastException: class xxx.xx.Msg cannot be cast to class java.lang.String (xxx.xx.Msg is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
    at org.springframework.http.converter.StringHttpMessageConverter.addDefaultHeaders(StringHttpMessageConverter.java:44) ~[spring-web-5.3.22.jar:5.3.22]

Comment From: simonbasle

RequestBodyAdvice is probably not the right tool for the job here, as you're seeking to transform/wrap the object returned by the controller after an HttpMessageConverter has been selected.

The contract should be made a bit more explicit, but basically you need to be super careful with ResponseBodyAdvice<Object> (notice the generic part) because then your Advice MUST maintain a type compatible with the returnType/the type of the body object in what it returns from beforeBodyWrite.

Some converters will seemingly work fine (JSON ones for instance will happily deal with any kind of object), but others like the StringHttpMessageConverter are stricter in what they accept.

Comment From: simonbasle

see this other answer: https://github.com/spring-projects/spring-framework/issues/25103#issuecomment-630774536