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