-
Notifications
You must be signed in to change notification settings - Fork 37.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jackson2Decoder fails to determine correct target type from default interface method with a generic type #23791
Comments
Please provide a repro project for the issue you observe. |
Thanks for the sample project. I can confirm there is an issue with resolving generic types from a default method via import java.lang.reflect.Method;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import static org.assertj.core.api.Assertions.assertThat;
public class Issue23791Tests {
@Test
void name() throws NoSuchMethodException {
Method method = TestController.class.getMethod("test", Mono.class);
MethodParameter bodyParam = new MethodParameter(method, 0);
ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam);
ResolvableType elementType = bodyType.getGeneric();
assertThat(elementType.getSource()).isEqualTo(TestEntity.class);
}
public interface GenericController<E> {
@PostMapping("/test")
default Mono<String> test(@RequestBody Mono<E> test) {
return Mono.empty();
}
}
@RestController
public class TestController implements GenericController<TestEntity> {
}
public class TestEntity {
}
} The above prints:
If the default method is changed to be a regular interface method, the test passes. |
I did a bit of digging that problem is caused by the fact that If you put a breakpoint at Unfortunately it doesn't appear that MethodParameter param = new MethodParameter(method, 0, TestController.class); The sets |
@rstoyanchev I think the only way to fix this is to move up the stack to the point where the |
Thanks for taking a look @philwebb. My mistake actually, the example above does not accurately reflect what actually happens in Spring MVC where a So in the above example, the TestController bean = new TestController();
HandlerMethod handlerMethod = new HandlerMethod(bean, bean.getClass().getMethod("test", Mono.class));
MethodParameter bodyParam = handlerMethod.getMethodParameters()[0]; I have also added a disabled test in the framework that mimics closely the scenario. For debugging, this is where we handle the Would you mind taking another look? It seems that all the information should be available and as far as I know the code is using |
Oops closed in error. So far the only commit for this issue is 7456fb9. |
I've not yet been able to pinpoint the exact cause. If I take the failing type and change
The call to If I run the original I see the following:
The call to In the second case the call to So it seems like the |
It looks like the ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType); At this point, because |
I'm not sure what the fix is since I don't really understand all of that code. Perhaps if |
Thanks @philwebb. So I found a way to pass the containing class through the "hints" map which resolves this issue. However I still wonder if there is room for improvement in
Right. I found out that if ResolvableType elementType = ResolvableType.forType(
GenericTypeResolver.resolveType(
bodyType.getGeneric().getType(), bodyParam.getContainingClass())); Considering that |
version:
5.2.0-RELEASE
spring-framework/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java
Line 132 in d1aee0e
The text was updated successfully, but these errors were encountered: