Search code examples
spring-hateoasparameterized-types

How can I specify actual type of T on a ParameterizedTypeReference<T>?


I have a controller defines following methods.


    Mono<EntityModel<Some>> readSome(...) {
        // works, simply.
    }

    Flux<EntityModel<Other>> readOther(...) {
        // works, simply.
    }

And, within my test class, I defined following methods that work.

    // WORKS!
    static List<EntityModel<Some>> readSome(...) {
        client...
                .exchange()
                .expectStatus().isOk()
                .expectBodyList(new TypeReferences.EntityModelType<Some>() {
                })
                .returnResult()
                .getResponseBody();
    }

    // WORKS!
    static List<EntityModel<Other>> readOther(...) {
        client...
                .exchange()
                .expectStatus().isOk()
                .expectBodyList(new TypeReferences.EntityModelType<Other>() {
                })
                .returnResult()
                .getResponseBody()
    }

And I naturally defined following method for all types.

As you can see, it's just a generic method for all types.

    private static <T> List<EntityModel<T>> readList(final WebTestClient client,
                                                     final Function<UriBuilder, URI> uriFunction,
                                                     @Nullable final String accept) {
        final var responseBody = client
                .get()
                .uri(uriFunction)
                .headers(h -> {
                    Optional.ofNullable(accept)
                            .map(MediaType::valueOf)
                            .map(List::of)
                            .ifPresent(h::setAccept);
                })
                .exchange()
                .expectStatus().isOk()
                .expectBodyList(new TypeReferences.EntityModelType<T>() { // NOT <T>, BUT Map
                })
                .returnResult()
                .getResponseBody();
        return Objects.requireNonNull(responseBody, "responseBody is null");
    }

Now, when I changed the readSome|readOther method with the readList method, I see a weird behavior.

The Jackson does not parse the content into the anymore, but a LinkedHashMap.

How can I specify Class<T> with the TypeReferences.EntityModelType<T>?


Solution

  • Try to make EntityModelType as a parameter of your method.

    private static <T> List<EntityModel<T>> readList(
        TypeReferences.EntityModelType<T> entityType,
        final WebTestClient client,
        final Function<UriBuilder, URI> uriFunction,
        @Nullable final String accept
    ) {
            final var responseBody = client
                    .get()
                    .uri(uriFunction)
                    .headers(h -> {
                        Optional.ofNullable(accept)
                                .map(MediaType::valueOf)
                                .map(List::of)
                                .ifPresent(h::setAccept);
                    })
                    .exchange()
                    .expectStatus().isOk()
                    .expectBodyList(entityType)
                    .returnResult()
                    .getResponseBody();
            return Objects.requireNonNull(responseBody, "responseBody is null");
        }
    
    

    and then call it

    readList(
        new TypeReferences.EntityModelType<Other>() {},
        .....
    );
    

    Hope it works.