Spring pagination - request parameters - spring

My REST contorller:
#GetMapping("/test")
public Page<MyObject> pathParamTest(Pageable pageable) {
return myService.getPage(pageable);
}
I send a request like following:
localhost:8091/endpoint/test?page=0&size=3&sort=id&direction=DESC
It's my response from server:
{
"content": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
],
"last": true,
"totalPages": 1,
"totalElements": 3,
"first": true,
"sort": [
{
"direction": "ASC",
"property": "id",
"ignoreCase": false,
"nullHandling": "NATIVE",
"descending": false,
"ascending": true
}
],
"numberOfElements": 3,
"size": 3,
"number": 0
}
but the request has still direction = ASC.
How can I send to server direction = DESC?
And why response has a field "last" = true, because next page has one element more?

try
localhost:8091/endpoint/test?page=0&size=3&sort=id,DESC
from spring data rest 6.2. Sorting
curl -v
"http://localhost:8080/people/search/nameStartsWith?name=K&sort=name,desc"
sort Properties that should be sorted by in the format
property,property(,ASC|DESC). Default sort direction is ascending. Use
multiple sort parameters if you want to switch directions, e.g.
?sort=firstname&sort=lastname,asc.

Related

Feign client sorting problem with Turkish characters into response

I use feign to make request to another microservice with pageable and my custom encoder to manage sorting/paging;
#GetMapping(
value = {"/add-ben"},
produces = {"application/json"}
)
BaseResponse<MyPageImpl<AddBenDTO>> getAddBenDTOList(#SpringQueryMap RequestGetAddBen request, Pageable pageable);
I am using below JSON to use pageable;
{
"offset": 0,
"sort": "name,DESC",
"unpaged": true,
"paged": true,
"pageNumber": 0,
"pageSize": 0
}
After the response accepted, I saw that the 'name' values are sorted into DESCENDING order with using "Turkish" characters at first (not starting from Z, but with turkish characters such as İ,Ü,Ş is at the beginning);
{
"data": {
"content": [
{
(...)
"name": "İSDEMİR ADDBEN TANIMI",
},
{
(...)
"name": "ÜCRETSİZ HAYAT SİGORTA"
},
{
(...)
"name": "ZUNICO _ADD BEN"
},
{
(...)
"name": "TPATVAKF_ FON",
},
{
(...)
"name": "PROMET END.VE TİC.LAST."
},
{
(...)
"name": "OYAK RENAULT OTOMOBİL FABRİKALARI A.Ş."
}
], (...)
}
I think, this is related with the default charset. According to feign doc. UTF-8 is the default charset.
How can I correct the sorting with correct order including Turkish characters also?
Thanks

Laravel JSON Pagination: How to remove the arrows from next/previous link?

I'm using Laravel 8.20.1 and my API route returns a paginated JSON response.
Is there a better way than str_replace() to remove the arrows from the labels?
routes/api.php:
Route::middleware('auth:sanctum')->get('/items', function (Request $request) {
return new ItemCollection(Item::paginate(5));
});
response.data.meta
{
"current_page": 1,
"from": 1,
"last_page": 3,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
....
{
"url": "http://localhost/api/items?page=2",
"label": "Next »",
"active": false
}
],
"path": "http://localhost/api/items",
"per_page": 5,
"to": 5,
"total": 15
}
Those labels for Next and Previous are in the translation files, resources/lang/en/pagination.php. If you look at Illuminate\Pagination\LengthAwarePaginator::linkCollection you can see it building the links part of the response.

How to extend CollectionModel/PagedModel in Spring Hateoas?

A hypermedia response that needs to be consumed by one of my services looks like this:
{
"_embedded": {
"content": [
{
"createdBy": "...",
"createdDate": "2020-03-07T14:21:27.507Z",
"id": "...",
"name": "item1",
"_links": {
"self": {
"href": ".."
}
}
}
]
},
"_links": {
"self": {
"href": "..."
},
},
"pageNumber": 1,
"totalItems": 20,
"pageSize": 10
}
See how the paging related info is not what's expected by Spring Hateoas PagedModel which should have a single "page" property instead of individual ones for pageNumber, totalItems and pageSize:
"page": {
"size": 2,
"totalElements": 1000,
"totalPages": 500,
"number": 5
}
What I did in the end was to extend CollectionModel by adding those individual properties. This does work correctly deserialising a response shown above. But, all the CollectionModel constructors are now deprecated and the alternative is to use "CollectionModel.of", which however returns just CollectionModel.
What's the right way of customising paging information in using Spring Hateoas?
Many thanks!

Laravel - Change pagination root url

I am building an API Gateway and I am having a small problem returning the pagination urls from a microservice to the API Gateway.
This is the current structure of my API Gateway:
When I call the microservice, I can easily pass the paging parameters using the request data:
HTTP::get('http://api.billing.microservice.test/v2/invoices', $request->all());
However, when I make a request for a microservice, it returns the requested data, but with the URL of the microservice:
{
"data": [
# data returned from billing microservice with the billing API URL
],
"links": {
"first": "http://api.billing.microservice.test/v2/invoices?page=1",
"last": "http://api.billing.microservice.test/v2/invoices?page=10",
"prev": null,
"next": "http://api.billing.microservice.test/v2/invoices?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://api.billing.microservice.test/v2/invoices",
"per_page": 30,
"to": 30,
"total": 300
}
}
However I need the return to have the main API URL:
{
"data": [
# data returned from billing microservice with the main API Address
],
"links": {
"first": "http://api.main.test/v2/invoices?page=1",
"last": "http://api.main.microservice.test/v2/invoices?page=10",
"prev": null,
"next": "http://api.main.test/v2/invoices?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://api.main.test/v2/invoices",
"per_page": 30,
"to": 30,
"total": 300
}
}
Has anyone had to do something similar? What is the best way to achieve the desired results? Do a replace using some kind of regex? Is there anything I can do inside the microservice?
I was able to solve my problem with a simple method that already exists:
Model::paginate()->setPath('http://api.main.microservice.test/v2/invoices');
The result is:
{
"data": [
# data
],
"links": {
"first": "http://api.main.microservice.test/v2/invoices?page=1",
"last": "http://api.main.microservice.test/v2/invoices?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://api.main.microservice.test/v2/invoices",
"per_page": 30,
"to": 3,
"total": 3
}
}

Pageable REST API

I'm using Pageable to return json results with pages. One example of my controller
#GetMapping("/nome/{nome}")
public ResponseEntity<Page<Cidadao>> consultaPorNome(
#PathVariable(value="nome",required=true) String nome,
#RequestParam(value="pagina", defaultValue="0") Integer page,
#RequestParam(value="quantidade", defaultValue="10") Integer linesPerPage,
#RequestParam(value="ordem", defaultValue="nome") String orderBy,
#RequestParam(value="direcao", defaultValue="ASC") String direction){
Page<Cidadao> lista = cidadaoService.findByNome(nome,page,linesPerPage,orderBy, direction);
return ResponseEntity.ok(lista);
}
And i get json like
{
"content": [
{
"id": 1,
"name": "Lucas"
},
{
"id": 2,
"name": "Erick"
},
],
"totalElements": 23,
"totalPages": 3,
"last": false,
"numberOfElements": 10,
"first": true,
"sort": [
{
"direction": "ASC",
"property": "nome",
"ignoreCase": false,
"nullHandling": "NATIVE",
"ascending": true,
"descending": false
}
],
"size": 10,
"number": 0
}
but i would like to return this way
{
"data":{
"content" : [
{
"id": 1,
"name": "Lucas"
},
{
"id": 1,
"name": "Lucas"
}
],
"totalElements": 23,
"totalPages": 3,
"last": false,
"numberOfElements": 10,
"first": true,
"sort": [
{
"direction": "ASC",
"property": "nome",
"ignoreCase": false,
"nullHandling": "NATIVE",
"ascending": true,
"descending": false
}
],
"size": 10,
"number": 0
},
errors:[]
}
It is possible implements anything like this to change or add attributes like errors ? Or if possible change the name attributes from Page like totalElements for numberofTotalElementBySomething.... ??
When I was looking for, I didn't find a beautiful solution to do this. So, I did this way:
Create a class called PageAdapter (or whatever you like)
public class PageAdapter<T extends Serializable> implements Serializable {
private long totalElements;
private long totalPages;
private long size;
private List<T> content;
public PageAdapter(Page<T> page){
this.totalElements = page.getTotalElements();
this.totalPages = page.getTotalPages();
this.size = page.getSize();
this.content = page.getContent();
}
}
And receive within constructor the original Pageable.
You can customize your properties, these properties were used in my case.
After this, you can return the PageAdapter in your controller/resource.
if there is a better solution, I would like to know too.
A suggestion for you, spring can receive an instance of Pageable, so, you don't need to receive each parameter for size, page, order and etc.
Just do this:
public ResponseEntity<Page<Cidadao>> consultaPorNome(
#PathVariable(value="nome",required=true) String nome, Pageable pageable){
You will have all information about size, page, order...
I'm not a native English speaker, so, may contains grammar errors.

Resources