Skip to content

Commit

Permalink
Replace Page<> with Slice<> for pagination operations
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-punko committed Dec 27, 2023
1 parent da0bbee commit 914a58f
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 36 deletions.
9 changes: 3 additions & 6 deletions src/main/java/by/andd3dfx/controllers/ArticleController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.util.List;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.data.web.SortDefault;
Expand All @@ -27,7 +25,6 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

Expand Down Expand Up @@ -102,7 +99,7 @@ public void deleteArticle(
articleService.delete(id);
}

@ApiOperation(value = "Read articles paged", response = Page.class)
@ApiOperation(value = "Read articles paged", response = Slice.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Articles successfully retrieved"),
@ApiResponse(code = 401, message = "You are not authorized to view the resource")
Expand All @@ -120,7 +117,7 @@ public void deleteArticle(
"Multiple sort criteria are supported.",
defaultValue = "title,ASC")
})
public Page<ArticleDto> readArticlesPaged(
public Slice<ArticleDto> readArticlesPaged(
@PageableDefault(page = 0, size = 50)
@SortDefault.SortDefaults({
@SortDefault(sort = "title", direction = Sort.Direction.ASC)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package by.andd3dfx.persistence.dao;

import by.andd3dfx.persistence.entities.Article;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ArticleRepository extends PagingAndSortingRepository<Article, Long>,
CrudRepository<Article, Long>, ArticleRepositoryCustom {
public interface ArticleRepository extends CrudRepository<Article, Long>, ArticleRepositoryCustom {

Slice<Article> findAll(Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

import by.andd3dfx.persistence.entities.LoggedRecord;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface LoggingRepository extends PagingAndSortingRepository<LoggedRecord, Long>,
public interface LoggingRepository extends
CrudRepository<LoggedRecord, Long>, LoggingRepositoryCustom {

}
4 changes: 2 additions & 2 deletions src/main/java/by/andd3dfx/services/IArticleService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import by.andd3dfx.dto.ArticleDto;
import by.andd3dfx.dto.ArticleUpdateDto;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

public interface IArticleService {

Expand All @@ -18,5 +18,5 @@ public interface IArticleService {

List<ArticleDto> getAll(Integer pageNo, Integer pageSize, String sortBy);

Page<ArticleDto> getAll(Pageable pageable);
Slice<ArticleDto> getAll(Pageable pageable);
}
9 changes: 4 additions & 5 deletions src/main/java/by/andd3dfx/services/impl/ArticleService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
import by.andd3dfx.persistence.entities.Article;
import by.andd3dfx.services.IArticleService;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -69,14 +68,14 @@ public void delete(Long id) {
@Override
public List<ArticleDto> getAll(Integer pageNo, Integer pageSize, String sortBy) {
Pageable pageRequest = PageRequest.of(pageNo, pageSize, Sort.by(sortBy));
Page<Article> pagedResult = articleRepository.findAll(pageRequest);
Slice<Article> pagedResult = articleRepository.findAll(pageRequest);
return articleMapper.toArticleDtoList(pagedResult.getContent());
}

@Transactional(readOnly = true)
@Override
public Page<ArticleDto> getAll(Pageable pageable) {
final Page<Article> pagedResult = articleRepository.findAll(pageable);
public Slice<ArticleDto> getAll(Pageable pageable) {
Slice<Article> pagedResult = articleRepository.findAll(pageable);
return pagedResult.map(articleMapper::toArticleDto);
}
}
2 changes: 1 addition & 1 deletion src/main/java/by/andd3dfx/services/impl/AuthorService.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ public AuthorDto get(Long id) {
public List<AuthorDto> getAll() {
return StreamSupport.stream(authorRepository.findAll().spliterator(), false)
.map(authorMapper::toAuthorDto)
.collect(Collectors.toList());
.toList();
}
}
4 changes: 3 additions & 1 deletion src/main/java/by/andd3dfx/services/impl/LoggingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ public void logMethodCall(Method method, Object[] args, Object result, boolean i
}

private MethodCallRecord buildMethodCallRecord(Method method, Object[] args, Object result, boolean isSucceed) {
List<String> paramNames = Arrays.stream(method.getParameters()).map(Parameter::getName).collect(Collectors.toList());
List<String> paramNames = Arrays.stream(method.getParameters())
.map(Parameter::getName)
.toList();
if (paramNames.size() != args.length) {
throw new IllegalArgumentException("Parameter names amount differ from args amount!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.domain.Pageable;

@ExtendWith(MockitoExtension.class)
@DataJpaTest
Expand Down Expand Up @@ -153,7 +154,7 @@ public void deleteByCriteriaForEmptyCriteria() {
assertTrue(repository.findByCriteria(new ArticleSearchCriteria()).isEmpty());
}

private Article buildArticle(String title, String summary, LocalDateTime timestamp) {
public static Article buildArticle(String title, String summary, LocalDateTime timestamp) {
Article article = new Article();
article.setTitle(title);
article.setSummary(summary);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package by.andd3dfx.persistence.dao;

import by.andd3dfx.persistence.entities.Article;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import static by.andd3dfx.persistence.dao.ArticleRepositoryCustomImplTest.buildArticle;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;

@ExtendWith(MockitoExtension.class)
@DataJpaTest
class ArticleRepositoryTest {

@Autowired
private ArticleRepository repository;

private Article entity;
private Article entity2;
private Article entity3;

@BeforeEach
public void setup() {
repository.deleteAll();
entity = buildArticle("Ivan", "HD", LocalDateTime.parse("2010-12-03T10:15:30"));
entity2 = buildArticle("Vasily", "HD", LocalDateTime.parse("2011-12-03T10:15:30"));
entity3 = buildArticle("Ivan", "4K", LocalDateTime.parse("2012-12-03T10:15:30"));
repository.saveAll(Arrays.asList(entity, entity2, entity3));
}

@AfterEach
public void tearDown() {
repository.deleteAll();
}

@Test
public void findAll() {
var result = repository.findAll(Pageable.ofSize(10));

assertThat("Wrong records amount", result.getNumberOfElements(), is(3));
assertTrue(result.getContent().containsAll(List.of(entity, entity2, entity3)));
}

@Test
public void findAll_withPageNSizeNSorting() {
var result = repository.findAll(PageRequest.of(0, 2, Sort.by("title", "summary")));

assertThat("Wrong records amount", result.getNumberOfElements(), is(2));
var articles = result.getContent();
assertThat(articles.get(0), is(entity3));
assertThat(articles.get(1), is(entity));
}
}
9 changes: 4 additions & 5 deletions src/test/java/by/andd3dfx/services/ArticleServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -176,7 +175,7 @@ void getAll() {
final Pageable pageRequest = PageRequest.of(pageNo, pageSize, Sort.by(sortBy));

final List<Article> articles = Arrays.asList(new Article());
final Page<Article> pagedResult = new PageImpl<>(articles, pageRequest, articles.size());
final Slice<Article> pagedResult = new PageImpl<>(articles, pageRequest, articles.size());
final List<ArticleDto> articleDtoList = Arrays.asList(new ArticleDto());

Mockito.doReturn(pagedResult).when(articleRepositoryMock).findAll(pageRequest);
Expand All @@ -197,13 +196,13 @@ void getAllPaged() {
final Pageable pageRequest = PageRequest.of(pageNo, pageSize, Sort.by(sortBy));

final List<Article> articles = Arrays.asList(new Article());
final Page<Article> pagedResult = new PageImpl<>(articles, pageRequest, articles.size());
final Slice<Article> pagedResult = new PageImpl<>(articles, pageRequest, articles.size());
final List<ArticleDto> articleDtoList = Arrays.asList(new ArticleDto());

Mockito.doReturn(pagedResult).when(articleRepositoryMock).findAll(pageRequest);
Mockito.doReturn(articleDtoList.get(0)).when(articleMapperMock).toArticleDto(articles.get(0));

Page<ArticleDto> result = articleService.getAll(pageRequest);
Slice<ArticleDto> result = articleService.getAll(pageRequest);

Mockito.verify(articleRepositoryMock).findAll(pageRequest);
Mockito.verify(articleMapperMock).toArticleDto(articles.get(0));
Expand Down
19 changes: 9 additions & 10 deletions src/test/java/by/andd3dfx/util/MemoryAppender.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,45 @@
import ch.qos.logback.core.read.ListAppender;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* Class for testing purposes to catch logs.
*/
public class MemoryAppender extends ListAppender<ILoggingEvent> {
public void reset() {
this.list.clear();
list.clear();
}

public boolean contains(String string, Level level) {
return this.list.stream()
return list.stream()
.anyMatch(event -> event.getMessage().toString().contains(string)
&& event.getLevel().equals(level));
}

public int countEventsForLogger(String loggerName) {
return (int) this.list.stream()
return (int) list.stream()
.filter(event -> event.getLoggerName().contains(loggerName))
.count();
}

public List<ILoggingEvent> search(String string) {
return this.list.stream()
return list.stream()
.filter(event -> event.getMessage().toString().contains(string))
.collect(Collectors.toList());
.toList();
}

public List<ILoggingEvent> search(String string, Level level) {
return this.list.stream()
return list.stream()
.filter(event -> event.getMessage().toString().contains(string)
&& event.getLevel().equals(level))
.collect(Collectors.toList());
.toList();
}

public int getSize() {
return this.list.size();
return list.size();
}

public List<ILoggingEvent> getLoggedEvents() {
return Collections.unmodifiableList(this.list);
return Collections.unmodifiableList(list);
}
}

0 comments on commit 914a58f

Please sign in to comment.