From 9d62c13670c075768636ef7f9621c027c8019af3 Mon Sep 17 00:00:00 2001 From: Martin Kuba Date: Thu, 26 Jan 2023 18:40:24 +0100 Subject: [PATCH] added generated server --- README.md | 3 +- chat-server-generated/pom.xml | 120 ++++++++++++++++++ .../chat/generated/server/api/ChatImpl.java | 102 +++++++++++++++ .../src/main/resources/application.properties | 3 + .../generated/server/GeneratedServerIT.java | 84 ++++++++++++ .../src/test/resources/application.properties | 6 + .../src/test/resources/logback.xml | 14 ++ .../java/cz/muni/chat/server/rest/ChatIT.java | 8 +- pom.xml | 1 + 9 files changed, 335 insertions(+), 6 deletions(-) create mode 100644 chat-server-generated/pom.xml create mode 100644 chat-server-generated/src/main/java/cz/muni/chat/generated/server/api/ChatImpl.java create mode 100644 chat-server-generated/src/main/resources/application.properties create mode 100644 chat-server-generated/src/test/java/cz/muni/chat/generated/server/GeneratedServerIT.java create mode 100644 chat-server-generated/src/test/resources/application.properties create mode 100644 chat-server-generated/src/test/resources/logback.xml diff --git a/README.md b/README.md index 419192b..be7ad2f 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ This project demonstrates the following features: * a multimodule Maven project * parent project [chat-service-parent](pom.xml) and multiple modules: * module [chat-server](chat-server/pom.xml) - executable server - * module [chat-client-java-lib](chat-client-java-lib/pom.xml) - Java library generated by OpenAPI Generator + * module [chat-client-java-lib](chat-client-java-lib/pom.xml) - Java client library generated by OpenAPI Generator "java" * module [chat-client-java](chat-client-java/pom.xml) - executable client using the library + * module [chat-server-generated](chat-server-generated/pom.xml) - executable server generated by OpenAPI Generator "spring" * module aggregation, where a command executed in the parent project gets executed also in all modules * module inheritance, where the parent project inherits from `org.springframework.boot:spring-boot-starter-parent` and each module inherits from the parent diff --git a/chat-server-generated/pom.xml b/chat-server-generated/pom.xml new file mode 100644 index 0000000..0e018b7 --- /dev/null +++ b/chat-server-generated/pom.xml @@ -0,0 +1,120 @@ + + + 4.0.0 + + cz.muni.chat + chat-service-parent + 0.0.0-SNAPSHOT + + + chat-server-generated + jar + Generated server + Server generated by OpenAPI Generator + + + spring-boot:run + + chat_server_generated + + + + org.openapitools + openapi-generator-maven-plugin + 6.2.1 + + + + generate + + + ${project.basedir}/../openapi.yaml + spring + cz.muni.chat.generated.server.api + cz.muni.chat.generated.server.model + + + cz.muni.chat.generated.server + cz.muni.chat.generated.server.config + true + true + true + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + + + + 0.2.4 + 2.2.7 + 2.0.1.Final + + + + + org.springframework.boot + spring-boot-starter-web + + + jakarta.annotation + jakarta.annotation-api + + + jakarta.validation + jakarta.validation-api + + + io.swagger.core.v3 + swagger-models-jakarta + ${swagger-jakarta-version} + + + io.swagger.core.v3 + swagger-annotations-jakarta + ${swagger-jakarta-version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + + javax.validation + validation-api + ${javax-validation-api-version} + + + + + org.springframework.data + spring-data-commons + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + \ No newline at end of file diff --git a/chat-server-generated/src/main/java/cz/muni/chat/generated/server/api/ChatImpl.java b/chat-server-generated/src/main/java/cz/muni/chat/generated/server/api/ChatImpl.java new file mode 100644 index 0000000..74ef0c9 --- /dev/null +++ b/chat-server-generated/src/main/java/cz/muni/chat/generated/server/api/ChatImpl.java @@ -0,0 +1,102 @@ +package cz.muni.chat.generated.server.api; + +import cz.muni.chat.generated.server.model.BackgroundColorEnum; +import cz.muni.chat.generated.server.model.ChatMessage; +import cz.muni.chat.generated.server.model.NewChatMessageRequest; +import cz.muni.chat.generated.server.model.NewChatMessageRequest.TextColorEnum; +import cz.muni.chat.generated.server.model.PageChatMessage; +import cz.muni.chat.generated.server.model.PageableObject; +import cz.muni.chat.generated.server.model.SortObject; +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.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Implementation of API methods for generated controller. + */ +@Component +public class ChatImpl implements ChatApiDelegate { + + private static final Logger log = LoggerFactory.getLogger(ChatImpl.class); + + @Override + public ResponseEntity> getAllMessages() { + log.debug("getAllMessages()"); + return new ResponseEntity<>(messages, HttpStatus.OK); + } + + @Override + public ResponseEntity getMessage(String id) { + log.debug("getMessage({})", id); + ChatMessage chatMessage = messages.stream().filter(x -> x.getId().equals(id)).findFirst().orElse(null); + return new ResponseEntity<>(chatMessage, chatMessage != null ? HttpStatus.OK : HttpStatus.NOT_FOUND); + } + + @Override + public ResponseEntity createMessage(NewChatMessageRequest r, String author, String userAgent) { + log.debug("createMessage({},{},{})", r, author, userAgent); + String text = r.getText(); + BackgroundColorEnum backgroundColor = r.getBackgroundColor(); + TextColorEnum textColor = r.getTextColor(); + ChatMessage chatMessage = new ChatMessage() + .id(UUID.randomUUID().toString()) + .timestamp(OffsetDateTime.now()) + .author(author) + .text(text) + .textColor(textColor.getValue()) + .backgroundColor(backgroundColor); + messages.add(0, chatMessage); + return new ResponseEntity<>(chatMessage, HttpStatus.CREATED); + } + + @Override + public ResponseEntity paged(Integer page, Integer size, List sort) { + log.debug("paged(page={}, size={}, sort={})", page, size, sort); + PageRequest p = PageRequest.of(page, size); + List chatMessages = messages.stream().skip(p.getOffset()).limit(p.getPageSize()).toList(); + Page m = new PageImpl<>(chatMessages, p, messages.size()); + + // copy to generated models :-( + SortObject s = new SortObject() + .sorted(p.getSort().isSorted()) + .unsorted(p.getSort().isUnsorted()) + .empty(p.getSort().isEmpty()) + ; + PageableObject pageableObject = new PageableObject() + .paged(p.isPaged()) + .unpaged(p.isUnpaged()) + .pageNumber(p.getPageNumber()) + .pageSize(p.getPageSize()) + .sort(s) + .offset(p.getOffset()) + ; + PageChatMessage pageChatMessage = new PageChatMessage() + .content(chatMessages) + .pageable(pageableObject) + .last(m.isLast()) + .first(m.isFirst()) + .empty(m.isEmpty()) + .totalPages(m.getTotalPages()) + .totalElements(m.getTotalElements()) + .number(m.getNumber()) + .numberOfElements(m.getNumberOfElements()) + .size(m.getSize()) + .sort(s) + ; + return new ResponseEntity<>(pageChatMessage, HttpStatus.OK); + } + + private final List messages = new CopyOnWriteArrayList<>(); + + +} diff --git a/chat-server-generated/src/main/resources/application.properties b/chat-server-generated/src/main/resources/application.properties new file mode 100644 index 0000000..b38c97a --- /dev/null +++ b/chat-server-generated/src/main/resources/application.properties @@ -0,0 +1,3 @@ +logging.level.root=info +logging.level.cz.muni=debug +server.port=8080 diff --git a/chat-server-generated/src/test/java/cz/muni/chat/generated/server/GeneratedServerIT.java b/chat-server-generated/src/test/java/cz/muni/chat/generated/server/GeneratedServerIT.java new file mode 100644 index 0000000..dbeed07 --- /dev/null +++ b/chat-server-generated/src/test/java/cz/muni/chat/generated/server/GeneratedServerIT.java @@ -0,0 +1,84 @@ +package cz.muni.chat.generated.server; + +import com.fasterxml.jackson.databind.ObjectMapper; +import cz.muni.chat.generated.server.model.BackgroundColorEnum; +import cz.muni.chat.generated.server.model.ChatMessage; +import cz.muni.chat.generated.server.model.NewChatMessageRequest; +import cz.muni.chat.generated.server.model.NewChatMessageRequest.TextColorEnum; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +public class GeneratedServerIT { + + private static final Logger log = LoggerFactory.getLogger(GeneratedServerIT.class); + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Test + void testMessageIds() throws Exception { + log.debug("Integration Test - testMessageIds"); + //create more messages + List msgs = new ArrayList<>(); + for(int i = 1; i<=2; i++) { + String author = "Joe"; + String text = "message " + i; + TextColorEnum textColor = TextColorEnum.BLACK; + BackgroundColorEnum backgroundColor = BackgroundColorEnum.WHITE; + NewChatMessageRequest n = new NewChatMessageRequest(); + n.setText(text); + n.setTextColor(textColor); + n.setBackgroundColor(backgroundColor); + String reponse = mockMvc.perform(post("/api/messages?author=" + author) + .header("User-Agent", "007") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(n)) + ) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.text").value(text)) + .andExpect(jsonPath("$.author").value(author)) + .andExpect(jsonPath("$.textColor").value(textColor.getValue())) + .andExpect(jsonPath("$.backgroundColor").value(backgroundColor.getValue())) + .andReturn().getResponse().getContentAsString(); + log.debug("response = {}", reponse); + ChatMessage chatMessage = objectMapper.readValue(reponse, ChatMessage.class); + log.debug("msg = {}", chatMessage); + msgs.add(chatMessage); + } + + // get each message by calling URL and compare its content + for (ChatMessage msg : msgs) { + // read each message by calling the RestController + String response = mockMvc.perform(get("/api/message/{id}",msg.getId()).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + log.debug("response: {}", response); + ChatMessage chatMessage = objectMapper.readValue(response, ChatMessage.class); + assertThat("id", chatMessage.getId(), is(equalTo(msg.getId()))); + assertThat("text", chatMessage.getText(), is(equalTo(msg.getText()))); + } + } + +} diff --git a/chat-server-generated/src/test/resources/application.properties b/chat-server-generated/src/test/resources/application.properties new file mode 100644 index 0000000..4ffa1bb --- /dev/null +++ b/chat-server-generated/src/test/resources/application.properties @@ -0,0 +1,6 @@ +spring.main.banner-mode=off +logging.pattern.console=%clr(%d{HH:mm:ss}) %clr(%-5p) %clr(%logger{22}) %clr(%m){faint}%n +logging.level.root=warn +logging.level.org.springframework=warn +# change to logging.level.cz.muni=debug to see log of tests execution +logging.level.cz.muni=warn diff --git a/chat-server-generated/src/test/resources/logback.xml b/chat-server-generated/src/test/resources/logback.xml new file mode 100644 index 0000000..a78474d --- /dev/null +++ b/chat-server-generated/src/test/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n + + + + + + + diff --git a/chat-server/src/test/java/cz/muni/chat/server/rest/ChatIT.java b/chat-server/src/test/java/cz/muni/chat/server/rest/ChatIT.java index fc0ae1f..d4024dd 100644 --- a/chat-server/src/test/java/cz/muni/chat/server/rest/ChatIT.java +++ b/chat-server/src/test/java/cz/muni/chat/server/rest/ChatIT.java @@ -108,11 +108,9 @@ void testMessageIds() throws Exception { .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); log.debug("response: {}", response); - JsonNode tree = objectMapper.readTree(response); - String idFromJSON = tree.get("id").asText(); - String textFromJSON = tree.get("text").asText(); - assertThat("id", idFromJSON, is(equalTo(storedMessage.id()))); - assertThat("text", textFromJSON, is(equalTo(storedMessage.text()))); + ChatMessage chatMessage = objectMapper.readValue(response, ChatMessage.class); + assertThat("id", chatMessage.id(), is(equalTo(storedMessage.id()))); + assertThat("text", chatMessage.text(), is(equalTo(storedMessage.text()))); } } diff --git a/pom.xml b/pom.xml index 0f8c3b6..e438b54 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,7 @@ chat-server chat-client-java-lib chat-client-java + chat-server-generated