moved Rest Pagination article code from spring-rest-full to spring-boot-rest

This commit is contained in:
Ger Roza
2019-01-20 18:19:52 -02:00
parent 5d6640a87b
commit 14b65b327f
48 changed files with 1125 additions and 164 deletions
@@ -3,8 +3,6 @@ package org.baeldung.persistence;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Page;
public interface IOperations<T extends Serializable> {
// read - one
@@ -15,8 +13,6 @@ public interface IOperations<T extends Serializable> {
List<T> findAll();
Page<T> findPaginated(int page, int size);
// write
T create(final T entity);
@@ -2,13 +2,9 @@ package org.baeldung.persistence.service;
import org.baeldung.persistence.IOperations;
import org.baeldung.persistence.model.Foo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface IFooService extends IOperations<Foo> {
Foo retrieveByName(String name);
Page<Foo> findPaginated(Pageable pageable);
}
@@ -4,8 +4,6 @@ import java.io.Serializable;
import java.util.List;
import org.baeldung.persistence.IOperations;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;
@@ -30,11 +28,6 @@ public abstract class AbstractService<T extends Serializable> implements IOperat
return Lists.newArrayList(getDao().findAll());
}
@Override
public Page<T> findPaginated(final int page, final int size) {
return getDao().findAll(new PageRequest(page, size));
}
// write
@Override
@@ -7,8 +7,6 @@ import org.baeldung.persistence.model.Foo;
import org.baeldung.persistence.service.IFooService;
import org.baeldung.persistence.service.common.AbstractService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -48,9 +46,4 @@ public class FooService extends AbstractService<Foo> implements IFooService {
return Lists.newArrayList(getDao().findAll());
}
@Override
public Page<Foo> findPaginated(Pageable pageable) {
return dao.findAll(pageable);
}
}
@@ -6,27 +6,20 @@ import javax.servlet.http.HttpServletResponse;
import org.baeldung.persistence.model.Foo;
import org.baeldung.persistence.service.IFooService;
import org.baeldung.web.exception.MyResourceNotFoundException;
import org.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
import org.baeldung.web.hateoas.event.ResourceCreatedEvent;
import org.baeldung.web.hateoas.event.SingleResourceRetrievedEvent;
import org.baeldung.web.util.RestPreconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.base.Preconditions;
@@ -72,30 +65,6 @@ public class FooController {
return service.findAll();
}
@RequestMapping(params = { "page", "size" }, method = RequestMethod.GET)
@ResponseBody
public List<Foo> findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
final Page<Foo> resultPage = service.findPaginated(page, size);
if (page > resultPage.getTotalPages()) {
throw new MyResourceNotFoundException();
}
eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent<Foo>(Foo.class, uriBuilder, response, page, resultPage.getTotalPages(), size));
return resultPage.getContent();
}
@GetMapping("/pageable")
@ResponseBody
public List<Foo> findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
final Page<Foo> resultPage = service.findPaginated(pageable);
if (pageable.getPageNumber() > resultPage.getTotalPages()) {
throw new MyResourceNotFoundException();
}
eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent<Foo>(Foo.class, uriBuilder, response, pageable.getPageNumber(), resultPage.getTotalPages(), pageable.getPageSize()));
return resultPage.getContent();
}
// write
@RequestMapping(method = RequestMethod.POST)
@@ -1,67 +0,0 @@
package org.baeldung.web.hateoas.event;
import java.io.Serializable;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationEvent;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Event that is fired when a paginated search is performed.
* <p/>
* This event object contains all the information needed to create the URL for the paginated results
*
* @param <T>
* Type of the result that is being handled (commonly Entities).
*/
public final class PaginatedResultsRetrievedEvent<T extends Serializable> extends ApplicationEvent {
private final UriComponentsBuilder uriBuilder;
private final HttpServletResponse response;
private final int page;
private final int totalPages;
private final int pageSize;
public PaginatedResultsRetrievedEvent(final Class<T> clazz, final UriComponentsBuilder uriBuilderToSet, final HttpServletResponse responseToSet, final int pageToSet, final int totalPagesToSet, final int pageSizeToSet) {
super(clazz);
uriBuilder = uriBuilderToSet;
response = responseToSet;
page = pageToSet;
totalPages = totalPagesToSet;
pageSize = pageSizeToSet;
}
// API
public final UriComponentsBuilder getUriBuilder() {
return uriBuilder;
}
public final HttpServletResponse getResponse() {
return response;
}
public final int getPage() {
return page;
}
public final int getTotalPages() {
return totalPages;
}
public final int getPageSize() {
return pageSize;
}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
@SuppressWarnings("unchecked")
public final Class<T> getClazz() {
return (Class<T>) getSource();
}
}
@@ -1,108 +0,0 @@
package org.baeldung.web.hateoas.listener;
import javax.servlet.http.HttpServletResponse;
import org.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
import org.baeldung.web.util.LinkUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.base.Preconditions;
import com.google.common.net.HttpHeaders;
@SuppressWarnings({ "rawtypes" })
@Component
class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationListener<PaginatedResultsRetrievedEvent> {
private static final String PAGE = "page";
public PaginatedResultsRetrievedDiscoverabilityListener() {
super();
}
// API
@Override
public final void onApplicationEvent(final PaginatedResultsRetrievedEvent ev) {
Preconditions.checkNotNull(ev);
addLinkHeaderOnPagedResourceRetrieval(ev.getUriBuilder(), ev.getResponse(), ev.getClazz(), ev.getPage(), ev.getTotalPages(), ev.getPageSize());
}
// - note: at this point, the URI is transformed into plural (added `s`) in a hardcoded way - this will change in the future
final void addLinkHeaderOnPagedResourceRetrieval(final UriComponentsBuilder uriBuilder, final HttpServletResponse response, final Class clazz, final int page, final int totalPages, final int pageSize) {
plural(uriBuilder, clazz);
final StringBuilder linkHeader = new StringBuilder();
if (hasNextPage(page, totalPages)) {
final String uriForNextPage = constructNextPageUri(uriBuilder, page, pageSize);
linkHeader.append(LinkUtil.createLinkHeader(uriForNextPage, LinkUtil.REL_NEXT));
}
if (hasPreviousPage(page)) {
final String uriForPrevPage = constructPrevPageUri(uriBuilder, page, pageSize);
appendCommaIfNecessary(linkHeader);
linkHeader.append(LinkUtil.createLinkHeader(uriForPrevPage, LinkUtil.REL_PREV));
}
if (hasFirstPage(page)) {
final String uriForFirstPage = constructFirstPageUri(uriBuilder, pageSize);
appendCommaIfNecessary(linkHeader);
linkHeader.append(LinkUtil.createLinkHeader(uriForFirstPage, LinkUtil.REL_FIRST));
}
if (hasLastPage(page, totalPages)) {
final String uriForLastPage = constructLastPageUri(uriBuilder, totalPages, pageSize);
appendCommaIfNecessary(linkHeader);
linkHeader.append(LinkUtil.createLinkHeader(uriForLastPage, LinkUtil.REL_LAST));
}
if (linkHeader.length() > 0) {
response.addHeader(HttpHeaders.LINK, linkHeader.toString());
}
}
final String constructNextPageUri(final UriComponentsBuilder uriBuilder, final int page, final int size) {
return uriBuilder.replaceQueryParam(PAGE, page + 1).replaceQueryParam("size", size).build().encode().toUriString();
}
final String constructPrevPageUri(final UriComponentsBuilder uriBuilder, final int page, final int size) {
return uriBuilder.replaceQueryParam(PAGE, page - 1).replaceQueryParam("size", size).build().encode().toUriString();
}
final String constructFirstPageUri(final UriComponentsBuilder uriBuilder, final int size) {
return uriBuilder.replaceQueryParam(PAGE, 0).replaceQueryParam("size", size).build().encode().toUriString();
}
final String constructLastPageUri(final UriComponentsBuilder uriBuilder, final int totalPages, final int size) {
return uriBuilder.replaceQueryParam(PAGE, totalPages).replaceQueryParam("size", size).build().encode().toUriString();
}
final boolean hasNextPage(final int page, final int totalPages) {
return page < (totalPages - 1);
}
final boolean hasPreviousPage(final int page) {
return page > 0;
}
final boolean hasFirstPage(final int page) {
return hasPreviousPage(page);
}
final boolean hasLastPage(final int page, final int totalPages) {
return (totalPages > 1) && hasNextPage(page, totalPages);
}
final void appendCommaIfNecessary(final StringBuilder linkHeader) {
if (linkHeader.length() > 0) {
linkHeader.append(", ");
}
}
// template
protected void plural(final UriComponentsBuilder uriBuilder, final Class clazz) {
final String resourceName = clazz.getSimpleName().toLowerCase() + "s";
uriBuilder.path("/auth/" + resourceName);
}
}
@@ -1,8 +1,9 @@
package org.baeldung.web.util;
import org.baeldung.web.exception.MyResourceNotFoundException;
import org.springframework.http.HttpStatus;
import org.baeldung.web.exception.MyResourceNotFoundException;
/**
* Simple static methods to be called at the start of your own methods to verify correct arguments and state. If the Precondition fails, an {@link HttpStatus} code is thrown
*/