From 6e49e033a484c85748ee0099d71c8f0c439fb539 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:47:21 +0000 Subject: [PATCH] Modernize Spring Boot 2.7, add validation, exception handling, tests Co-Authored-By: Bobby Nobakht --- .gitignore | 64 ++++++++- .gitignore.txt | 1 - build.gradle | 2 +- pom.xml | 18 ++- src/main/java/hello/Application.java | 23 ---- .../hello/controller/HelloController.java | 17 +-- .../hello/controller/TopicController.java | 52 +++++--- .../hello/declaration/CustomPredicate.java | 1 + .../SimpleTimeClient.java | 4 +- .../exception/GlobalExceptionHandler.java | 38 ++++++ .../exception/TopicNotFoundException.java | 12 ++ src/main/java/hello/model/Quote.java | 34 ----- src/main/java/hello/model/Topic.java | 33 +++++ src/main/java/hello/model/Value.java | 33 ----- src/main/java/hello/service/TopicService.java | 22 ++-- .../main/resources/application.properties | 0 .../hello/controller/TopicControllerTest.java | 121 ++++++++++++++++++ .../declaration/SimpleTimeClientTest.java | 60 +++++++++ .../java/hello/service/TopicServiceTest.java | 112 ++++++++++++++++ target/classes/hello/Application.class | Bin 6460 -> 0 bytes .../hello/controller/GreetingController.class | Bin 1219 -> 0 bytes .../hello/controller/HelloController.class | Bin 4496 -> 0 bytes .../hello/controller/TopicController.class | Bin 2344 -> 0 bytes .../hello/declaration/CustomPredicate.class | Bin 248 -> 0 bytes .../hello/declaration/TimeClient.class | Bin 1383 -> 0 bytes target/classes/hello/model/Customer.class | Bin 1407 -> 0 bytes target/classes/hello/model/Greeting.class | Bin 588 -> 0 bytes target/classes/hello/model/Quote.class | Bin 1128 -> 0 bytes .../hello/model/SimpleTimeClient.class | Bin 1720 -> 0 bytes target/classes/hello/model/Topic.class | Bin 1121 -> 0 bytes target/classes/hello/model/Value.class | Bin 1111 -> 0 bytes .../classes/hello/service/TopicService.class | Bin 13054 -> 0 bytes target/classes/public/index.html | 10 -- 33 files changed, 509 insertions(+), 148 deletions(-) delete mode 100644 .gitignore.txt rename src/main/java/hello/{model => declaration}/SimpleTimeClient.java (95%) create mode 100644 src/main/java/hello/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/hello/exception/TopicNotFoundException.java delete mode 100644 src/main/java/hello/model/Quote.java delete mode 100644 src/main/java/hello/model/Value.java rename application.properties => src/main/resources/application.properties (100%) create mode 100644 src/test/java/hello/controller/TopicControllerTest.java create mode 100644 src/test/java/hello/declaration/SimpleTimeClientTest.java create mode 100644 src/test/java/hello/service/TopicServiceTest.java delete mode 100644 target/classes/hello/Application.class delete mode 100644 target/classes/hello/controller/GreetingController.class delete mode 100644 target/classes/hello/controller/HelloController.class delete mode 100644 target/classes/hello/controller/TopicController.class delete mode 100644 target/classes/hello/declaration/CustomPredicate.class delete mode 100644 target/classes/hello/declaration/TimeClient.class delete mode 100644 target/classes/hello/model/Customer.class delete mode 100644 target/classes/hello/model/Greeting.class delete mode 100644 target/classes/hello/model/Quote.class delete mode 100644 target/classes/hello/model/SimpleTimeClient.class delete mode 100644 target/classes/hello/model/Topic.class delete mode 100644 target/classes/hello/model/Value.class delete mode 100644 target/classes/hello/service/TopicService.class delete mode 100644 target/classes/public/index.html diff --git a/.gitignore b/.gitignore index 57f1cb2..9ef9c26 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,63 @@ -/.idea/ \ No newline at end of file +/.idea/ + +# Compiled class files +*.class + +# Log files +*.log + +# Package files +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# Gradle +build/ +.gradle/ +!gradle/wrapper/gradle-wrapper.jar + +# Eclipse +.classpath +.project +.settings/ +bin/ + +# IntelliJ +*.iml +*.iws +*.ipr +out/ + +# NetBeans +nbproject/private/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +# VS Code +.vscode/ + +# OS files +.DS_Store +Thumbs.db + +# Virtual machine crash logs +hs_err_pid* +replay_pid* diff --git a/.gitignore.txt b/.gitignore.txt deleted file mode 100644 index 57f1cb2..0000000 --- a/.gitignore.txt +++ /dev/null @@ -1 +0,0 @@ -/.idea/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 09f1083..0a6973e 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.2.RELEASE") + classpath("org.springframework.boot:spring-boot-gradle-plugin:2.7.18") } } diff --git a/pom.xml b/pom.xml index 63f5cbd..75edc18 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,13 @@ org.springframework gs-spring-boot - pom + jar 0.1.0 org.springframework.boot spring-boot-starter-parent - 2.0.2.RELEASE + 2.7.18 @@ -28,10 +28,24 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-validation + com.h2database h2 + + org.springdoc + springdoc-openapi-ui + 1.7.0 + + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/src/main/java/hello/Application.java b/src/main/java/hello/Application.java index 7cf8faf..53605fa 100644 --- a/src/main/java/hello/Application.java +++ b/src/main/java/hello/Application.java @@ -5,18 +5,14 @@ import java.util.stream.Collectors; import hello.model.Customer; -import hello.model.Quote; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.web.client.RestTemplate; @SpringBootApplication public class Application implements CommandLineRunner { @@ -34,25 +30,6 @@ public static void main(String[] args) { for (String beanName : beanNames) { System.out.println(beanName); } - - RestTemplate restTemplate = new RestTemplate(); - Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class); - log.info(quote.toString()); - } - - - @Bean - public RestTemplate restTemplate(RestTemplateBuilder builder) { - return builder.build(); - } - - @Bean - public CommandLineRunner run(RestTemplate restTemplate) throws Exception { - return args -> { - Quote quote = restTemplate.getForObject( - "http://gturnquist-quoters.cfapps.io/api/random", Quote.class); - log.info(quote.toString()); - }; } diff --git a/src/main/java/hello/controller/HelloController.java b/src/main/java/hello/controller/HelloController.java index f3602fa..a1cdfb8 100644 --- a/src/main/java/hello/controller/HelloController.java +++ b/src/main/java/hello/controller/HelloController.java @@ -1,23 +1,16 @@ package hello.controller; +import hello.declaration.SimpleTimeClient; import hello.declaration.TimeClient; -import hello.model.SimpleTimeClient; -import hello.model.Topic; import hello.service.TopicService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestMapping; import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.time.ZoneId; -import java.time.chrono.ChronoPeriod; import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collector; -import java.util.stream.Collectors; @RestController public class HelloController { @@ -43,7 +36,7 @@ public class HelloController { * * @return */ - @RequestMapping("/datetime") + @GetMapping("/datetime") public String index() { TimeClient myTimeClient = new SimpleTimeClient(); LocalDateTime localDateTime = LocalDateTime.now(); @@ -63,7 +56,7 @@ public String index() { * * @return */ - @RequestMapping("/topic/string/operation") + @GetMapping("/topic/string/operation") public String showStringOperation() { String join = topicService.returnAllTopicIDWithStringSlicing(); @@ -84,7 +77,7 @@ public String showStringOperation() { * File Operation in Java 8 * @return */ - @RequestMapping("/topic/file/operation") + @GetMapping("/topic/file/operation") public String showFileOperation() { String findAllFilesInPathAndSort = topicService.findAllFilesInPathAndSort(); String findParticularFileInPathAndSort = topicService.findParticularFileInPathAndSort(); diff --git a/src/main/java/hello/controller/TopicController.java b/src/main/java/hello/controller/TopicController.java index c2e8273..4c30d35 100644 --- a/src/main/java/hello/controller/TopicController.java +++ b/src/main/java/hello/controller/TopicController.java @@ -3,8 +3,17 @@ import hello.model.Topic; import hello.service.TopicService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; import java.util.List; @RestController @@ -18,9 +27,9 @@ public class TopicController { * Get all Topic * @return */ - @RequestMapping("/topic") - public List getAllTopics() { - return topicService.getAllTopics(); + @GetMapping("/topic") + public ResponseEntity> getAllTopics() { + return ResponseEntity.ok(topicService.getAllTopics()); } /** @@ -28,18 +37,19 @@ public List getAllTopics() { * @param id * @return */ - @RequestMapping("/topic/{id}") - public Topic getTopicWithID(@PathVariable String id) { - return topicService.getTopicWithId(id); + @GetMapping("/topic/{id}") + public ResponseEntity getTopicWithID(@PathVariable String id) { + return ResponseEntity.ok(topicService.getTopicWithId(id)); } /** * Add a new topic in list * @param topic */ - @RequestMapping(method = RequestMethod.POST, value = "/topic") - public void addTopic(@RequestBody Topic topic) { + @PostMapping("/topic") + public ResponseEntity addTopic(@Valid @RequestBody Topic topic) { topicService.addTopic(topic); + return ResponseEntity.status(HttpStatus.CREATED).build(); } /** @@ -47,9 +57,10 @@ public void addTopic(@RequestBody Topic topic) { * @param id * @param topic */ - @RequestMapping(method = RequestMethod.PUT, value = "/topic/{id}") - public void updateTopic(@PathVariable String id, @RequestBody Topic topic) { + @PutMapping("/topic/{id}") + public ResponseEntity updateTopic(@PathVariable String id, @Valid @RequestBody Topic topic) { topicService.updateTopic(id, topic); + return ResponseEntity.ok().build(); } @@ -57,9 +68,10 @@ public void updateTopic(@PathVariable String id, @RequestBody Topic topic) { * Delete a topic with ID * @param id */ - @RequestMapping(method = RequestMethod.DELETE, value = "/topic/{id}") - public void deleteTopic(@PathVariable String id) { + @DeleteMapping("/topic/{id}") + public ResponseEntity deleteTopic(@PathVariable String id) { topicService.deleteTopic(id); + return ResponseEntity.noContent().build(); } /** @@ -67,9 +79,9 @@ public void deleteTopic(@PathVariable String id) { * @param minLength * @return */ - @RequestMapping(value = "/topic/minimum/length/{minLength}") - public List filterMinimumLengthForId(@PathVariable Integer minLength) { - return topicService.filterMinimumLengthForId(minLength); + @GetMapping("/topic/minimum/length/{minLength}") + public ResponseEntity> filterMinimumLengthForId(@PathVariable Integer minLength) { + return ResponseEntity.ok(topicService.filterMinimumLengthForId(minLength)); } @@ -77,9 +89,9 @@ public List filterMinimumLengthForId(@PathVariable Integer minLength) { * Sort with Id * @return */ - @RequestMapping("/topic/sort") - public List sortTopicsWithID() { - return topicService.sortTopicsWithID(); + @GetMapping("/topic/sort") + public ResponseEntity> sortTopicsWithID() { + return ResponseEntity.ok(topicService.sortTopicsWithID()); } diff --git a/src/main/java/hello/declaration/CustomPredicate.java b/src/main/java/hello/declaration/CustomPredicate.java index 46f0c44..af828ac 100644 --- a/src/main/java/hello/declaration/CustomPredicate.java +++ b/src/main/java/hello/declaration/CustomPredicate.java @@ -4,6 +4,7 @@ * Use as a Functional Interface * @param */ +@FunctionalInterface public interface CustomPredicate { boolean test(T t); } diff --git a/src/main/java/hello/model/SimpleTimeClient.java b/src/main/java/hello/declaration/SimpleTimeClient.java similarity index 95% rename from src/main/java/hello/model/SimpleTimeClient.java rename to src/main/java/hello/declaration/SimpleTimeClient.java index e4e142a..e1eac43 100644 --- a/src/main/java/hello/model/SimpleTimeClient.java +++ b/src/main/java/hello/declaration/SimpleTimeClient.java @@ -1,6 +1,4 @@ -package hello.model; - -import hello.declaration.TimeClient; +package hello.declaration; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/hello/exception/GlobalExceptionHandler.java b/src/main/java/hello/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..55a11d9 --- /dev/null +++ b/src/main/java/hello/exception/GlobalExceptionHandler.java @@ -0,0 +1,38 @@ +package hello.exception; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(TopicNotFoundException.class) + public ResponseEntity> handleTopicNotFound(TopicNotFoundException ex) { + return buildResponse(HttpStatus.NOT_FOUND, ex.getMessage()); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity> handleGenericException(Exception ex) { + log.error("Unhandled exception", ex); + return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage()); + } + + private ResponseEntity> buildResponse(HttpStatus status, String message) { + Map body = new HashMap<>(); + body.put("timestamp", LocalDateTime.now().toString()); + body.put("status", status.value()); + body.put("error", status.getReasonPhrase()); + body.put("message", message); + return ResponseEntity.status(status).body(body); + } +} diff --git a/src/main/java/hello/exception/TopicNotFoundException.java b/src/main/java/hello/exception/TopicNotFoundException.java new file mode 100644 index 0000000..7ae064c --- /dev/null +++ b/src/main/java/hello/exception/TopicNotFoundException.java @@ -0,0 +1,12 @@ +package hello.exception; + +public class TopicNotFoundException extends RuntimeException { + + public TopicNotFoundException(String message) { + super(message); + } + + public TopicNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/hello/model/Quote.java b/src/main/java/hello/model/Quote.java deleted file mode 100644 index 2178a6d..0000000 --- a/src/main/java/hello/model/Quote.java +++ /dev/null @@ -1,34 +0,0 @@ -package hello.model; - -public class Quote { - private String type; - private Value value; - - @Override - public String toString() { - return "Quote{" + - "type='" + type + '\'' + - ", value=" + value + - '}'; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Value getValue() { - return value; - } - - public void setValue(Value value) { - this.value = value; - } - - public Quote() { - - } -} diff --git a/src/main/java/hello/model/Topic.java b/src/main/java/hello/model/Topic.java index 483a4a7..64e6907 100644 --- a/src/main/java/hello/model/Topic.java +++ b/src/main/java/hello/model/Topic.java @@ -1,9 +1,18 @@ package hello.model; +import java.util.Objects; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; public class Topic { + @NotBlank private String id; + + @NotBlank private String subjectName; + + @Size(max = 500) private String subjectDescription; public Topic() { @@ -40,4 +49,28 @@ public Topic(String id, String subjectName, String subjectDescription) { this.subjectDescription = subjectDescription; } + @Override + public String toString() { + return "Topic{" + + "id='" + id + '\'' + + ", subjectName='" + subjectName + '\'' + + ", subjectDescription='" + subjectDescription + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Topic topic = (Topic) o; + return Objects.equals(id, topic.id) + && Objects.equals(subjectName, topic.subjectName) + && Objects.equals(subjectDescription, topic.subjectDescription); + } + + @Override + public int hashCode() { + return Objects.hash(id, subjectName, subjectDescription); + } + } diff --git a/src/main/java/hello/model/Value.java b/src/main/java/hello/model/Value.java deleted file mode 100644 index 272be70..0000000 --- a/src/main/java/hello/model/Value.java +++ /dev/null @@ -1,33 +0,0 @@ -package hello.model; - -public class Value { - private Long id; - private String quote; - - public Value() { - } - - @Override - public String toString() { - return "Value{" + - "id=" + id + - ", quote='" + quote + '\'' + - '}'; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getQuote() { - return quote; - } - - public void setQuote(String quote) { - this.quote = quote; - } -} diff --git a/src/main/java/hello/service/TopicService.java b/src/main/java/hello/service/TopicService.java index feffb92..eabe950 100644 --- a/src/main/java/hello/service/TopicService.java +++ b/src/main/java/hello/service/TopicService.java @@ -1,6 +1,7 @@ package hello.service; import hello.declaration.CustomPredicate; +import hello.exception.TopicNotFoundException; import hello.model.Topic; import org.springframework.stereotype.Service; @@ -10,6 +11,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -19,7 +21,7 @@ public class TopicService { - private List topics = new ArrayList<>(Arrays.asList( + private List topics = new CopyOnWriteArrayList<>(Arrays.asList( new Topic("spring", "Spring Framework", "Spring Framework Description"), new Topic("java", "Core Java", "Java Description"), new Topic("javascript", "javascript Framework", "javascript Framework Description") @@ -36,7 +38,10 @@ public List getAllTopics() { * @return */ public Topic getTopicWithId(String id) { - return topics.stream().filter(topic -> topic.getId().equals(id)).findFirst().get(); + return topics.stream() + .filter(topic -> topic.getId().equals(id)) + .findFirst() + .orElseThrow(() -> new TopicNotFoundException("Topic not found with id: " + id)); } public void addTopic(Topic topic) { @@ -96,8 +101,9 @@ private static List printTopicsWithPredicate(List topicList, Custo * @return */ public List sortTopicsWithID() { - topics.sort(Comparator.comparing(Topic::getId)); - return topics; + return topics.stream() + .sorted(Comparator.comparing(Topic::getId)) + .collect(Collectors.toList()); } @@ -166,7 +172,7 @@ public String findIdHavingCharacter() { * @return */ public String findAllFilesInPathAndSort() { - try (Stream stream = Files.list(Paths.get(""))) { + try (Stream stream = Files.list(Paths.get(System.getProperty("user.dir")))) { String joined = stream .map(String::valueOf) .filter(path -> !path.startsWith(".")) @@ -183,7 +189,7 @@ public String findAllFilesInPathAndSort() { * @return */ public String findParticularFileInPathAndSort() { - Path start = Paths.get(""); + Path start = Paths.get(System.getProperty("user.dir")); int maxDepth = 25; try (Stream stream = Files.find(start, maxDepth, (path, attr) -> String.valueOf(path).startsWith("grad"))) { @@ -203,7 +209,7 @@ public String findParticularFileInPathAndSort() { * @return */ public String findParticularFileInPathAndSortWithWalkFunction() { - Path start = Paths.get(""); + Path start = Paths.get(System.getProperty("user.dir")); int maxDepth = 5; try (Stream stream = Files.walk(start, maxDepth)) { String joined = stream @@ -223,7 +229,7 @@ public String findParticularFileInPathAndSortWithWalkFunction() { * @return */ public String readFileWithStreamFunction() { - Path path = Paths.get("temp.txt"); + Path path = Paths.get(System.getProperty("java.io.tmpdir"), "springboot-java8-temp.txt"); System.out.println(); try (BufferedReader reader = Files.newBufferedReader(path)) { String lines = reader diff --git a/application.properties b/src/main/resources/application.properties similarity index 100% rename from application.properties rename to src/main/resources/application.properties diff --git a/src/test/java/hello/controller/TopicControllerTest.java b/src/test/java/hello/controller/TopicControllerTest.java new file mode 100644 index 0000000..00cede2 --- /dev/null +++ b/src/test/java/hello/controller/TopicControllerTest.java @@ -0,0 +1,121 @@ +package hello.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import hello.exception.GlobalExceptionHandler; +import hello.exception.TopicNotFoundException; +import hello.model.Topic; +import hello.service.TopicService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.Arrays; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willThrow; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +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.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(TopicController.class) +@Import(GlobalExceptionHandler.class) +class TopicControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private TopicService topicService; + + @MockBean + private JdbcTemplate jdbcTemplate; + + @Autowired + private ObjectMapper objectMapper; + + @Test + void getAllTopicsReturns200WithJsonArray() throws Exception { + given(topicService.getAllTopics()).willReturn(Arrays.asList( + new Topic("java", "Core Java", "Java desc"), + new Topic("spring", "Spring Framework", "Spring desc") + )); + + mockMvc.perform(get("/topic")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", org.hamcrest.Matchers.hasSize(2))) + .andExpect(jsonPath("$[0].id").value("java")); + } + + @Test + void getTopicByIdReturns200WhenFound() throws Exception { + given(topicService.getTopicWithId("java")) + .willReturn(new Topic("java", "Core Java", "Java desc")); + + mockMvc.perform(get("/topic/java")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value("java")) + .andExpect(jsonPath("$.subjectName").value("Core Java")); + } + + @Test + void getTopicByIdReturns404WhenMissing() throws Exception { + given(topicService.getTopicWithId("missing")) + .willThrow(new TopicNotFoundException("Topic not found with id: missing")); + + mockMvc.perform(get("/topic/missing")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.message").value("Topic not found with id: missing")); + } + + @Test + void createTopicReturns201() throws Exception { + Topic topic = new Topic("python", "Python", "Python desc"); + + mockMvc.perform(post("/topic") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(topic))) + .andExpect(status().isCreated()); + + verify(topicService).addTopic(any(Topic.class)); + } + + @Test + void updateTopicReturns200() throws Exception { + Topic topic = new Topic("java", "Java 17", "Updated desc"); + + mockMvc.perform(put("/topic/java") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(topic))) + .andExpect(status().isOk()); + + verify(topicService).updateTopic(eq("java"), any(Topic.class)); + } + + @Test + void deleteTopicReturns204() throws Exception { + mockMvc.perform(delete("/topic/java")) + .andExpect(status().isNoContent()); + + verify(topicService).deleteTopic("java"); + } + + @Test + void genericExceptionReturns500() throws Exception { + willThrow(new RuntimeException("boom")).given(topicService).deleteTopic("boom"); + + mockMvc.perform(delete("/topic/boom")) + .andExpect(status().isInternalServerError()) + .andExpect(jsonPath("$.message").value("boom")); + } +} diff --git a/src/test/java/hello/declaration/SimpleTimeClientTest.java b/src/test/java/hello/declaration/SimpleTimeClientTest.java new file mode 100644 index 0000000..9e54737 --- /dev/null +++ b/src/test/java/hello/declaration/SimpleTimeClientTest.java @@ -0,0 +1,60 @@ +package hello.declaration; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class SimpleTimeClientTest { + + @Test + void defaultConstructorInitializesLocalDateTime() { + SimpleTimeClient client = new SimpleTimeClient(); + LocalDateTime dateTime = client.getLocalDateTime(); + assertNotNull(dateTime); + } + + @Test + void setTimeUpdatesOnlyTimeComponent() { + SimpleTimeClient client = new SimpleTimeClient(); + client.setTime(10, 30, 45); + + LocalDateTime dateTime = client.getLocalDateTime(); + assertEquals(10, dateTime.getHour()); + assertEquals(30, dateTime.getMinute()); + assertEquals(45, dateTime.getSecond()); + } + + @Test + void toStringReturnsIsoFormattedDateTime() { + SimpleTimeClient client = new SimpleTimeClient(); + String result = client.toString(); + assertNotNull(result); + assertEquals(client.getLocalDateTime().toString(), result); + } + + @Test + void defaultMethodGetZonedDateTimeReturnsZonedDateTime() { + TimeClient client = new SimpleTimeClient(); + ZonedDateTime zoned = client.getZonedDateTime("America/New_York"); + + assertNotNull(zoned); + assertEquals(ZoneId.of("America/New_York"), zoned.getZone()); + } + + @Test + void staticGetZoneIdReturnsSystemDefaultForInvalidZone() { + ZoneId zoneId = TimeClient.getZoneId("Not/AValidZone"); + assertEquals(ZoneId.systemDefault(), zoneId); + } + + @Test + void staticGetZoneIdReturnsParsedZoneForValidZone() { + ZoneId zoneId = TimeClient.getZoneId("UTC"); + assertEquals(ZoneId.of("UTC"), zoneId); + } +} diff --git a/src/test/java/hello/service/TopicServiceTest.java b/src/test/java/hello/service/TopicServiceTest.java new file mode 100644 index 0000000..18ecbe6 --- /dev/null +++ b/src/test/java/hello/service/TopicServiceTest.java @@ -0,0 +1,112 @@ +package hello.service; + +import hello.exception.TopicNotFoundException; +import hello.model.Topic; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class TopicServiceTest { + + private TopicService topicService; + + @BeforeEach + void setUp() { + topicService = new TopicService(); + } + + @Test + void getAllTopicsReturnsInitialThreeTopics() { + List topics = topicService.getAllTopics(); + assertNotNull(topics); + assertEquals(3, topics.size()); + } + + @Test + void getTopicWithValidIdReturnsMatchingTopic() { + Topic topic = topicService.getTopicWithId("java"); + assertNotNull(topic); + assertEquals("java", topic.getId()); + assertEquals("Core Java", topic.getSubjectName()); + } + + @Test + void getTopicWithInvalidIdThrowsTopicNotFoundException() { + TopicNotFoundException ex = assertThrows( + TopicNotFoundException.class, + () -> topicService.getTopicWithId("does-not-exist") + ); + assertTrue(ex.getMessage().contains("does-not-exist")); + } + + @Test + void addTopicAppendsToList() { + Topic newTopic = new Topic("python", "Python Language", "Python Description"); + topicService.addTopic(newTopic); + + assertEquals(4, topicService.getAllTopics().size()); + assertEquals(newTopic, topicService.getTopicWithId("python")); + } + + @Test + void updateTopicReplacesExistingTopic() { + Topic updated = new Topic("java", "Java 17", "Updated Java Description"); + topicService.updateTopic("java", updated); + + Topic result = topicService.getTopicWithId("java"); + assertEquals("Java 17", result.getSubjectName()); + assertEquals("Updated Java Description", result.getSubjectDescription()); + } + + @Test + void deleteTopicRemovesFromList() { + topicService.deleteTopic("spring"); + + assertEquals(2, topicService.getAllTopics().size()); + assertThrows(TopicNotFoundException.class, + () -> topicService.getTopicWithId("spring")); + } + + @Test + void sortTopicsWithIDReturnsSortedListWithoutMutatingOriginal() { + List originalOrder = topicService.getAllTopics(); + List originalIds = originalOrder.stream().map(Topic::getId).collect(java.util.stream.Collectors.toList()); + + List sorted = topicService.sortTopicsWithID(); + List sortedIds = sorted.stream().map(Topic::getId).collect(java.util.stream.Collectors.toList()); + + assertEquals(java.util.Arrays.asList("java", "javascript", "spring"), sortedIds); + assertNotSame(originalOrder, sorted); + assertEquals(originalIds, originalOrder.stream().map(Topic::getId).collect(java.util.stream.Collectors.toList()), + "Original list order should not be mutated"); + } + + @Test + void filterMinimumLengthForIdFiltersById() { + List filtered = topicService.filterMinimumLengthForId(5); + assertEquals(2, filtered.size()); + assertTrue(filtered.stream().allMatch(t -> t.getId().length() > 5)); + } + + @Test + void stringOperationMethodsRunWithoutError() { + assertDoesNotThrow(() -> { + String join = topicService.returnAllTopicIDWithStringSlicing(); + assertNotNull(join); + assertFalse(join.isEmpty()); + + assertNotNull(topicService.makeDistinctAndSortCharacters(join)); + assertNotNull(topicService.splitAllIdWithColonSelectIDWithJavaKeywordThenSortThenJoin(join)); + assertNotNull(topicService.findIdHavingCharacter()); + }); + } +} diff --git a/target/classes/hello/Application.class b/target/classes/hello/Application.class deleted file mode 100644 index 245a020cdb693ce4216257a9f5aa3bd787671f48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6460 zcmb7Jd3+RS8GgQ8v)K%gE+mwDxHloNlu{_91w%+A=>|$RKoM&@*_|Wejybqa!877`CZ1J~>+$Ruo)gCncy0rphv&!f0=!Vci{hxqbuqkH!AlgpR6gBU zk1D(@4iz^w;N^Hl95>^Z1ckmfhS$k=uaDskal8?4is8))-V(!GW4JYjx5e;wDfJx< zSc7*aAn=|Bych3_+w|D8Xh+6b^-NxZZJDwj282{YY4RYG)3Di3=i4*sBzk|PoyMGDr?zBsy9SU z?nV8jf@_W%hfT*E%o`nrg5~P2X%!rSOCv=M8hXJ=4e43evd2<-nIY9ta;?**ZR9An z?lQAry1Qt2vgNQqO{bNkZS&G*!Ps9K9W?9#o!UH)vU>ioZkzHsSgdhJOsb!s9x?KH zE7egf=FO~U6eZV;>SjTpIe9F7TtB6!@_J!7m2suJ?NU`t+P9y6OW`vp$gkVOQg{SA ztJO1qRPD)< zB@;R6{wPD2PaTwtd^;!O>e&;0deMuOf&&V^EHILcR5EB;ZfX`ydrD?LM*y`%a?Zj; z1C&9ZQD8?T=i|{S5FM1s5QjjuhuNgoYP-awAB%Q#He;h*^9<~?Mo0BRPU4XTQ1A*V z-gPEx6g})K_zLsr5O?mOq68Du+UTRH2PMpY^9Vg@i@*rH3AHPRZmI$MNmubh z{7A*+*rnpf_=$p_s`!~S_U9^ofrrTl_IGs* zbWJBsnmH}g)!);RZqtTL+i|av(A5ri^mp#-=ud9B zzOQw(wT>zhVm^DIriukPrHCd~G>e4-tx=^Fz0t6;qKGHAzEGP8rVCC2Q&m*nq6C_} zRoUA!2h*YT*=_OLL`Z|cV7TRWG9*rWRCkPQcatX5POsa^Vhjln%;zo_>H?WD$2Hh2 zs;!bs7yP}3jpRzsZ!QbR&_~JOJ6yTU$wRg-H_sAk3R@j)3bKPY4;!u=81@=NvXOI& z4fgJ)WJ`owla_f!)M4BD827&#$FgafN>SaG?RPDK-UyAp@!n=NGjfw#V2G%^?ZsSc zvPUdPwuC4GS7_JtIiGf!g&}s5?NQ+IkTy#v59U11mEPbckfO>cA+zwe$Hj$WQ5;ob z@hmuxK3gzf#u+19lA~;$?#PKrU~R?JUKyiuDb#EV6{6 zB!|J^9UEkrm-BF1Zr|n6oB?Imk;A|&Ev}c_7AgF22}H#(obMp40?B0W%q}x?MP{jv zDIL|B{T+`l4w3q5y^|B`XnGs#_P-kVZunm?WK#&4;&;-ZLxn$dC}M>wG_gj-X`E3} zlGD*iIqe+hP=Fyh2&|fdgjqOcoiI{q?|8*YQV+gY5Qd{uPl{MakJFZQqQt6Jd*ngT zGeDmA9t@im$n$5?eVlkXcdqdn1K5V~67r{laeybpF!|$u>8t$Tyx~*?k~{T$K4bF3 zfg;v3&@s;Zr?&aRpb%Eb96BOyQc5sA@fj>hztcNz{&` zZo>o=fxfnLh_&tCc;B{~>TR`6wM{j*V&TT7+ATZlNVuqugg4ZR+a7!P9@HN_i}?PH ziH3w)eJ|#WWA6P>ch=mAd5dbs(Kvw%svwQ4_Ke#^AAqG)y&UtP(ae?fcoo0Zt;VIi z?!r3Kt;Z20kwc5;#4ftD88M{M$2*#g{W!p@!qdx@I7o+@`P|Px8GseYV1U|=U@i{f zFx@;t+Qq1Pj4J9BT&3Ws_j{FKoF3sDL5?SpSH^S)pQ?DR-7t>C?Ys%cbdzUJvriDj zl%zO@CzGv%)H3#0^D5-QibhD0?SV*T!+FdHrVG6|BvdI2RXi`)JSm`t0`v;;*Hioz zzQr7y>!=90g%M9I@WS1CH<}X7<5=k3T*w>cUMxCVomiYXT9a6kIa-@onmJmRSe7}5 z3Ih|?j|_q{`q7XZet) z)UTX5G{^)fgiVpmQpf;-Cn2KUgUv@<6BkWj3*(cxcmiAH^%C!T7TcyLdLWc&4S9@G z2Bn|?i$-0`duecyy4ZzzCw1+kE@|*`8T9S7UZh*Aw=j*ZHCvdyOCvortHD>t= diff --git a/target/classes/hello/controller/GreetingController.class b/target/classes/hello/controller/GreetingController.class deleted file mode 100644 index 1149660667b8bd33f1ed25bd2d4d556a0184f111..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1219 zcmb7DYflqF6g|^-OLKy#_<+zlxxYx|+pLNS!% z@K8IhW&6?&l@d~0T>GA5TWis;=0_lz$BuOLDnqhdsWYV3{U$*T)*LCGhh9UdSG?gy z41Alrb*>y^cbqA`?*t5UwSD2bzA2@Z@47-+8%hXGG>KxzMTB#$j+dd@q1fF~r32#; z1@{zz@=}s}L}7f3+H*WncLIkvtV!u>t{oDA;bF~JEh}gnY4#L_ANlI7btD>A!;wvk zpT=5S;$0{L{fxKUv5e`%SUzSk%=DIc$qf`q+EZ)!ytN`2>Z8~cdpvZ1zgPOTuiPd> zVcQRtEuJ_==drWOEt$7JUyFh6626EFC^5`OBlORiC}I#p48!r0_P#|Cw{eGI_CKDR z+Inh+VsUCNm}VIIGruny2g24_+%3{h+&AQwY2X}bE8)?UuF2+x(9t|@_T6H*_d$YJ`L{RaAwBD4`Y72|k}VvH}nYdEC!4K(-JWfYr$d+wjzujAq7}jAk4~Of#YPfGtv&s&a7u< zB}5MAuyfz{?cDcaJC*>G*faD{qV)P=sBg)cP7Aj~0;N)8Ro zXRwgNHc@(A=%So(BZm*;BUyZO13rdVgze*5e4-nl#HZxr)hu4i;nVnx44)O=&t>uX z9KL`rX7QygzAR#2$>FP_Xd7-dHY-<087GJIQx@5u078NMgO_cQoG20zrG zU-fKv%Bs~JBeXQ+C$1XvM$s|cxneo=ZFlathDU0~HEYZcLffr`Bd%HY{BX2t_(mnP z{Gcg(GN?OtIN~@Z^O7A_M?J@L%a&tR!qS*5j8pZq*5ZQan^RTG6*WS~S6Q%U)^^R3 zdB&LM;pr*OLwaSOXPmMfD=4|=jj)=S)a2B+p6c^0!xYWJLRVQvZ7q`?dUd-}w)}a!LhtULs9KKW6@z%8IMuRCKkvNIa6`Lh zU9+C085 zvAp8Bq3=14?_ zu0hz6jXK8gehmdFE{wBc#ZYlTRcWk0Pz$`ZYJ9SEPSvci>Y2kz$CDV+aQa~D-)SpU z21QF_s*+Z`K@~(*O_@>?E97uZ6|kDcT1#Uml%l%#inBzHheceU`$n`8rn2m_0RPyirV3@ z*mqpyo8qT!$bx@*YOMdQp4d@66r@O8hSO)_bI<%^KQ&oDuZ9?_%&YF z@f-YB!?9Fk)g+boW>wv{=54PLs2V#+RV^3+mHbY}@9_s6f5e|!Gjo-aQlO+IDMLAy zQCEwW;j3p9h5szxdPB#XcuQdXg>`I|VEQp;%^D3SRKa4vII0_-%j7kg-5I>CV+qR| z`cvlSM4FH!`KaO8v!3tT#<0@xz^LIGrcoSa-us55<0fupa9hXwFp|MLI__XX$3^^A z$0ZqFkk2bJyePv5WOxY^8dRJM_inHnHaGKNa^@;;*h*@wZHa95jIV}WE3J4f3%lle zHbKiZ>Fa^D4SQ`5PtuNp+0cuN=_;dEmNHRCot)LMzg2H+^YOKMsW7<-?cV}CWX=j# zwS1aTcN)Q%vB<~C?t$?{XN;?~)g(Y|2g*aivX-# zu0nqO5;BE+b_v~ud~OLF3VD4A8w>ddmawUi-@Jq^Z&I)Wr#bGAjNL)yJ;-4fHe)xo zV=qUAJ^~uxcnJG&hP--wAW9hLmxgCCK`mm;ztDwsq_5pUe)=Z1PTazSXYXJe=iBo; zmhsS|%h-7fJ)Grt$>(kCW@as8PqO%MbMYN1}!O$#%bp zj$!S)3zK9gCR6d1{q-JiwLb_bAXZsBw-!0i!$X#%{=#Jqxs*tmMxx0>LlQ*h65U%+kV i%8Q(Jkb8u@0Sv6Q}7zpJZ!eFO?-%S|!6U z{ZH*oC!Og-e?Wg!r{AvRON2ay2kmO5bI$jD=d%C&``6z@v`kiosx{>a}|Mwj*?Pl_%- z5TR(gyzY6vw59O9kkKQ{587tf3xwA`4D2pH_Jg0zCbzxNJhWTV58j&gz`?9X(mxgf zcM!I?COje68Rct>2aF0Ez5_02E#dL+qi&N2`!>)RON>o#)gSYw*%Y2LDtwRs67f*JvU@#b3a%4Jwi^MgXzE%pngUBr@kb#$JDZ9| zOw+Z!w%L#>!>fxKL>T3Sqtc{BjaoCR#?j4p!ub{1I$g+JTNO<5;8aB)WL7jw)2=N$ z{jxw&*>)T)fYEF%gQqI;L?U)3<3Dl%HXR>Y9)2)~eqOaBNECKoH})B=d~AT{zVjCD z)u`v#k|#2185PJNu7u@xe*kP1?SX_Q?iVuLm2Giz%i7xCVl;OsT%`XM=AavOE$+2t zXWI{Ukb#?{zB``eZ62Wd@Aqw2c(Eg+nUN0YyD)nEA(6&4_(IY@Kv5J;S93Jq4N%cl z=R!Y-J2&jNZolo+A4Zji9|bMGEz~rh*U1^q=RGCq<0dJTL-$pK&e10Z8FZ#ZFAcg# za|V4!*9^Kzw+#A%?iutYePz(sv~18fG{z|E z_i+{XGe%P}!#;&m5&K!}W$Yl0bs8rVJHtM)^e3_3@sgt%tjd@Wx^Y~WLD({|9F%7*8Nh=z9KDHc4tt3+6 zO^QTL=QK^iOi0A?&*TR3V=Cy*gi1OIr8JXuB;o0pBn*?D#=n0Ge(j~_PCTdfyJDG;u(~xoN|9|T~M)Frt#vH8;X6*^le`Q|( AuK)l5 diff --git a/target/classes/hello/declaration/CustomPredicate.class b/target/classes/hello/declaration/CustomPredicate.class deleted file mode 100644 index e35803f64936c9dac92044b2074162814cb240fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmZXPu?~Vj5JYDYLD0fNKfn$fudz~NV`62Z2~>9Hals=eByjj~7Jh&qWjwLNVw0Vh z$?WXw{dfXcV&o(AF(kM~)`l>R4mrPbrg@RE<0Y5EtmkJ!5UZ@;(I#2_ z+qeIS5XNOw3AtC=226HMZOYrJlBp8h$i??0VRn^Tmn@Y+^NJf)7OZ0=jJxeT0>QDr W0OS&SaINlJ<-oJ^+k6aK5_|y1tUr+e diff --git a/target/classes/hello/declaration/TimeClient.class b/target/classes/hello/declaration/TimeClient.class deleted file mode 100644 index a077c3b314ee91fac7a75e48cd1d292b119702c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1383 zcma)6YflqF6g|_H-L@%Al)A1LI*PW0fBdOc3!3FdX=bSyCF6(M)+l3>uxd_F(D7n;_%BvUsz)o$6fLQFzo z>agBJAq!rSI|>oHN6hKMF+bs1NsQTZ&KyI60^WMA$Xg6kW(ah+dzjskzU?07+G9f; z1;ti9i z66kH0!O*oMdGXyQF9)ntVg{A0(quIl8D{?@g(h5OB9H6}!+7CHIF6UKMA6|sSE912 zdaI5tT&eW!cvZhBHf)t;Ps=r@l0krnj*M1BHXX-8?5~{&qxI+6+h$2F(nW=%D7Cs~T9kDlG z(2>&4pl9ew#p!j1#2Jz`be>WiQK5sPq8OolicTQD4&u|uavftBCCeZoG)&NGJcu!I z6=||xqelZ<*U85)N%&C73gMNK?#x#h3^O%!)zE!PmPqg&ilO~vlbevZfhn@7o#JNn JyGf@A%-=-ZS;_za diff --git a/target/classes/hello/model/Customer.class b/target/classes/hello/model/Customer.class deleted file mode 100644 index 06e7307b01f2d26b0448a3cb8b12af11a1a0577c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1407 zcmaJ-=K;NhX@e zNHp;W_@j*HY4<`#F->}(mwV51&bjx`-=Dt$tYJNcN(Kt1j%8V^X-r~8qE#K1Bo8Hd zq~oz9Pb68(U(KW0?Y1jjrWSF=$vkjHiD&=#Y*Ft`(GOiQDHA}=M%M}^#o#=C=8O20guu=%g$(4FY=QCj;J1FG7u-b$1Ex^CQe=$b)Di7p^XJWSK;&R}hh_5hA7F4$A)kZ~E($ diff --git a/target/classes/hello/model/Greeting.class b/target/classes/hello/model/Greeting.class deleted file mode 100644 index f875277914303b411d510e45ee094e441fbdc76c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmZuu%SyvQ6g`tiV{7^_t@Vw%YXh2%JH<^wu>@UI3NF)hXs4tJ#MHkM6fA-ZKfsR? z?0D}nny=iIsZ`u_L?aE5~tbZix&VOyFV1G@(H7!)yNU|j~okHUn934`TMyeH2I zyl~|7l30YJbB4l&2t{(q&}?;A`|Uo1)`^Ckq3Vi|-_E839^ZR|fGU<7`CicXVj=Uq zs3l|ZNNnzy2SMaa2^%=qG3QC9r;m7YL#wH+HZ518th3m!(Q2=5Kr_8)7W@24NX_zs z>QuhPL<##Q3NTEpp~%qqPnDte_wc*Hg!^<1((mJ#E~e8N6sn zK)FV~YQKZohjS?Q$sFn{l@yf8T4~!LE8#^{2wb815djHCUyZzsqzp?VIVoi}2%X6| s#3p;X{RZWkf{eV710R diff --git a/target/classes/hello/model/Quote.class b/target/classes/hello/model/Quote.class deleted file mode 100644 index 3ec6c6c7d3ee5544ff04f2ad4753558e032a5fd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1128 zcmZ`%?@!ZE6g_XWYgdbm!3OFO5OCf2Q5C)+e2~OXi^f1^{Mc>HC@JkSS`uUYpES{t zXyPB>A7#Avt+LsbGLW4Yq(1eeAmerRIfm?byB(^z74U;03)y0rlGPW4c^up1Zyu+LvM1_3aiX z=~j=zQKi75RnO{IPN+d(uIUBtoA|Qr4$hpmFWJJ5& zZgeJS`KV^%8J?TCk2yZQAhA1Z(&Zx)Ma*+@-$V%u z0`rr?C5Aw8O!c;X;dUaD>Gb<<(53&HWyh35i8ivdYMo5~wej_Ta3iwAyX&z|Z)}#{ zVvatVPM&BW+Vk}0Xdqe_DSA)$g7)2?5Fc)kE6og{G`>Nltymi(U(!YieTYKwGbM&F zzDT%o0tOUNp|d#x!V;D#5_oV+VpGH}>2h@KX*oGIinRk8T5GR;+Hc>#d&NqAkt8#ZQb%-NV%80vbdzZiAbf}XF?Sb6Tf^xTwzyApT2@Gei~XilL#A4EaA zpipehJW(hu#a&kHT?r!p(N=HWPu9HkkUL|#@QIfM5}VCZx*7Bp4zFzbVHmqT)`sqC z(0joQ!Y_q^AEhL*`+k~9DYurFmo?F5yp<@ZWlHD;(N;>1a^LU7QJ3;NTS>xF(Wy|+ zlTXx&G_)44`e{y%X-}9llw#L=tzh-yDBWbAuYHg774gYH{3OkU4x7S(i4{?9#E)$F z>2F3VOtfb5WEvSx8n32F5N#;z|Ctzi(T1DtvYF~C{pk4j12Mb4+rx7*z#8^q#Kz4U z7BEx89t_*KRl{v8+PG8067I_5o;>c$_JbPQIIS@Gujwd^=*ywiJYIk9cj%_6==z<| zOT09QBUc*9=BY6Lm+Qn!6veL;_T`+@@@GlhQ~#EoKThUy z-K0;uv9oCv;%5qn^xfKlu191haBnB=V0Lr4*}2>XC!a*F7{&c>ZyFoZ{D}`ip~i1P z#>@YJGS{3spQDTxxUcxGwLe3(w^8_r;(NvgjPW^)qMV_`+95{!bfojKA9Y3w2QY51 z-Y~n&y{YyG6t_{DElo^LZNr+i+Kp1f+D7>|@G-)IG!?>*5^j=!La>m57y`oKAR1ca z6b^A!5DH9iRb;KyO%Z97G7qB(ifgs5S(W_PU^U6(8XO*?p!EXAL2_w zw|Y7X&Zgr*kevI2P?~%3&<`*CM9V!dTIrRZDD3vGf-sD|F?&PrJigIG4lj*@^fQ$; z+MOb8rOEtrv%UURl+@VXzb(JUhNVJtfmnJ{a{*kczb%-wK6||)YMg#NO@_fIExT~C zC%%$}yQso-QAWkZh6D!{h5Fh)6t)-se926~Ax*StuL(m4crt_|%cNnhfF8nS+~n;w zvtllFe?ooFU^PaEZD6Ct(-uzxCkWf9Gt)WjG75pmJSX@8;~NVGguu>^XiySz;Xw+e-rt3sNELhcm{F;|7`QOJWkgvfG5$o)bg z)~b;GLLqy_LabFG;_lHMLd0DWQl-?nH6gcVak~xiHrsIb#SCWmCujCoiFXb8J^8;WJmk&5qkoNMrN96H diff --git a/target/classes/hello/model/Value.class b/target/classes/hello/model/Value.class deleted file mode 100644 index 862a68f17d303c4c370907d46f8531959e3c75f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1111 zcmZ`%?@!ZU5PsgW{+dO`3QPrM0=jN6s=_yf50aReEE}@YKL1C#6$o%YBJ@^a$};#&e+Cd*F{P*H$}6^e`$gbMD^N$^I< za)bAT*PwcA&R9hWQMr)l?o*AAZEku$3vQwf|nt1$5ipn}LHC`MKULUE=6Va!M gtj;7-rMpO1H9K@9)jq+1Z0b|0o}wnfKoBzTWS> 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 diff --git a/target/classes/public/index.html b/target/classes/public/index.html deleted file mode 100644 index 566549b..0000000 --- a/target/classes/public/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Title - - - - - \ No newline at end of file