Spring 5: MVC controller argument pageable doesn't get initialised - spring

I have a controller like so:
#GetMapping(value = "/list")
#PreAuthorize("#authService.hasPermission('read')")
public Page<SomeObject> getlist(
#PageableDefault(page = 0, size = 10, sort = "id")
Pageable pageable,
#RequestHeader HttpHeaders headers) {
log.info(pageable.toString());
// Some code
}
Now when I hit this API endpoint with:
http://some-ip/list?pageNumber=1&pageSize=1
The pageable is not initialized with these values and I see the below log.
Page request [number: 0, size 10, sort: id: ASC]
I have tried manually accepting the page size and number and building the pageable myself, that seems to work just fine but the pageable argument in my controller doesn't seem to get initialized. I have no clue why.
I have seen this thread already but it doesn't work for me.

Related

how to pass Spring Pageable to FeignClient

as I wrote in this issue: https://github.com/spring-cloud/spring-cloud-openfeign/issues/375
and in this SO question:
Spring data Pageable does not work with feign client
I have some problems sending a Pageable object in a POST request containing a #requestbody element.
First I tried sending the Pageable embedded in my RequestBody since it was generated as example when using springdoc-openapi-webmvc-core.
Example:
#PostMapping("/search") public Page<HelloDto> searchHellos(#RequestBody HelloDto example, Pageable pageable)
{ "example": { "message": "string" }, "pageable": { "pageNumber": 0, "pageSize": 50, "offset": 10, "sort": { "sorted": false, }, "paged": true, } }
No I learned, that I can send it via Query parameter aswell and it will be parsed. The annotation that extracts the pageable into QueryParams is called org.springdoc.api.annotations.ParameterObject in SpringDoc.
#PostMapping("/search") public Page<HelloDto> searchHellos(#RequestBody HelloDto example, #ParameterObject Pageable pageable) { return helloCallerService.callHelloServiceClient(example, pageable); }
When I try to call a similar controller interface via feign like this client interface:
#PostMapping("/search") public Page<HelloDto> searchHellos(#RequestHeader("apiKey") String apiKey, #RequestBody HelloDto example, Pageable pageable);
The application won't start since the method "has too many body params".
I tried to annotate Pageable with #RequestParam but it won't be recognized / parsed.
My question is:
Can we use a custom AnnotatedParameterProcessor for e.g. #ParameterObject that flats out the ParameterObject and encodes it into the url query parameters?
How would you do that? Or is the AnnotatedParameterProcessor the wrong way? Do I maybe need an expander or anything?
Your question is more related to feign usage than springdoc-openapi.
Using using org.springframework.cloud.openfeign.SpringQueryMap, solves your problem.

Caching with Pagination on Spring Boot

I have an endpoint which fetches data from the database returns huge number of records. All of this records needs to be visible on the UI but as we scroll the view.
These records are used in 2 ways, one is displaying as it is another is displaying subset of the records based on some filter (through same/another endpoint).
Any suggestions on how this can be achieved using Spring features or without ?
You can achieve this using pageable. Sample controller code for pageable
#PostMapping
#ResponseStatus(HttpStatus.OK)
public Page<AllInventoryTransactions> fetchAllInwardInventory(#PageableDefault(page = 0, size = 10, sort = "created", direction = Direction.DESC) Pageable pageable) throws Exception
{
return allInventoryService.fetchAllInventory(pageable);
}
You can pass this pageable received from UI directly to Repo. Below is the service method
public Page<AllInventoryTransactions> fetchAllInventory(FilterDataList filterDataList, Pageable pageable) throws ParseException
{
Page<AllInventoryTransactions> data = allInventoryRepo.findAll(spec,pageable);
allInventoryReturnData.setTransactions(data);
return data;
}
in UI, you can handle logic to make next API call as user scrolls the page

Is there a way to restrict Pageable's size and page values passed to controller method by Spring?

I am using following controller method
public String listUsers(#PageableDefault(size = 20, page = 0) Pageable pageable)
And obviously, we can controll page and size with query params size and page. But lets say, we want to protect ourselfs from dumping whole database in one page by user or due to tempering. Is there a limit, that can be set to Pageable object eg. #DefaultPageableConstrains or I have to validate size by hand?
I just would like to make use of Spring validation mechanisms like #Valid #Min or #Max annotations.
The default maxPageSize is 2000. This can be overriden like so:
#Configuration
public class PaginationConfiguration extends SpringDataWebConfiguration {
private final int MAX_PAGE_SIZE = 200;
#Bean
#Override
public PageableHandlerMethodArgumentResolver pageableResolver() {
PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver =
new PageableHandlerMethodArgumentResolver(sortResolver());
pageableHandlerMethodArgumentResolver.setMaxPageSize(MAX_PAGE_SIZE);
return pageableHandlerMethodArgumentResolver;
}
}

Spring Boot: #RequestMapping Priority

My Spring Boot application encountered a problem as follows:
I have two #RequestMapping:
#RequestMapping(value = "/{categorySlug:^[a-z0-9-]+$}/{slug:^[a-z0-9-]+$}")
public ModelAndView aTutorial(
#PathVariable(value = "categorySlug", required = false) String categorySlug,
#PathVariable(value = "slug") String slug) {
// (1)
}
and
#RequestMapping(value = "/questions/**")
public ModelAndView fix404() {
// (2)
}
I used (2) to redirect the 404 pages to homepage.
but when I go to the url like: https://w3stacks.com/questions/fix, i want it to (2) but it requests processed in (1), by /questions/fix coincides with {categorySlug)/{slug}.
So how do to it on (2), or in other words, can customize the priority between #RequestMapping or not?
Thanks.
You can ignore the questions word for categorySlug of aTutorial API.
Something like;
#RequestMapping(value = "/{categorySlug:^(?!questions)[a-z0-9-]+$}/{slug:^[a-z0-9-]+$}")
With that, you wouldn't get any call that starts with questions in aTutorial API like /questions/etc, but would also ignore /questionsCategory/etc
Hence fix404 endpoint will be utilized properly as you have desired.

How to pass String array in #RequestParam in REST GET API call through POSTMAN or DHC REST application?

I have following REST controller in Java Spring Application:
#RequestMapping(
value = "/api/getApplication/{me_userId}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public Object getApplication(
#PathVariable String userId,
#RequestParam(value="fieldNames[]", required = false) String[] fieldNames) {
if (fieldNames != null) {
for (String fieldName : fieldNames)
System.out.println(fieldName);
}
...
return null;
}
So I can not succeed in simulating API call from DHC REST of POSTMAN what will pass that fieldNames[].
Does anyone know how to do it?
First of all, your current method does not work because your #PathVariable is wrong. In your #RequestMapping you have the following placeholder in your path: {me_userId}, which means that it will be mapped to a path variable with that name.
However, the only #PathVariable you have is nameless, which means it will use the name of the parameter (userId) in stead.
So before you try to execute your request, you have to change your #RequestMapping into:
#RequestMapping(
value = "/api/getApplication/{userId}", // <-- it's now {userId}
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
Then, if you run the application, you can kinda choose how you want to pass your parameters. Both the following will work:
?fieldNames[]=test,test2
Or:
?fieldNames[]=test&fieldNames[]=test2
Both these results should print the desired results.

Resources