Skip to content
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

PageJacksonModule doesn't deserialize all Spring Page attributes #814

Closed
AlexyNau opened this issue Jan 5, 2023 · 6 comments · Fixed by #984
Closed

PageJacksonModule doesn't deserialize all Spring Page attributes #814

AlexyNau opened this issue Jan 5, 2023 · 6 comments · Fixed by #984
Assignees
Labels
bug Something isn't working
Milestone

Comments

@AlexyNau
Copy link

AlexyNau commented Jan 5, 2023

Describe the bug
My app is an Spring boot API using these versions :
Spring-cloud-openfeign-core : 3.1.5
Spring-data-commons : 2.7.6

I am using a feign client with an endpoint returning a Page<ClientDTO> like this example :

import org.springframework.data.domain.Page;
/* others imports */

@FeignClient(name = "SpringRemoteApiClient ", url = "${api.spring-remote.url}/users", configuration = FeignConfig.class)
public interface SpringRemoteApiClient {

    @GetMapping(value = "/country/{country}")
    Page<ClientDTO> getClientsByCountry(@PathVariable("country") String country, @ParameterObject @PageableDefault(sort = "name") Pageable pageable);
}

This feign client is a Spring boot OpenAPI application (Spring boot 2.7.6).

If I call directly the endpoint, the JSON reponse will have this structure :

{
  "content": [
    {
      "id": 1,
      "name": "Abc",
      "country": "Def"
    },
  ...
  ],
  "pageable": {
    "page": 0,
    "size": 10,
    "sort": {
      "orders": [
        {
          "direction": "ASC",
          "property": "client.name",
          "ignoreCase": false,
          "nullHandling": "NATIVE",
          "ascending": true,
          "descending": false
        }
      ],
      "empty": false,
      "sorted": true,
      "unsorted": false
    },
    "unpaged": false,
    "paged": true
  },
  "total": 34,
  "last": true,
  "first": false,
  "empty": false
}

And when I call the endpoint with feign, the response is decoded by org.springframework.cloud.openfeign.support.PageJacksonModule

What I get :

Page<ClientDTO> clients = springRemoteApiClient.getClientsByCountry(country, PageRequest.of(0, 10));
clients.getTotalElements(); // 10
clients.getSize(); // 10
clients.getTotalPages(); // 1
clients.getSort().isSorted(); // false
clients.isLast(); // true

What I want :

Page<ClientDTO> clients = springRemoteApiClient.getClientsByCountry(country, PageRequest.of(0, 10));
clients.getTotalElements(); // 34
clients.getSize(); // 10
clients.getTotalPages(); // 4
clients.getSort().isSorted(); // true
clients.isLast(); // false

The response is then incomplete, only content match with SimplePageImpl constructor. Other attributes gets a wrong default value.
The issue is that PageJacksonModule doesn't fullfill number, size, totalElements or sort attributes in SimplePageImpl constructor as you can see here :

/* part of PageJacksonModule */

SimplePageImpl(@JsonProperty("content") List<T> content, @JsonProperty("number") int number, @JsonProperty("size") int size, @JsonProperty("totalElements") @JsonAlias({"total-elements", "total_elements", "totalelements", "TotalElements"}) long totalElements, @JsonProperty("sort") Sort sort) {
            if (size > 0) {
                PageRequest pageRequest;
                if (sort != null) {
                    pageRequest = PageRequest.of(number, size, sort);
                } else {
                    pageRequest = PageRequest.of(number, size);
                }

                this.delegate = new PageImpl(content, pageRequest, totalElements);
            } else {
                this.delegate = new PageImpl(content);
            }

        }

Do you have any solution or is it possible to fix this issue in a future release ?
By adding @JsonProperty("pageable") JsonNode pageable, and @JsonAlias({"total",...}) in the SimplePageImpl constructor for example ?

Thank you,

@OlgaMaciaszek
Copy link
Collaborator

Hi @AlexyNau, thanks for reporting this issue. Can you please provide a sample as a link to a small executable app that reproduces the issue instead of separate code snippets? - we'll take a closer look then.

@AlexyNau
Copy link
Author

Hello @OlgaMaciaszek, you can find a sample in my repositories.
First, a backend api that is used as a feign client : https://github.com/AlexyNau/my-app
And then, the bff api, where you can reproduce the issue : https://github.com/AlexyNau/bff-my-app
Clone them both and launch them as a SpringBoot Application (JDK 19).
Feel free if you have any questions.

@OlgaMaciaszek
Copy link
Collaborator

Thanks for the sample @AlexyNau. I was able to reproduce it. Will provide a fix.

@spencergibb spencergibb removed this from the 3.1.7 milestone Apr 28, 2023
@ffroliva
Copy link

ffroliva commented Aug 2, 2023

Any update on this?

@aliemredeneri
Copy link

Any news ?

@OlgaMaciaszek
Copy link
Collaborator

Fix merged to main. Will be available with the next 2023.0.x Spring Cloud release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Done
Status: Done
Development

Successfully merging a pull request may close this issue.

6 participants