API request and response:
Request: http://localhost:5555/api/products?page=1&size=100
Response:
{
"reports": {
"content": [
{
"productCatTx": "ERROR_product",
"productValTx": "000",
"productShrtDescTx": "NO_ERROR",
"productLongDescTx": "No Error in response"
},
{
"productCatTx": "ERROR_product",
"productValTx": "010",
"productShrtDescTx": "PRODUCT_ACCEPTED",
"productLongDescTx": "Product Accepted"
}
],
"pageable": {
"sort": {
"empty": false,
"sorted": true,
"unsorted": false
},
"offset": 0,
"pageNumber": 0,
"pageSize": 100,
"unpaged": false,
"paged": true
},
"totalElements": 321,
"totalPages": 4,
"last": false,
"size": 100,
"number": 0,
"sort": {
"empty": false,
"sorted": true,
"unsorted": false
},
"numberOfElements": 100,
"first": true,
"empty": false
}
}
Client REST API call from another project:
@GetMapping("/paginatedWResponseData")
public void getProductsWResponseData() {
RestTemplate restTemplate = new RestTemplate();
String resourceUrl = "http://localhost:5555/api/products?page=1&size=100";
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(resourceUrl)
.queryParam("page", 1)
.queryParam("size", 100);
ResponseEntity<ReportResponse> responseEntity = restTemplate.exchange(uriBuilder.toUriString(),
HttpMethod.GET, null, ReportResponse.class);
System.out.println(responseEntity);
}
ReportResponse.java
@Data
@Builder
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ReportResponse extends CustomPageImpl implements Serializable {
Page<Product> reportData;
@JsonCreator
public ReportResponse(@JsonProperty("reports") Page<Product> reportData) {
super(reportData.getContent());
this.reportData = reportData;
}
}
CustomPageImpl.java
public class CustomPageImpl<T> extends PageImpl<T> {
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public CustomPageImpl(@JsonProperty("content") List<T> content, @JsonProperty("number") int number,
@JsonProperty("size") int size, @JsonProperty("totalElements") Long totalElements,
@JsonProperty("pageable") JsonNode pageable, @JsonProperty("last") boolean last,
@JsonProperty("totalPages") int totalPages, @JsonProperty("sort") JsonNode sort,
@JsonProperty("numberOfElements") int numberOfElements) {
super(content, PageRequest.of(number, 1), 10);
}
public CustomPageImpl(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public CustomPageImpl(List<T> content) {
super(content);
}
public CustomPageImpl() {
super(new ArrayList<>());
}
}
Error:
2023-08-24T13:58:53.372-04:00 ERROR 20304 --- [nio-5656-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.springframework.data.domain.Page]] with root cause
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.data.domain.Page` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 12] (through reference chain: net.code.sample.ReportResponse["reports"])
The stacktrace is telling you that Jackson library can't create a
org.springframework.data.domain.Pageinstance because it has no constructor, and it makes sense because is an interface.I think what you actually need is adjust
ReportResponseto receive aCustomPageImplinstance as argument in its constructor. Additionally you could also get rid of inheritance like this: