I'm using 'admin-on-rest' UI for my Web-application and it has next restriction:
Note: The jsonServer REST client expects the API to include a X-Total-Count header in the response to GET_LIST calls. The value must be the total number of resources in the collection. This allows admin-on-rest to know how many pages of resources there are in total, and build the pagination controls.
I solved the problem by adding X-Total-Count header to my list-returning REST-endpoints manually like this:
response.addHeader("X-Total-Count", String.valueOf(outputList.size()));
But I'm wondering: if there's some elegant way to do it automatically in Spring? I mean auto-add this header with proper value when some endpoint returns JSON-list?
In case you don't want just the total number of the elements in the response but the total number of entities in the corresponding JPA method of PagingAndSortingRepository
you can do something like that which is useful for paging applications :)
Inspired by Bohdan's answer ( https://stackoverflow.com/a/44376133/986160)
@ControllerAdvice
public class ResourceSizeAdvice implements ResponseBodyAdvice<Page<?>> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
//Checks if this advice is applicable.
//In this case it applies to any endpoint which returns a page.
return Page.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public Page<?> beforeBodyWrite(Page<?> page, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
serverHttpResponse.getHeaders().add("X-Total-Count",String.valueOf(page.getTotalElements()));
return page;
}
}
Make sure to call the Pageable version of the default methods like so it returns a Page
and not a List
:
repository.findAll(new PageRequest(0,100));
If you are not using Repositories then you have to do two queries:
Select * from ...
and
Select count(*) from ...
and return a Wrapper
which has contents for the list of results plus total for the total coming from count. Then you can change the @ControllerAdvice
class to expect your Wrapper
and get the total from it and put it in the header
Because from Page you can get total elements. So I've added headers to ResponseEntity
@GetMapping(value = POSTS, headers = "Accept=application/json")
public ResponseEntity<?> getListPost(@RequestParam(required = false, defaultValue = "0") Integer page, @RequestParam(required = false, defaultValue = "25") Integer size) {
// Create pageable
Pageable pageable = new PageRequest(page, size);
Page<Post> pagePost = postService.getPagePost(pageable);
HttpHeaders headers = new HttpHeaders() {
{
add("Access-Control-Expose-Headers", "Content-Range");
add("Content-Range", String.valueOf(pagePost.getTotalElements()));
}
};
// return new ResponseEntity<>(new CommonResponseBody("OK", 200, postList), HttpStatus.OK);
return new ResponseEntity<>(new CommonResponseBody("OK", 200, new LinkedHashMap() {
{
put("data", pagePost.getContent());
}
}), headers, HttpStatus.OK);
}
getPagePost is service method which uses Page findAll(Pageable pageable) in Repository.
Note: Change Content-Range to X-Total-Count if it doesn't work for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With