diff --git a/chat-client-java/src/main/java/cz/muni/chat/client/Main.java b/chat-client-java/src/main/java/cz/muni/chat/client/Main.java index 52fc3ec..3f90ddf 100644 --- a/chat-client-java/src/main/java/cz/muni/chat/client/Main.java +++ b/chat-client-java/src/main/java/cz/muni/chat/client/Main.java @@ -57,8 +57,14 @@ public void run(String... args) throws Exception { chat.createMessage(new NewChatMessageRequest().text("Message num " + i), "robot", null); } //get paged messages - PageChatMessage paged = chat.paged(1, 3, null); - log.info("paged messages:"); + int pageIndex = 2; + int pageSize = 3; + PageChatMessage paged = chat.paged(pageIndex, pageSize, null); + log.info("paged messages: page={}/{} offset={} items={}/{} total={}", + paged.getNumber() + 1, paged.getTotalPages(), + paged.getPageable().getOffset(), + paged.getNumberOfElements(), paged.getSize(), + paged.getTotalElements()); for (ChatMessage chatMessage : paged.getContent()) { log.info("msg: {}", chatMessage); } diff --git a/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java b/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java index 5ef5b5f..59b4192 100644 --- a/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java +++ b/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java @@ -24,7 +24,6 @@ import org.springdoc.core.annotations.ParameterObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -174,14 +173,7 @@ public ChatMessage createMessage(@Valid @RequestBody NewChatMessageRequest r, @GetMapping(path = "/paged", produces = MediaType.APPLICATION_JSON_VALUE) @CrossOrigin(origins = "*") public Page paged(@ParameterObject Pageable pageable) { - log.debug("/paged: pageable = {} offset = {}", pageable, pageable.getOffset()); - List msgs = chatService.getAllChatMessages(); - long total = msgs.size(); - List chatMessages = msgs.stream() - .skip(pageable.getOffset()) - .limit(pageable.getPageSize()) - .map(ChatMessage::fromStoredMessage).toList(); - return new PageImpl<>(chatMessages, pageable, total); + return chatService.getPageOfMessages(pageable).map(ChatMessage::fromStoredMessage); } } diff --git a/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java b/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java index 853d748..c5a1aaf 100644 --- a/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java +++ b/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java @@ -1,5 +1,8 @@ package cz.muni.chat.server.service; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + import java.util.List; public interface ChatService { @@ -9,4 +12,6 @@ public interface ChatService { StoredMessage createNewChatMessage(String text, String author, String textColor, String backgroundColor); StoredMessage getMessage(String id); + + Page getPageOfMessages(Pageable pageable); } diff --git a/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java b/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java index 60e908c..18912d2 100644 --- a/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java +++ b/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java @@ -3,8 +3,11 @@ import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import org.springframework.util.comparator.Comparators; import java.time.ZonedDateTime; import java.util.List; @@ -42,4 +45,24 @@ public StoredMessage createNewChatMessage(String text, String author, String tex public StoredMessage getMessage(String id) { return messages.stream().filter(x -> x.id().equals(id)).findFirst().orElse(null); } + + @Override + public Page getPageOfMessages(Pageable pageable) { + // In practice Pageable object is propagated into Spring Data repositories and transformed + // into LIMIT, OFFSET, and ORDER BY keywords in SQL queries, so the pagination is + // performed efficiently by the database engine when reading data from disk, + // which is the most time-consuming part of getting data. + // + // In this simple example, there is no persistence layer, so the following code gets all messages + // and then filters them in memory. That would be highly inefficient when using a real database. + // DO NOT perform pagination at the service level, do it at the persistence level! + List msgs = messages.stream() + .skip(pageable.getOffset()) + .limit(pageable.getPageSize()) + .toList(); + Page page = new PageImpl<>(msgs, pageable, messages.size()); + log.debug("pageable = {}", pageable); + log.debug("page: {}", page); + return page; + } }