From b623297829c113a80b571e25e5680ff5e9bcfaf6 Mon Sep 17 00:00:00 2001 From: mbarriola <85458535+mbarriola@users.noreply.github.com> Date: Thu, 5 Aug 2021 15:50:37 -0400 Subject: [PATCH] Core java 12 improvements (#11090) * Commit source code to branch * Fix to BAEL-5072 Change package definition and implementation of compactValues junit * BAEL-5053 Compare file contents --- core-java-modules/core-java-12/pom.xml | 93 ++++++++------- .../comparison/CompareFileContents.java | 88 ++++++++++++++ .../CampareFileContentsApacheIOUnitTest.java | 88 ++++++++++++++ .../CompareByMemoryMappedFilesUnitTest.java | 42 +++++++ .../CompareFileContentsByBytesUnitTest.java | 96 +++++++++++++++ .../CompareFileContentsByLinesUnitTest.java | 94 +++++++++++++++ .../newfeatures/CompactNumbersUnitTest.java | 6 +- .../newfeatures/FileMismatchUnitTest.java | 4 +- .../baeldung/newfeatures/StringUnitTest.java | 4 +- .../newfeatures/TeeingCollectorUnitTest.java | 6 +- patterns/simplehexagonalexample/pom.xml | 31 +++++ .../simplehexagonalex/DailyQuoteMain.java | 32 +++++ .../controller/QuoteCliController.java | 24 ++++ .../controller/QuoteRestController.java | 24 ++++ .../domain/QuoteOfTheDay.java | 56 +++++++++ .../repository/QuoteOfTheDayFromProvider.java | 8 ++ .../domain/service/QuoteAggregator.java | 22 ++++ .../domain/service/QuoteService.java | 8 ++ .../primary/quoteadapter/ProviderQuote.java | 109 ++++++++++++++++++ .../quoteadapter/ProviderQuoteAdapter.java | 54 +++++++++ .../quoteadapter/ProviderQuoteEnvelope.java | 68 +++++++++++ .../mock/quoteadapter/MockQuoteAdapter.java | 20 ++++ .../src/main/resources/application.properties | 1 + .../MockAccessProviderUnitTest.java | 22 ++++ .../PrimaryAccessProviderIntegrationTest.java | 28 +++++ .../QuoteRequestIntegrationTest.java | 36 ++++++ .../src/test/resources/application.properties | 1 + 27 files changed, 1014 insertions(+), 51 deletions(-) create mode 100644 core-java-modules/core-java-12/src/main/java/com/baeldung/file/content/comparison/CompareFileContents.java create mode 100644 core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CampareFileContentsApacheIOUnitTest.java create mode 100644 core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareByMemoryMappedFilesUnitTest.java create mode 100644 core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByBytesUnitTest.java create mode 100644 core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByLinesUnitTest.java create mode 100644 patterns/simplehexagonalexample/pom.xml create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java create mode 100644 patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java create mode 100644 patterns/simplehexagonalexample/src/main/resources/application.properties create mode 100644 patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java create mode 100644 patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java create mode 100644 patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java create mode 100644 patterns/simplehexagonalexample/src/test/resources/application.properties diff --git a/core-java-modules/core-java-12/pom.xml b/core-java-modules/core-java-12/pom.xml index 8f6abdda5b..ce7ec72aeb 100644 --- a/core-java-modules/core-java-12/pom.xml +++ b/core-java-modules/core-java-12/pom.xml @@ -1,49 +1,60 @@ - 4.0.0 - core-java-12 - 0.1.0-SNAPSHOT - core-java-12 - jar - http://maven.apache.org + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + core-java-12 + 0.1.0-SNAPSHOT + core-java-12 + jar + http://maven.apache.org - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + - - - org.assertj - assertj-core - ${assertj.version} - test - - + + + org.assertj + assertj-core + ${assertj.version} + test + + + commons-io + commons-io + 2.11.0 + + - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${maven.compiler.source.version} - ${maven.compiler.target.version} - --enable-preview - - - - + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + --enable-preview + + + + maven-surefire-plugin + + --enable-preview + + + + - - 12 - 12 - 3.6.1 - + + 12 + 12 + 3.6.1 + \ No newline at end of file diff --git a/core-java-modules/core-java-12/src/main/java/com/baeldung/file/content/comparison/CompareFileContents.java b/core-java-modules/core-java-12/src/main/java/com/baeldung/file/content/comparison/CompareFileContents.java new file mode 100644 index 0000000000..637ddb4a91 --- /dev/null +++ b/core-java-modules/core-java-12/src/main/java/com/baeldung/file/content/comparison/CompareFileContents.java @@ -0,0 +1,88 @@ +package com.baeldung.file.content.comparison; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; + +public class CompareFileContents { + + public static long filesCompareByByte(Path path1, Path path2) throws IOException { + + if (path1.getFileSystem() + .provider() + .isSameFile(path1, path2)) { + return -1; + } + + try (BufferedInputStream fis1 = new BufferedInputStream(new FileInputStream(path1.toFile())); + BufferedInputStream fis2 = new BufferedInputStream(new FileInputStream(path2.toFile()))) { + int ch = 0; + long pos = 1; + while ((ch = fis1.read()) != -1) { + if (ch != fis2.read()) { + return pos; + } + pos++; + } + if (fis2.read() == -1) { + return -1; + } else { + return pos; + } + } + } + + public static long filesCompareByLine(Path path1, Path path2) throws IOException { + + if (path1.getFileSystem() + .provider() + .isSameFile(path1, path2)) { + return -1; + } + + try (BufferedReader bf1 = Files.newBufferedReader(path1); + BufferedReader bf2 = Files.newBufferedReader(path2)) { + + long lineNumber = 1; + String line1 = "", line2 = ""; + while ((line1 = bf1.readLine()) != null) { + line2 = bf2.readLine(); + if (line2 == null || !line1.equals(line2)) { + return lineNumber; + } + lineNumber++; + } + if (bf2.readLine() == null) { + return -1; + } else { + return lineNumber; + } + } + } + + public static boolean compareByMemoryMappedFiles(Path path1, Path path2) throws IOException { + + try (RandomAccessFile randomAccessFile1 = new RandomAccessFile(path1.toFile(), "r"); + RandomAccessFile randomAccessFile2 = new RandomAccessFile(path2.toFile(), "r")) { + + FileChannel ch1 = randomAccessFile1.getChannel(); + FileChannel ch2 = randomAccessFile2.getChannel(); + if (ch1.size() != ch2.size()) { + + return false; + } + long size = ch1.size(); + MappedByteBuffer m1 = ch1.map(FileChannel.MapMode.READ_ONLY, 0L, size); + MappedByteBuffer m2 = ch2.map(FileChannel.MapMode.READ_ONLY, 0L, size); + + return m1.equals(m2); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CampareFileContentsApacheIOUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CampareFileContentsApacheIOUnitTest.java new file mode 100644 index 0000000000..0d86abae11 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CampareFileContentsApacheIOUnitTest.java @@ -0,0 +1,88 @@ +package com.baeldung.file.content.comparison; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class CampareFileContentsApacheIOUnitTest { + + public static Path path1 = null; + public static Path path2 = null; + + @BeforeAll + public static void setup() throws IOException { + + path1 = Files.createTempFile("file1Test", ".txt"); + path2 = Files.createTempFile("file2Test", ".txt"); + } + + @Test + public void whenFilesIdentical_thenReturnTrue() throws IOException { + + InputStream inputStream1 = new FileInputStream(path1.toFile()); + InputStream inputStream2 = new FileInputStream(path2.toFile()); + + Files.writeString(path1, "testing line 1" + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2"); + + assertTrue(IOUtils.contentEquals(inputStream1, inputStream2)); + } + + @Test + public void whenFilesDifferent_thenReturnFalse() throws IOException { + + InputStream inputStream1 = new FileInputStream(path1.toFile()); + InputStream inputStream2 = new FileInputStream(path2.toFile()); + + Files.writeString(path1, "testing line " + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2"); + + assertFalse(IOUtils.contentEquals(inputStream1, inputStream2)); + } + + @Test + public void whenFilesIdenticalIgnoreEOF_thenReturnTrue() throws IOException { + + Files.writeString(path1, "testing line 1 \n line 2"); + Files.writeString(path2, "testing line 1 \r\n line 2"); + + Reader reader1 = new BufferedReader(new FileReader(path1.toFile())); + Reader reader2 = new BufferedReader(new FileReader(path2.toFile())); + + assertTrue(IOUtils.contentEqualsIgnoreEOL(reader1, reader2)); + } + + @Test + public void whenFilesNotIdenticalIgnoreEOF_thenReturnFalse() throws IOException { + + Files.writeString(path1, "testing line \n line 2"); + Files.writeString(path2, "testing line 1 \r\n line 2"); + + Reader reader1 = new BufferedReader(new FileReader(path1.toFile())); + Reader reader2 = new BufferedReader(new FileReader(path2.toFile())); + + assertFalse(IOUtils.contentEqualsIgnoreEOL(reader1, reader2)); + } + + @AfterAll + public static void shutDown() { + + path1.toFile() + .deleteOnExit(); + path2.toFile() + .deleteOnExit(); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareByMemoryMappedFilesUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareByMemoryMappedFilesUnitTest.java new file mode 100644 index 0000000000..0405ac3b52 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareByMemoryMappedFilesUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.file.content.comparison; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class CompareByMemoryMappedFilesUnitTest { + + public static Path path1 = null; + public static Path path2 = null; + + @BeforeAll + public static void setup() throws IOException { + + path1 = Files.createTempFile("file1Test", ".txt"); + path2 = Files.createTempFile("file2Test", ".txt"); + } + + @Test + public void whenFilesIdentical_thenReturnTrue() throws IOException { + + Files.writeString(path1, "testing line 1" + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2"); + + assertTrue(CompareFileContents.compareByMemoryMappedFiles(path1, path2)); + } + + @Test + public void whenFilesDifferent_thenReturnFalse() throws IOException { + + Files.writeString(path1, "testing line " + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2"); + + assertFalse(CompareFileContents.compareByMemoryMappedFiles(path1, path2)); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByBytesUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByBytesUnitTest.java new file mode 100644 index 0000000000..15efc952c2 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByBytesUnitTest.java @@ -0,0 +1,96 @@ +package com.baeldung.file.content.comparison; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class CompareFileContentsByBytesUnitTest { + + public static Path path1 = null; + public static Path path2 = null; + + @BeforeAll + public static void setup() throws IOException { + + path1 = Files.createTempFile("file1Test", ".txt"); + path2 = Files.createTempFile("file2Test", ".txt"); + } + + @Test + public void whenFirstFileShorter_thenPositionInSecondFile() throws IOException { + + Files.writeString(path1, "testing"); + Files.writeString(path2, "testing1"); + + assertEquals(8, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @Test + public void whenSecondFileShorter_thenPositionInFirstFile() throws IOException { + + Files.writeString(path1, "testing1"); + Files.writeString(path2, "testing"); + + assertEquals(8, CompareFileContents.filesCompareByByte(path1, path2)); + + } + + @Test + public void whenFilesIdentical_thenSuccess() throws IOException { + + Files.writeString(path1, "testing"); + Files.writeString(path2, "testing"); + + assertEquals(-1, CompareFileContents.filesCompareByByte(path1, path2)); + + } + + @Test + public void whenFilesDifferent_thenPosition() throws IOException { + + Files.writeString(path1, "tesXing"); + Files.writeString(path2, "testing"); + + assertEquals(4, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @Test + public void whenBothFilesEmpty_thenEqual() throws IOException { + + Files.writeString(path1, ""); + Files.writeString(path2, ""); + + assertEquals(-1, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @Test + public void whenFirstEmpty_thenPositionFirst() throws IOException { + + Files.writeString(path1, ""); + Files.writeString(path2, "test"); + + assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @Test + public void whenSecondEmpty_thenPositionFirst() throws IOException { + + Files.writeString(path1, "test"); + Files.writeString(path2, ""); + + assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @AfterAll + public static void shutDown() { + + path1.toFile().deleteOnExit(); + path2.toFile().deleteOnExit(); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByLinesUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByLinesUnitTest.java new file mode 100644 index 0000000000..63170221d3 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/file/content/comparison/CompareFileContentsByLinesUnitTest.java @@ -0,0 +1,94 @@ +package com.baeldung.file.content.comparison; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class CompareFileContentsByLinesUnitTest { + + public static Path path1 = null; + public static Path path2 = null; + + @BeforeAll + public static void setup() throws IOException { + + path1 = Files.createTempFile("file1Test", ".txt"); + path2 = Files.createTempFile("file2Test", ".txt"); + } + + @Test + public void whenFirstFileShorter_thenLineNumbersFirstFile() throws IOException { + + Files.writeString(path1, "testing line 1"); + Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "line 2"); + + assertEquals(1, CompareFileContents.filesCompareByLine(path1, path2)); + } + + @Test + public void whenSecondFileShorter_thenLineNumbersSecondFile() throws IOException { + + Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing line 1"); + + assertEquals(1, CompareFileContents.filesCompareByLine(path1, path2)); + } + + @Test + public void whenFileIdentical_thenLineSuccess() throws IOException { + + Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "line 2"); + + assertEquals(-1, CompareFileContents.filesCompareByLine(path1, path2)); + } + + @Test + public void whenFilesDifferent_thenLineNumber() throws IOException { + + Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2"); + Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "linX 2"); + + assertEquals(2, CompareFileContents.filesCompareByLine(path1, path2)); + } + + @Test + public void whenBothFilesEmpty_thenEqual() throws IOException { + + Files.writeString(path1, ""); + Files.writeString(path2, ""); + + assertEquals(-1, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @Test + public void whenFirstEmpty_thenPositionFirst() throws IOException { + + Files.writeString(path1, ""); + Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "line 2"); + + assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @Test + public void whenSecondEmpty_thenPositionFirst() throws IOException { + + Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2"); + Files.writeString(path2, ""); + + assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2)); + } + + @AfterAll + public static void shutDown() { + + path1.toFile().deleteOnExit(); + path2.toFile().deleteOnExit(); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java index 08a6d58d72..a557ce5545 100644 --- a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java @@ -1,6 +1,6 @@ -package java.com.baeldung.newfeatures; +package com.baeldung.newfeatures; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.text.NumberFormat; import java.util.Locale; @@ -16,6 +16,6 @@ public class CompactNumbersUnitTest { assertEquals("2.59K", likesShort.format(2592)); NumberFormat likesLong = NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG); likesLong.setMaximumFractionDigits(2); - assertEquals("2.59 thousand", likesShort.format(2592)); + assertEquals("2.59 thousand", likesLong.format(2592)); } } diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java index 7f081fe399..93fcfbda02 100644 --- a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java @@ -1,6 +1,6 @@ -package java.com.baeldung.newfeatures; +package com.baeldung.newfeatures; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.file.Files; diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java index 5ae51bd960..1651fe0ee6 100644 --- a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java @@ -1,6 +1,6 @@ -package java.com.baeldung.newfeatures; +package com.baeldung.newfeatures; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.junit.Assert.assertEquals; diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java index 30a5cb40a7..a925e693ff 100644 --- a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java @@ -1,6 +1,6 @@ -package java.com.baeldung.newfeatures; +package com.baeldung.newfeatures; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -13,6 +13,6 @@ public class TeeingCollectorUnitTest { public void givenSetOfNumbers_thenCalculateAverage() { double mean = Stream.of(1, 2, 3, 4, 5) .collect(Collectors.teeing(Collectors.summingDouble(i -> i), Collectors.counting(), (sum, count) -> sum / count)); - assertEquals(3.0, mean); + assertEquals(3.0, mean, 0); } } diff --git a/patterns/simplehexagonalexample/pom.xml b/patterns/simplehexagonalexample/pom.xml new file mode 100644 index 0000000000..b73e81be44 --- /dev/null +++ b/patterns/simplehexagonalexample/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + 1.0.0-SNAPSHOT + simple-hexagonal-example + simpleHexagonalExample + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java new file mode 100644 index 0000000000..de8b2f4793 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/DailyQuoteMain.java @@ -0,0 +1,32 @@ +package com.baeldung.simplehexagonalex; + +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 com.baeldung.simplehexagonalex.controller.QuoteCliController; +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; + +@SpringBootApplication +public class DailyQuoteMain implements CommandLineRunner { + + private static final Logger LOG = LoggerFactory.getLogger(DailyQuoteMain.class); + @Autowired + private QuoteCliController quoteCliController; + + public static void main(final String[] args) { + + SpringApplication.run(DailyQuoteMain.class, args); + } + + @Override + public void run(String... args) throws Exception { + + QuoteOfTheDay quoteOfTheDay = quoteCliController.getQuote("cliController"); + + LOG.info(quoteOfTheDay.toString()); + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java new file mode 100644 index 0000000000..9ecb2bf822 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteCliController.java @@ -0,0 +1,24 @@ +package com.baeldung.simplehexagonalex.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.domain.service.QuoteService; + +@Component +public class QuoteCliController { + + private static final Logger LOG = LoggerFactory.getLogger(QuoteCliController.class); + + @Autowired + private QuoteService quoteService; + + public QuoteOfTheDay getQuote(String userId) { + + LOG.info("Getting quote"); + return quoteService.getQuote(userId); + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java new file mode 100644 index 0000000000..061cff8cec --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/controller/QuoteRestController.java @@ -0,0 +1,24 @@ +package com.baeldung.simplehexagonalex.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.domain.service.QuoteService; + +@RestController +@RequestMapping("/quote") +public class QuoteRestController { + + @Autowired + private QuoteService quoteService; + + @GetMapping(path = "/{userId}") + public QuoteOfTheDay getEmployee(@PathVariable("userId") String userId) { + return quoteService.getQuote(userId); + } + +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java new file mode 100644 index 0000000000..c74c224c70 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/QuoteOfTheDay.java @@ -0,0 +1,56 @@ +package com.baeldung.simplehexagonalex.domain; + +import java.util.Objects; + +public class QuoteOfTheDay { + + private String userName; + private String quote; + private String provider; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getQuote() { + return quote; + } + + public void setQuote(String quote) { + this.quote = quote; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + @Override + public int hashCode() { + return Objects.hash(provider, quote, userName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + QuoteOfTheDay other = (QuoteOfTheDay) obj; + return Objects.equals(provider, other.provider) && Objects.equals(quote, other.quote) && Objects.equals(userName, other.userName); + } + + @Override + public String toString() { + return "QuoteOfTheDay [userName=" + userName + ", quote=" + quote + ", provider=" + provider + "]"; + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java new file mode 100644 index 0000000000..7e70cebd12 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/repository/QuoteOfTheDayFromProvider.java @@ -0,0 +1,8 @@ +package com.baeldung.simplehexagonalex.domain.repository; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; + +public interface QuoteOfTheDayFromProvider { + + QuoteOfTheDay getQuote(); +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java new file mode 100644 index 0000000000..16f7015ace --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteAggregator.java @@ -0,0 +1,22 @@ +package com.baeldung.simplehexagonalex.domain.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; + +@Service +public class QuoteAggregator implements QuoteService { + + @Autowired + private QuoteOfTheDayFromProvider quoteOfTheDayFromProvider; + + @Override + public QuoteOfTheDay getQuote(String userName) { + + QuoteOfTheDay quoteOfTheDay = quoteOfTheDayFromProvider.getQuote(); + quoteOfTheDay.setUserName(userName); + return quoteOfTheDay; + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java new file mode 100644 index 0000000000..300387a41d --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/domain/service/QuoteService.java @@ -0,0 +1,8 @@ +package com.baeldung.simplehexagonalex.domain.service; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; + +public interface QuoteService { + + QuoteOfTheDay getQuote(String userName); +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java new file mode 100644 index 0000000000..0cbbc60726 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuote.java @@ -0,0 +1,109 @@ +package com.baeldung.simplehexagonalex.repository.primary.quoteadapter; + +import java.util.List; +import java.util.Objects; + +public class ProviderQuote { + + private String quote; + private String length; + private String author; + private List tags; + private String category; + private String language; + private String date; + private String permalink; + private String id; + private String background; + private String title; + + public ProviderQuote() { + + } + + public ProviderQuote(String quote, String length, String author, List tags, String category, String language, String date, String permalink, String id, String background, String title) { + super(); + this.quote = quote; + this.length = length; + this.author = author; + this.tags = tags; + this.category = category; + this.language = language; + this.date = date; + this.permalink = permalink; + this.id = id; + this.background = background; + this.title = title; + } + + public String getQuote() { + return quote; + } + + public String getLength() { + return length; + } + + public String getAuthor() { + return author; + } + + public List getTags() { + return tags; + } + + public String getCategory() { + return category; + } + + public String getLanguage() { + return language; + } + + public String getDate() { + return date; + } + + public String getPermalink() { + return permalink; + } + + public String getId() { + return id; + } + + public String getBackground() { + return background; + } + + public String getTitle() { + return title; + } + + public void setId(String id) { + this.id = id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ProviderQuote other = (ProviderQuote) obj; + return Objects.equals(id, other.id); + } + + @Override + public String toString() { + return "TheysaysoQuote [quote=" + quote + ", length=" + length + ", " + "author=" + author + ", tags=" + tags + ", category=" + category + ", language=" + language + ", date=" + date + ", permalink=" + permalink + ", id=" + id + ", background=" + + background + ", title=" + title + "]"; + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java new file mode 100644 index 0000000000..ded08f7b18 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteAdapter.java @@ -0,0 +1,54 @@ +package com.baeldung.simplehexagonalex.repository.primary.quoteadapter; + +import java.net.URI; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; +import com.fasterxml.jackson.databind.ObjectMapper; + +@Service("providerQuoteAdapter") +@Primary +public class ProviderQuoteAdapter implements QuoteOfTheDayFromProvider { + + @Autowired + private Environment env; + + @Override + public QuoteOfTheDay getQuote() { + + QuoteOfTheDay quoteOfTheDay = new QuoteOfTheDay(); + ProviderQuoteEnvelope providerQuote; + try { + providerQuote = getProviderQuote(); + quoteOfTheDay.setQuote(providerQuote.getContents() + .getQuotes() + .get(0) + .getQuote()); + quoteOfTheDay.setProvider(providerQuote.getCopyright() + .getUrl()); + } catch (Exception e) { + quoteOfTheDay.setQuote("Unable to get the quote"); + quoteOfTheDay.setProvider("none"); + } + return quoteOfTheDay; + } + + private ProviderQuoteEnvelope getProviderQuote() throws Exception { + + HttpGet request = new HttpGet(URI.create(env.getProperty("theysayso.quote.provider.url"))); + CloseableHttpClient client = HttpClients.createDefault(); + CloseableHttpResponse response = client.execute(request); + ProviderQuoteEnvelope providersQuote = new ObjectMapper().readValue(response.getEntity() + .getContent(), ProviderQuoteEnvelope.class); + return providersQuote; + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java new file mode 100644 index 0000000000..611549f23d --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/repository/primary/quoteadapter/ProviderQuoteEnvelope.java @@ -0,0 +1,68 @@ +package com.baeldung.simplehexagonalex.repository.primary.quoteadapter; + +import java.util.List; + +public class ProviderQuoteEnvelope { + + private Success success; + private Contents contents; + private String baseurl; + private Copyright copyright; + + public ProviderQuoteEnvelope() { + + } + + public ProviderQuoteEnvelope(Success success, Contents contents, String baseurl, Copyright copyright) { + super(); + this.success = success; + this.contents = contents; + this.baseurl = baseurl; + this.copyright = copyright; + } + + public Success getSuccess() { + return success; + } + + public Contents getContents() { + return contents; + } + + public String getBaseurl() { + return baseurl; + } + + public Copyright getCopyright() { + return copyright; + } + + public class Contents { + private List quotes; + + public List getQuotes() { + return quotes; + } + } + + public class Copyright { + private int year; + private String url; + + public int getYear() { + return year; + } + + public String getUrl() { + return url; + } + } + + public class Success { + private int total; + + public int getTotal() { + return total; + } + } +} diff --git a/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java new file mode 100644 index 0000000000..54c28fc94e --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/java/com/baeldung/simplehexagonalex/reposity/mock/quoteadapter/MockQuoteAdapter.java @@ -0,0 +1,20 @@ +package com.baeldung.simplehexagonalex.reposity.mock.quoteadapter; + +import org.springframework.stereotype.Service; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; + +@Service +public class MockQuoteAdapter implements QuoteOfTheDayFromProvider { + + @Override + public QuoteOfTheDay getQuote() { + + QuoteOfTheDay quoteOfTheDay = new QuoteOfTheDay(); + quoteOfTheDay.setQuote("Mock quote of the day"); + quoteOfTheDay.setProvider("Mock Provider"); + + return quoteOfTheDay; + } +} diff --git a/patterns/simplehexagonalexample/src/main/resources/application.properties b/patterns/simplehexagonalexample/src/main/resources/application.properties new file mode 100644 index 0000000000..dd9413bfd5 --- /dev/null +++ b/patterns/simplehexagonalexample/src/main/resources/application.properties @@ -0,0 +1 @@ +theysayso.quote.provider.url=https://quotes.rest/qod?language=en \ No newline at end of file diff --git a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java new file mode 100644 index 0000000000..602f7ea5d4 --- /dev/null +++ b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/MockAccessProviderUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.simplehexagonalex.repository.primaryQuoteProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.reposity.mock.quoteadapter.MockQuoteAdapter; + +public class MockAccessProviderUnitTest { + + @Test + public void givenProvider_whenConnect_thenResponse() throws Exception { + + MockQuoteAdapter provider = new MockQuoteAdapter(); + QuoteOfTheDay quote = provider.getQuote(); + assertNotNull(quote); + assertEquals("Mock quote of the day", quote.getQuote()); + assertEquals("Mock Provider", quote.getProvider()); + } +} diff --git a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java new file mode 100644 index 0000000000..47e1dde136 --- /dev/null +++ b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/PrimaryAccessProviderIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.simplehexagonalex.repository.primaryQuoteProvider; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; + +import com.baeldung.simplehexagonalex.domain.QuoteOfTheDay; +import com.baeldung.simplehexagonalex.domain.repository.QuoteOfTheDayFromProvider; + +@SpringBootTest +public class PrimaryAccessProviderIntegrationTest { + + @Autowired + @Qualifier("providerQuoteAdapter") + QuoteOfTheDayFromProvider provider; + + @Test + public void whenQuoteProvider_thenResponse() throws Exception { + + QuoteOfTheDay quote = provider.getQuote(); + assertNotNull(quote); + assertThat(quote.getProvider()).contains("theysaidso"); + } +} diff --git a/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java new file mode 100644 index 0000000000..552b5d51c2 --- /dev/null +++ b/patterns/simplehexagonalexample/src/test/java/com/baeldung/simplehexagonalex/repository/primaryQuoteProvider/QuoteRequestIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.simplehexagonalex.repository.primaryQuoteProvider; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.Test; +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.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +@SpringBootTest +@AutoConfigureMockMvc +public class QuoteRequestIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenRestQuoteRequest_thenResponse() throws Exception { + + MvcResult result = this.mockMvc.perform(get("/quote/tester")) + .andDo(print()) + .andExpect(status().isOk()) + .andReturn(); + + String content = result.getResponse() + .getContentAsString(); + + assertThat(content).contains("tester"); + assertThat(content).contains("theysaidso"); + } +} \ No newline at end of file diff --git a/patterns/simplehexagonalexample/src/test/resources/application.properties b/patterns/simplehexagonalexample/src/test/resources/application.properties new file mode 100644 index 0000000000..dd9413bfd5 --- /dev/null +++ b/patterns/simplehexagonalexample/src/test/resources/application.properties @@ -0,0 +1 @@ +theysayso.quote.provider.url=https://quotes.rest/qod?language=en \ No newline at end of file