This is related to this issue, and I know we have a test to confirm that is not an issue. However the issue I found is that it only works when we explicitly specify the type like this bodyToMono(new ParameterizedTypeReference<ValueContainer<Foo>>() {}). It will not work if we move that webClient.get() block to a separate function and change it to take generic type like this bodyToMono(new ParameterizedTypeReference<ValueContainer<T>>() {});. Here is the modified unit test. It will throw error class java.util.LinkedHashMap cannot be cast to class org.springframework.web.reactive.function.client. WebClientIntegrationTests$Foo

    @Test
    public void shouldReceiveJsonAsTypeReferenceString() throws Exception {
        String content = "{\"containerValue\":{\"fooValue\":\"bar\"}}";
        prepareResponse(response -> response
            .setHeader("Content-Type", "application/json").setBody(content));

        Mono<ValueContainer<Foo>> result = getData();

        StepVerifier.create(result)
            .assertNext(valueContainer -> {
                Foo foo = valueContainer.getContainerValue();
                assertNotNull(foo);
                assertEquals("bar", foo.getFooValue());
            })
            .expectComplete().verify(Duration.ofSeconds(3));

        expectRequestCount(1);
        expectRequest(request -> {
            assertEquals("/json", request.getPath());
            assertEquals("application/json", request.getHeader(HttpHeaders.ACCEPT));
        });
    }

    private <T> Mono<ValueContainer<T>> getData() {
        return this.webClient.get()
            .uri("/json").accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(new ParameterizedTypeReference<ValueContainer<T>>() {});
    }

Spring boot version is 2.5.3

Comment From: poutsma

You are running into one of the limitations of the Java type system. In order for ParameterizedTypeReference to work, it needs to be bound to a specific type at compile time, and cannot be used in the generic way shown in the test. For more information about this topic, see this article.

In other words: there is nothing that Spring can do to fix this.

Comment From: anhtuta

I think this will work

private <T> Mono<ValueContainer<T>> getData(Class<T> responseType) {
        return this.webClient.get()
            .uri("/json").accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(responseType);
}