I want to use WebClient to retrieve a page from another microservice. When I directly request the microservice using Postman, the response includes the type
attribute among other fields in the content
section. However, when I make the request via WebClient, the type
attribute (and some other fields) disappear from the content
section. The content
is a list of objects of the abstract class Account
. which uses JsonSubTypes
for polymorphic deserialization.
Can someone help me identify the mistake and understand why the "type" attribute disappears when using WebClient to call the microservice?
Here are the sample responses for comparison:
Responses
Response from http://localhost:8080/api/v1/accounts
{
"content": [
{
"type": "savingsBook",
"id": 108,
"accountNumber": 99781944,
...
}
], "pageable": {
...
}, "totalPages": ...
...
}
Response from http://localhost:8081/accounts
{
"content": [
{
"id": 108,
"accountNumber": 99781944,
...
}
], "pageable": {
...
}, "totalPages": ...
...
}
Code-Snippets:
8080's account controller
@RequestMapping(method = RequestMethod.GET, produces = "application/json")
public <T extends Account> Page<T> getAccounts(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "pageSize", required = false) Integer pageSize, @RequestParam(value = "sortBy", required = false) String sortBy) {
if (page == null) {
page = 0;
}
if (pageSize == null) {
pageSize = 10;
}
if (sortBy == null) {
Page<T> p = accountService.getAccounts(page, pageSize);
return new PageImpl<T>(p.getContent(), p.getPageable(), p.getTotalElements()) {};
} else {
Sort sort = Sort.by(sortBy);
Page<T> p = accountService.getAccounts(page, pageSize, sort);
return new PageImpl<T>(p.getContent(), p.getPageable(), p.getTotalElements()) {};
}
}
8081 Account Controler
@GetMapping
public <T extends Account> Page<T> getAllAccounts(@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "pageSize", required = false) Integer pageSize,
@RequestParam(value = "sortBy", required = false) String sortBy) {
if (page == null) {
page = 0;
}
if (pageSize == null) {
pageSize = 10;
}
if (sortBy == null) {
return accountService.getAllAccounts(page, pageSize);
} else {
return accountService.getAllAccounts(page, pageSize, sortBy);
}
}
8081 AccountService
public <T extends Account> Page<T> getAllAccounts(Integer pageNumber, Integer pageSize) {
ParameterizedTypeReference<CustomPageImpl<T>> typeReference = new ParameterizedTypeReference<CustomPageImpl<T>>(){};
System.out.println("Anfrage an: " + addr + "/accounts/");
System.out.println(client.get().uri("/accounts/").retrieve().bodyToMono(typeReference).block().getContent());
Page<T> prodData = (CustomPageImpl<T>)(client.get().uri("/accounts/").retrieve().bodyToMono(typeReference).block());
return prodData;
}
CustomPageImpl (got it from another StackOverflow-Post)
public class CustomPageImpl<T> extends PageImpl<T> {
private static final long serialVersionUID = 1L;
@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("first") boolean first,
@JsonProperty("numberOfElements") int numberOfElements){
super(content, PageRequest.of(number, size) , totalElements);
}
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<>());
}
}
I found an answer to this question on my own.
The problem is the fact, that Account is abstract and has json subtypes. By replacing public class CustomPageImpl<T> extends PageImpl<T>
by public class CustomPageImpl<T extends Account> extends PageImpl<T>
I was able to solve this issue. Now I receive the type as planned.