Caching with Pagination on Spring Boot - spring

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

Related

Spring Data returns deleted object sometimes

I am working by spring data to access database and do not use any cache. I have a problem that after deleting a record from database, I am sending an event to other micro system to re-query to update list of objects. So basically my code is :
private void deleteObject(MyObject object) {
myRepository.deleteById(object.getId());
myRepository.flush();
...
sendEventToSystemX();
}
Basically other micro service captures the event which is sent by sendEventToSystemX method and make a query to myRepository.
#Transactional(isolation = Isolation.READ_UNCOMMITTED, readOnly = true)
public Page<T> findAll(Specification<T> spec, Pageable pageable) {
TypedQuery<T> query = getQuery(spec, getDomainClass(), pageable.getSort());
if(pagable.isUnpaged()) {
return new PageImpl<>(query.getResultList())
}
return readPage(query, getDomainClass(), pageable, spec);
}
So note that I am flushing repo after deletion. And select query is done by different service so it is not in the same transaction. So why I still get deleted object for the first time I query after deletion. If I re-run findAll method then I get up-to data result. And this also does not happen always. So what can be reason behind it ?

Is there a way to map a Retrofit #QueryMap to some object for a Spring Rest Service?

The client interface looks like this
#GET("v3/users/posts")
Call<User> loadPosts(#QueryMap Map<String,String> data);
The RestController should then process the map of query data returning the user's post. There are multiple parameters that can be put in the map as shown in the UserService.findUserPosts(). Is it possible to use a map to pass data to the Spring Rest controller? The restriction I have is this is inherited from code using #Query parameters but it has now grown to quite a number and a query map would limit the changes on the client. I would be really grateful for some feedback. Many thanks
#RestController
public class UsersController{
#RequestMapping(value = "/user/posts", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> getUserPosts(.......What here) {
List<Posts> posts = userService.findPostsBy(id,postKey,offset,when);
}
Solved it. For anyone in the future who wants to do what I am doing , simply provide Request parameters for every key pair in the map
i.e #RequestParam("id") String id,
#RequestParam("postKey") Long, #RequestParam("offset") etc.

Spring&Hibernate paggination

i want to make pagination for my site (current just practice)
I using Spring and Hibernate. I understand that i can use Critera to retrive example 5 by 5 Person name. But how to send that to JSP page and make pagination.
You can use Spring Data for this:
interface BookRepository extends JpaRepository<Book, Integer> {
}
#RestController
class BookController {
#Autowired
BookRepository bookRepository;
#GetMapping("/books")
public Page<Book> getAllBooks(Pageable pageable){
return bookRepository.findAll(pageable);
}
}
By adding Pageable to controller method Spring adds three request parameters: page, size and sort. And request will look like: curl 'http://localhost:8080/books?page=0&size=20&sort=title%2Cdesc'
Spring automatically will create that Pageable object.
Spring Data can work with this object and returns Page<T> in response, which contains among requested entities (in content array) a lot of pagination information such as totalPages, numberOfElements.

Spring Pageable in handler

I have a handler like this:
#GetMapping("/users")
#Timed
public ResponseEntity<List<UserDTO>> getAllUsers(#ApiParam Pageable pageable) {
log.debug("REST request to get a page of Users");
Page<UserDTO> page = userService.findAll(pageable);
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/users");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
It was generated by JHipster. My main issue with this is that i dont understand what the front end is supposed to send to match Pageable object.
This handler will should return paginated users based on search words submitted by the user. I am using mongodb.
Based on this github issue it states
The custom pagable parameters (limit, offset) are replaced to the
Spring custom argument resolver PageableHandlerMethodArgumentResolver
You can find the code for PageableHandlerMethodArgumentResolver here. The default parameter names are "page" and "size". You might want to take a look at the jhipster-sample-app-mongodb which does look to showcase pagination. Example can be found here

Incompatible types List and Page

I am developing a webapp using JHipster that manages payments and wanted to filter the payments that a user can see so he can only see his payments. To do this I was following the blog tutorial from Matt Raible on Youtube. He uses findByUserIsCurrentUser() which is generated by JHipster.
List<Blog> blogs = blogRepository.findByUserIsCurrentUser();
When I went to make the same change in my project I found the type that I must return is a Page and I get an incompatible type error, here is my method:
public Page<Payment> findAll(Pageable pageable) {
log.debug("Request to get all Payments");
Page<Payment> result = paymentRepository.findByUserIsCurrentUser();
return result;
}
If I change the findAll(pageable) for findByUserIsCurrentUser() which is declared in the PaymentRepository as follows
public interface PaymentRepository extends JpaRepository<Payment,Long> {
#Query("select payment from Payment payment where payment.user.login = ?#{principal.username}")
List<Payment> findByUserIsCurrentUser();
}
I get the following error:
How can I solve this?
You can fix this in two ways. This is assuming you are using a service, if not it's still pretty similar:
Method 1: If you want your service to return ALL payments for the current user, then you need to modify your service and probably your resource to handle a list instead of a page:
public List<Payment> findAll() {
log.debug("Request to get all Payments");
List<Payment> result = paymentRepository.findByUserIsCurrentUser();
return result;
}
And in your resource:
public List<Payment> getAllPayments() {
log.debug("REST request to get all Payments");
List<Payment> payments = paymentService.findAll();
return payments;
}
Alternatively, you can change "pagination": "pagination" to "pagination": "no" in .jhipster/Payment.json and rerun the generator. This will regenerate the service, resource and repository without pagination.
Method 2: If you want your service to be paginated, you need to change your repository method to accept the Pageable object, and return a page:
public interface PaymentRepository extends JpaRepository<Payment,Long> {
#Query("select payment from Payment payment where payment.user.login = ?#{principal.username}")
Page<Payment> findByUserIsCurrentUser(Pageable pageable);
}
Then you need to pass the pageable object in from your service:
public Page<Payment> findAll(Pageable pageable) {
log.debug("Request to get all Payments");
Page<Payment> result = paymentRepository.findByUserIsCurrentUser(pageable);
return result;
}
This will return a subset of results, based on whatever the pageable object contains. This includes size, page number, offset, and sorting. For example, a size of 20 and a page number of 0 will return the first 20 results. Changing the page number to 1 will return the next 20 results. These parameters are generally passed in from the front end to your API - you will notice that getAllPayments() in PaymentResource has a Pageable parameter.

Resources