From 9a1d66f85251d8f3ec698df2be08baaf49fed5e3 Mon Sep 17 00:00:00 2001 From: 515882294 <515882294@qq.com> Date: Sun, 8 May 2022 16:00:41 +0800 Subject: [PATCH 01/12] BAEL-4463: What is com.sun.proxy.$Proxy --- .../reflection/proxy/AdvancedOperation.java | 7 ++++ .../reflection/proxy/BasicOperation.java | 7 ++++ .../reflection/proxy/DollarProxyUnitTest.java | 35 +++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java create mode 100644 core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java create mode 100644 core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/proxy/DollarProxyUnitTest.java diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java new file mode 100644 index 0000000000..3262b255f0 --- /dev/null +++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java @@ -0,0 +1,7 @@ +package com.baeldung.reflection.proxy; + +public interface AdvancedOperation { + int multiple(int a, int b); + + int divide(int a, int b); +} \ No newline at end of file diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java new file mode 100644 index 0000000000..b39eb0118e --- /dev/null +++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java @@ -0,0 +1,7 @@ +package com.baeldung.reflection.proxy; + +public interface BasicOperation { + int add(int a, int b); + + int sub(int a, int b); +} \ No newline at end of file diff --git a/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/proxy/DollarProxyUnitTest.java b/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/proxy/DollarProxyUnitTest.java new file mode 100644 index 0000000000..ef6c481778 --- /dev/null +++ b/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/proxy/DollarProxyUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.reflection.proxy; + +import org.junit.Test; + +import java.lang.reflect.Proxy; +import java.util.function.Consumer; + +import static org.junit.Assert.assertTrue; + +public class DollarProxyUnitTest { + @Test + public void givenProxy_whenInvokingGetProxyClass_thenGeneratingProxyClass() { + // Java 8: -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true + // Java 9 or later: -Djdk.proxy.ProxyGenerator.saveGeneratedFiles=true + // Note: System.setProperty() doesn't work here + // because ProxyGenerator.saveGeneratedFiles read its property only once. + // The @Test annotation in this method will generate a $Proxy class. + + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + Class[] interfaces = {BasicOperation.class, AdvancedOperation.class}; + Class proxyClass = Proxy.getProxyClass(classLoader, interfaces); + + boolean isProxyClass = Proxy.isProxyClass(proxyClass); + assertTrue(isProxyClass); + } + + @Test + public void givenReflection_whenReadingAnnotation_thenGeneratingProxyClass() { + FunctionalInterface instance = Consumer.class.getDeclaredAnnotation(FunctionalInterface.class); + Class clazz = instance.getClass(); + + boolean isProxyClass = Proxy.isProxyClass(clazz); + assertTrue(isProxyClass); + } +} From 386707c24f7edfeca9bf9c2bf32051cc2f3495dd Mon Sep 17 00:00:00 2001 From: panagiotiskakos Date: Sun, 15 May 2022 18:28:33 +0300 Subject: [PATCH 02/12] [JAVA-10577] workaround for circular dependencies --- .../src/main/resources/application.properties | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-security-modules/spring-security-saml/src/main/resources/application.properties b/spring-security-modules/spring-security-saml/src/main/resources/application.properties index 1d93a12737..fd7798dda9 100644 --- a/spring-security-modules/spring-security-saml/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-saml/src/main/resources/application.properties @@ -1,8 +1,9 @@ -saml.keystore.location=classpath:/saml/samlKeystore.jks +saml.keystore.location=classpath:/saml/saml-keystore # Password for Java keystore and item therein saml.keystore.password= saml.keystore.alias= # SAML Entity ID extracted from top of SAML metadata file saml.idp= -saml.sp=http://localhost:8080/saml/metadata \ No newline at end of file +saml.sp=http://localhost:8080/saml/metadata +spring.main.allow-circular-references=true \ No newline at end of file From 8fc971657a6a7017fb0f78a4efe4b762acb979bd Mon Sep 17 00:00:00 2001 From: Thibault Faure Date: Fri, 29 Apr 2022 22:13:19 +0200 Subject: [PATCH 03/12] BAEL-5383 code for the use delimiters article --- .../java9/delimiters/DelimiterDemo.java | 36 ++++++++++ .../delimiters/DelimiterDemoUnitTest.java | 67 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 core-java-modules/core-java-9/src/main/java/com/baeldung/java9/delimiters/DelimiterDemo.java create mode 100644 core-java-modules/core-java-9/src/test/java/com/baeldung/java9/delimiters/DelimiterDemoUnitTest.java diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/delimiters/DelimiterDemo.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/delimiters/DelimiterDemo.java new file mode 100644 index 0000000000..edc0b91d02 --- /dev/null +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/delimiters/DelimiterDemo.java @@ -0,0 +1,36 @@ +package com.baeldung.java9.delimiters; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.regex.Pattern; + +public class DelimiterDemo { + + public static List scannerWithDelimiter(String input, String delimiter) { + try (Scanner scan = new Scanner(input)) { + scan.useDelimiter(delimiter); + List result = new ArrayList(); + scan.forEachRemaining(result::add); + return result; + } + } + + public static List scannerWithDelimiterUsingPattern(String input, Pattern delimiter) { + try (Scanner scan = new Scanner(input)) { + scan.useDelimiter(delimiter); + List result = new ArrayList(); + scan.forEachRemaining(result::add); + return result; + } + } + + public static List baseScanner(String input) { + try (Scanner scan = new Scanner(input)) { + List result = new ArrayList(); + scan.forEachRemaining(result::add); + return result; + } + } + +} diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/delimiters/DelimiterDemoUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/delimiters/DelimiterDemoUnitTest.java new file mode 100644 index 0000000000..1c1fffe362 --- /dev/null +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/delimiters/DelimiterDemoUnitTest.java @@ -0,0 +1,67 @@ +package com.baeldung.java9.delimiters; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.function.BiFunction; +import java.util.regex.Pattern; + +import org.junit.jupiter.api.Test; + +class DelimiterDemoUnitTest { + + @Test + void givenSimpleCharacterDelimiter_whenScannerWithDelimiter_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiter, "Welcome to Baeldung", "\\s", Arrays.asList("Welcome", "to", "Baeldung")); + } + + @Test + void givenStringDelimiter_whenScannerWithDelimiter_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiter, "HelloBaeldungHelloWorld", "Hello", Arrays.asList("Baeldung", "World")); + } + + @Test + void givenVariousPossibleDelimiters_whenScannerWithDelimiter_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiter, "Welcome to Baeldung.\nThank you for reading.\nThe team", "\n|\\s", Arrays.asList("Welcome", "to", "Baeldung.", "Thank", "you", "for", "reading.", "The", "team")); + } + + @Test + void givenWildcardRegexDelimiter_whenScannerWithDelimiter_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiter, "1aaaaaaa2aa3aaa4", "a+", Arrays.asList("1", "2", "3", "4")); + } + + @Test + void givenSimpleCharacterDelimiter_whenScannerWithDelimiterUsingPattern_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiterUsingPattern, "Welcome to Baeldung", Pattern.compile("\\s"), Arrays.asList("Welcome", "to", "Baeldung")); + } + + @Test + void givenStringDelimiter_whenScannerWithDelimiterUsingPattern_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiterUsingPattern, "HelloBaeldungHelloWorld", Pattern.compile("Hello"), Arrays.asList("Baeldung", "World")); + } + + @Test + void givenVariousPossibleDelimiters_whenScannerWithDelimiterUsingPattern_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiterUsingPattern, "Welcome to Baeldung.\nThank you for reading.\nThe team", Pattern.compile("\n|\\s"), Arrays.asList("Welcome", "to", "Baeldung.", "Thank", "you", "for", "reading.", "The", "team")); + } + + @Test + void givenWildcardRegexDelimiters_whenScannerWithDelimiterUsingPattern_ThenInputIsCorrectlyParsed() { + checkOutput(DelimiterDemo::scannerWithDelimiterUsingPattern, "1aaaaaaa2aa3aaa4", Pattern.compile("a*"), Arrays.asList("1", "2", "3", "4")); + } + + void checkOutput(BiFunction> function, String input, String delimiter, List expectedOutput) { + assertEquals(expectedOutput, function.apply(input, delimiter)); + } + + void checkOutput(BiFunction> function, String input, Pattern delimiter, List expectedOutput) { + assertEquals(expectedOutput, function.apply(input, delimiter)); + } + + @Test + void whenBaseScanner_ThenWhitespacesAreUsedAsDelimiters() { + assertEquals(List.of("Welcome", "at", "Baeldung"), DelimiterDemo.baseScanner("Welcome at Baeldung")); + } + +} From 365f029e3a3fa5b22fd89c47d8b87254e0ccaf8a Mon Sep 17 00:00:00 2001 From: Alireza Ghasemi Date: Mon, 16 May 2022 17:34:55 +0200 Subject: [PATCH 04/12] Add tutorial files for ResultSet2JSON Article (#11912) * Add tutorial files * Move script to new folder * Use Maven/H2 instead of JBang/DuckDB * Use Java 8 * Usen an older versio of JOOQ * Format according to Beldung Intellij guide * Remove dangling commit * Use 2-space indentation * Apply formatting from Eclipse * Add unit test * Add assertion * Change test names * Change method names Co-authored-by: root Co-authored-by: Alireza Ghasemi --- .../core-java-persistence-2/example.csv | 4 + .../core-java-persistence-2/pom.xml | 18 ++- .../resultset2json/ResultSet2JSON.java | 137 ++++++++++++++++++ .../ResultSet2JSONUnitTest.java | 75 ++++++++++ 4 files changed, 231 insertions(+), 3 deletions(-) create mode 100644 persistence-modules/core-java-persistence-2/example.csv create mode 100755 persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultset2json/ResultSet2JSON.java create mode 100644 persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultset2json/ResultSet2JSONUnitTest.java diff --git a/persistence-modules/core-java-persistence-2/example.csv b/persistence-modules/core-java-persistence-2/example.csv new file mode 100644 index 0000000000..d7715864d1 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/example.csv @@ -0,0 +1,4 @@ +Username,Id,First name,Last name +doe1,7173,John,Doe +smith3,3722,Dana,Smith +john22,5490,John,Wang \ No newline at end of file diff --git a/persistence-modules/core-java-persistence-2/pom.xml b/persistence-modules/core-java-persistence-2/pom.xml index 780c1fcfca..c7547e1c46 100644 --- a/persistence-modules/core-java-persistence-2/pom.xml +++ b/persistence-modules/core-java-persistence-2/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 com.baeldung.core-java-persistence-2 core-java-persistence-2 @@ -41,6 +39,20 @@ mssql-jdbc ${mssql.driver.version} + + + + org.jooq + jooq + 3.11.11 + + + + org.json + json + 20220320 + + diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultset2json/ResultSet2JSON.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultset2json/ResultSet2JSON.java new file mode 100755 index 0000000000..bbe3ccf9a0 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultset2json/ResultSet2JSON.java @@ -0,0 +1,137 @@ +package com.baeldung.resultset2json; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.jooq.Record; +import org.jooq.RecordMapper; +import org.jooq.impl.DSL; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONArray; + +public class ResultSet2JSON { + + public static void main(String... args) throws ClassNotFoundException, SQLException { + + ResultSet2JSON testClass = new ResultSet2JSON(); + testClass.convertWithoutJOOQ(); + } + + public void convertWithoutJOOQ() throws ClassNotFoundException, SQLException { + Class.forName("org.h2.Driver"); + Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc", "user", "password"); + + // Create a table + Statement stmt = dbConnection.createStatement(); + stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')"); + ResultSet resultSet = stmt.executeQuery("SELECT * FROM words"); + + JSONArray result1 = resultSet2JdbcWithoutJOOQ(resultSet); + System.out.println(result1); + + resultSet.close(); + } + + public void convertUsingJOOQDefaultApproach() throws ClassNotFoundException, SQLException { + Class.forName("org.h2.Driver"); + Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc", "user", "password"); + // Create a table + Statement stmt = dbConnection.createStatement(); + stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')"); + ResultSet resultSet = stmt.executeQuery("SELECT * FROM words"); + + JSONObject result1 = resultSet2JdbcUsingJOOQDefaultApproach(resultSet, dbConnection); + System.out.println(result1); + + resultSet.close(); + } + + public void convertUsingCustomisedJOOQ() throws ClassNotFoundException, SQLException { + Class.forName("org.h2.Driver"); + Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc", "user", "password"); + // Create a table + Statement stmt = dbConnection.createStatement(); + stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')"); + ResultSet resultSet = stmt.executeQuery("SELECT * FROM words"); + + JSONArray result1 = resultSet2JdbcUsingCustomisedJOOQ(resultSet, dbConnection); + System.out.println(result1); + + resultSet.close(); + } + + public static JSONArray resultSet2JdbcWithoutJOOQ(ResultSet resultSet) throws SQLException { + ResultSetMetaData md = resultSet.getMetaData(); + int numCols = md.getColumnCount(); + List colNames = IntStream.range(0, numCols) + .mapToObj(i -> { + try { + return md.getColumnName(i + 1); + } catch (SQLException e) { + + e.printStackTrace(); + return "?"; + } + }) + .collect(Collectors.toList()); + + JSONArray result = new JSONArray(); + while (resultSet.next()) { + JSONObject row = new JSONObject(); + colNames.forEach(cn -> { + try { + row.put(cn, resultSet.getObject(cn)); + } catch (JSONException | SQLException e) { + + e.printStackTrace(); + } + }); + result.put(row); + } + return result; + } + + public static JSONObject resultSet2JdbcUsingJOOQDefaultApproach(ResultSet resultSet, Connection dbConnection) throws SQLException { + JSONObject result = new JSONObject(DSL.using(dbConnection) + .fetch(resultSet) + .formatJSON()); + return result; + } + + public static JSONArray resultSet2JdbcUsingCustomisedJOOQ(ResultSet resultSet, Connection dbConnection) throws SQLException { + ResultSetMetaData md = resultSet.getMetaData(); + int numCols = md.getColumnCount(); + List colNames = IntStream.range(0, numCols) + .mapToObj(i -> { + try { + return md.getColumnName(i + 1); + } catch (SQLException e) { + + e.printStackTrace(); + return "?"; + } + }) + .collect(Collectors.toList()); + + List json = DSL.using(dbConnection) + .fetch(resultSet) + .map(new RecordMapper() { + + @Override + public JSONObject map(Record r) { + JSONObject obj = new JSONObject(); + colNames.forEach(cn -> obj.put(cn, r.get(cn))); + return obj; + } + }); + return new JSONArray(json); + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultset2json/ResultSet2JSONUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultset2json/ResultSet2JSONUnitTest.java new file mode 100644 index 0000000000..f3dd8350fa --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultset2json/ResultSet2JSONUnitTest.java @@ -0,0 +1,75 @@ +package com.baeldung.resultset2json; + +import static com.baeldung.resultset2json.ResultSet2JSON.resultSet2JdbcWithoutJOOQ; +import static com.baeldung.resultset2json.ResultSet2JSON.resultSet2JdbcUsingJOOQDefaultApproach; +import static com.baeldung.resultset2json.ResultSet2JSON.resultSet2JdbcUsingCustomisedJOOQ; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ResultSet2JSONUnitTest { + JSONObject object = new JSONObject( + "{\"records\":[[\"doe1\",\"7173\",\"John\",\"Doe\"],[\"smith3\",\"3722\",\"Dana\",\"Smith\"],[\"john22\",\"5490\",\"John\",\"Wang\"]],\"fields\":[{\"schema\":\"PUBLIC\",\"name\":\"USERNAME\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"},{\"schema\":\"PUBLIC\",\"name\":\"ID\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"},{\"schema\":\"PUBLIC\",\"name\":\"First name\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"},{\"schema\":\"PUBLIC\",\"name\":\"Last name\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"}]}"); + + JSONArray array = new JSONArray( + "[{\"USERNAME\":\"doe1\",\"First name\":\"John\",\"ID\":\"7173\",\"Last name\":\"Doe\"},{\"USERNAME\":\"smith3\",\"First name\":\"Dana\",\"ID\":\"3722\",\"Last name\":\"Smith\"},{\"USERNAME\":\"john22\",\"First name\":\"John\",\"ID\":\"5490\",\"Last name\":\"Wang\"}]"); + + @Test + void whenResultSetConvertedWithoutJOOQ_shouldMatchJSON() throws SQLException, ClassNotFoundException { + Class.forName("org.h2.Driver"); + Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc1", "user", "password"); + + // Create a table + Statement stmt = dbConnection.createStatement(); + stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')"); + ResultSet resultSet = stmt.executeQuery("SELECT * FROM words"); + + JSONArray result1 = resultSet2JdbcWithoutJOOQ(resultSet); + + resultSet.close(); + + assertTrue(array.similar(result1)); + } + + @Test + void whenResultSetConvertedUsingJOOQDefaultApproach_shouldMatchJSON() throws SQLException, ClassNotFoundException { + Class.forName("org.h2.Driver"); + Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc2", "user", "password"); + // Create a table + Statement stmt = dbConnection.createStatement(); + stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')"); + ResultSet resultSet = stmt.executeQuery("SELECT * FROM words"); + + JSONObject result2 = resultSet2JdbcUsingJOOQDefaultApproach(resultSet, dbConnection); + + resultSet.close(); + + assertTrue(object.similar(result2)); + } + + @Test + void whenResultSetConvertedUsingCustomisedJOOQ_shouldMatchJSON() throws SQLException, ClassNotFoundException { + Class.forName("org.h2.Driver"); + Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc3", "user", "password"); + // Create a table + Statement stmt = dbConnection.createStatement(); + stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')"); + ResultSet resultSet = stmt.executeQuery("SELECT * FROM words"); + + JSONArray result3 = resultSet2JdbcUsingCustomisedJOOQ(resultSet, dbConnection); + + resultSet.close(); + + assertTrue(array.similar(result3)); + } + +} From d848af386a0cc984ed2fe596b590301fd252e364 Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Tue, 17 May 2022 09:44:35 +0500 Subject: [PATCH 05/12] Updated README.md added link back to the article: https://www.baeldung.com/java-httpclient-post --- core-java-modules/core-java-httpclient/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-httpclient/README.md b/core-java-modules/core-java-httpclient/README.md index 24ff7d9941..712328a123 100644 --- a/core-java-modules/core-java-httpclient/README.md +++ b/core-java-modules/core-java-httpclient/README.md @@ -3,4 +3,4 @@ This module contains articles about Java HttpClient ### Relevant articles -- TODO +- [Posting with Java HttpClient](https://www.baeldung.com/java-httpclient-post) From bb7edc30e4f1644dc412c6a4aa493b8f200f7f14 Mon Sep 17 00:00:00 2001 From: Asjad J <97493880+Asjad-J@users.noreply.github.com> Date: Tue, 17 May 2022 09:58:36 +0500 Subject: [PATCH 06/12] Updated README.md added link back to the article: https://www.baeldung.com/java-reverse-number --- java-numbers-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-numbers-4/README.md b/java-numbers-4/README.md index c18a5ebe6f..2a77992c8f 100644 --- a/java-numbers-4/README.md +++ b/java-numbers-4/README.md @@ -8,3 +8,4 @@ - [Convert Byte Size Into a Human-Readable Format in Java](https://www.baeldung.com/java-human-readable-byte-size) - [Convert boolean to int in Java](https://www.baeldung.com/java-boolean-to-int) - [Generate a Random Value From an Enum](https://www.baeldung.com/java-enum-random-value) +- [Reverse a Number in Java](https://www.baeldung.com/java-reverse-number) From 177f912393c0e0110a9b9b01862d7a5ff053508a Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Tue, 17 May 2022 16:07:21 +0100 Subject: [PATCH 07/12] Source code for Lightrun articles --- lightrun/README.md | 29 +++++++ lightrun/api-service/.gitignore | 33 +++++++ lightrun/api-service/pom.xml | 45 ++++++++++ .../apiservice/ApiServiceApplication.java | 13 +++ .../apiservice/RequestIdGenerator.java | 33 +++++++ .../apiservice/RestTemplateConfig.java | 20 +++++ .../com/baeldung/apiservice/WebConfig.java | 17 ++++ .../adapters/http/TaskResponse.java | 11 +++ .../adapters/http/TasksController.java | 54 ++++++++++++ .../adapters/http/UnknownTaskException.java | 4 + .../adapters/http/UserResponse.java | 4 + .../apiservice/adapters/tasks/Task.java | 11 +++ .../adapters/tasks/TaskRepository.java | 30 +++++++ .../apiservice/adapters/users/User.java | 4 + .../adapters/users/UserRepository.java | 31 +++++++ .../src/main/resources/application.properties | 2 + lightrun/pom.xml | 17 ++++ lightrun/tasks-service/.gitignore | 33 +++++++ lightrun/tasks-service/pom.xml | 67 +++++++++++++++ .../baeldung/tasksservice/ArtemisConfig.java | 23 +++++ .../tasksservice/TasksServiceApplication.java | 13 +++ .../adapters/http/CreateTaskRequest.java | 15 ++++ .../adapters/http/PatchTaskRequest.java | 17 ++++ .../adapters/http/TaskResponse.java | 22 +++++ .../adapters/http/TasksController.java | 86 +++++++++++++++++++ .../adapters/http/http-client.env.json | 5 ++ .../tasksservice/adapters/http/tasks.http | 35 ++++++++ .../adapters/jms/JmsConsumer.java | 18 ++++ .../adapters/repository/TaskRecord.java | 80 +++++++++++++++++ .../adapters/repository/TasksRepository.java | 28 ++++++ .../service/DeletedUserService.java | 27 ++++++ .../tasksservice/service/TasksService.java | 72 ++++++++++++++++ .../service/UnknownTaskException.java | 24 ++++++ .../src/main/resources/application.properties | 13 +++ .../migration/V1_0_0__create-tasks-table.sql | 13 +++ lightrun/users-service/.gitignore | 33 +++++++ lightrun/users-service/README.md | 29 +++++++ lightrun/users-service/pom.xml | 63 ++++++++++++++ .../com/baeldung/usersservice/JmsConfig.java | 29 +++++++ .../usersservice/UsersServiceApplication.java | 13 +++ .../adapters/http/CreateUserRequest.java | 15 ++++ .../adapters/http/PatchUserRequest.java | 17 ++++ .../adapters/http/UserResponse.java | 16 ++++ .../adapters/http/UsersController.java | 69 +++++++++++++++ .../adapters/http/http-client.env.json | 5 ++ .../usersservice/adapters/http/users.http | 25 ++++++ .../usersservice/adapters/jms/JmsSender.java | 26 ++++++ .../adapters/repository/UserRecord.java | 47 ++++++++++ .../adapters/repository/UsersRepository.java | 19 ++++ .../service/UnknownUserException.java | 24 ++++++ .../usersservice/service/UsersService.java | 61 +++++++++++++ .../src/main/resources/application.properties | 10 +++ .../migration/V1_0_0__create-users-table.sql | 8 ++ pom.xml | 2 + 54 files changed, 1460 insertions(+) create mode 100644 lightrun/README.md create mode 100644 lightrun/api-service/.gitignore create mode 100644 lightrun/api-service/pom.xml create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/ApiServiceApplication.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/RequestIdGenerator.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/RestTemplateConfig.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/WebConfig.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TaskResponse.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TasksController.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UnknownTaskException.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UserResponse.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/Task.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/TaskRepository.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/User.java create mode 100644 lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/UserRepository.java create mode 100644 lightrun/api-service/src/main/resources/application.properties create mode 100644 lightrun/pom.xml create mode 100644 lightrun/tasks-service/.gitignore create mode 100644 lightrun/tasks-service/pom.xml create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/ArtemisConfig.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/TasksServiceApplication.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/CreateTaskRequest.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/PatchTaskRequest.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TaskResponse.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TasksController.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/http-client.env.json create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/tasks.http create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/jms/JmsConsumer.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TaskRecord.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TasksRepository.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/DeletedUserService.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/TasksService.java create mode 100644 lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/UnknownTaskException.java create mode 100644 lightrun/tasks-service/src/main/resources/application.properties create mode 100644 lightrun/tasks-service/src/main/resources/db/migration/V1_0_0__create-tasks-table.sql create mode 100644 lightrun/users-service/.gitignore create mode 100644 lightrun/users-service/README.md create mode 100644 lightrun/users-service/pom.xml create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/JmsConfig.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/UsersServiceApplication.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/CreateUserRequest.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/PatchUserRequest.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UserResponse.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UsersController.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/http-client.env.json create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/users.http create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/jms/JmsSender.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UserRecord.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UsersRepository.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UnknownUserException.java create mode 100644 lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UsersService.java create mode 100644 lightrun/users-service/src/main/resources/application.properties create mode 100644 lightrun/users-service/src/main/resources/db/migration/V1_0_0__create-users-table.sql diff --git a/lightrun/README.md b/lightrun/README.md new file mode 100644 index 0000000000..732d9b03cd --- /dev/null +++ b/lightrun/README.md @@ -0,0 +1,29 @@ +# Lightrun Example Application - Tasks Management + +This application exists as an example for the Lightrun series of articles. + +## Building +This application requires [Apache Maven](https://maven.apache.org/) and [Java 17+](https://www.oracle.com/java/technologies/downloads/). + +Building the code is done by executing: +``` +$ mvn install +``` +from the top level. + +## Running +The application consists of three services: +* Tasks +* Users +* API + +These are all Spring Boot applications. + +The Tasks and Users services exist as microservices for managing one facet of data. Each uses a database, and utilise a JMS queue between them as well. For convenience this infrastructure is all embedded in the applications. + +This does mean that the startup order is important. The JMS queue exists within the Tasks service and is connected to from the Users service. As such, the Tasks service must be started before the others. + +Each service can be started either by executing `mvn spring-boot:run` from within the appropriate directory. Alternatively, as Spring Boot applications, the build will produce an executable JAR file within the `target` directory that can be executed as, for example: +``` +$ java -jar ./target/tasks-service-0.0.1-SNAPSHOT.jar +``` diff --git a/lightrun/api-service/.gitignore b/lightrun/api-service/.gitignore new file mode 100644 index 0000000000..549e00a2a9 --- /dev/null +++ b/lightrun/api-service/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/lightrun/api-service/pom.xml b/lightrun/api-service/pom.xml new file mode 100644 index 0000000000..c72d66748c --- /dev/null +++ b/lightrun/api-service/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.7 + + + com.baeldung + api-service + 0.0.1-SNAPSHOT + api-service + Aggregator Service for LightRun Article + + 17 + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/ApiServiceApplication.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/ApiServiceApplication.java new file mode 100644 index 0000000000..4d7e2f3ff7 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/ApiServiceApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.apiservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ApiServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(ApiServiceApplication.class, args); + } + +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/RequestIdGenerator.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/RequestIdGenerator.java new file mode 100644 index 0000000000..3ad137ca4d --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/RequestIdGenerator.java @@ -0,0 +1,33 @@ +package com.baeldung.apiservice; + +import org.slf4j.MDC; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.UUID; + +@Component +public class RequestIdGenerator implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String requestId = UUID.randomUUID().toString(); + + MDC.put(RequestIdGenerator.class.getCanonicalName(), requestId); + response.addHeader("X-Request-Id", requestId); + + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + MDC.remove(RequestIdGenerator.class.getCanonicalName()); + } + + public static String getRequestId() { + return MDC.get(RequestIdGenerator.class.getCanonicalName()); + } +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/RestTemplateConfig.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/RestTemplateConfig.java new file mode 100644 index 0000000000..278e1520c4 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/RestTemplateConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.apiservice; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) { + return builder + .additionalInterceptors((request, body, execution) -> { + request.getHeaders().add("X-Request-Id", RequestIdGenerator.getRequestId()); + + return execution.execute(request, body); + }) + .build(); + } +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/WebConfig.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/WebConfig.java new file mode 100644 index 0000000000..9edfcff6f6 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/WebConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.apiservice; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Autowired + private RequestIdGenerator requestIdGenerator; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(requestIdGenerator); + } +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TaskResponse.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TaskResponse.java new file mode 100644 index 0000000000..cec3105c04 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TaskResponse.java @@ -0,0 +1,11 @@ +package com.baeldung.apiservice.adapters.http; + +import java.time.Instant; + +public record TaskResponse(String id, + String title, + Instant created, + UserResponse createdBy, + UserResponse assignedTo, + String status) { +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TasksController.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TasksController.java new file mode 100644 index 0000000000..e11eaac35f --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/TasksController.java @@ -0,0 +1,54 @@ +package com.baeldung.apiservice.adapters.http; + +import com.baeldung.apiservice.adapters.tasks.Task; +import com.baeldung.apiservice.adapters.tasks.TaskRepository; +import com.baeldung.apiservice.adapters.users.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/") +@RestController +public class TasksController { + @Autowired + private TaskRepository taskRepository; + @Autowired + private UserRepository userRepository; + + @GetMapping("/{id}") + public TaskResponse getTaskById(@PathVariable("id") String id) { + Task task = taskRepository.getTaskById(id); + + if (task == null) { + throw new UnknownTaskException(); + } + + return buildResponse(task); + } + + private TaskResponse buildResponse(Task task) { + return new TaskResponse(task.id(), + task.title(), + task.created(), + getUser(task.createdBy()), + getUser(task.assignedTo()), + task.status()); + } + + private UserResponse getUser(String userId) { + if (userId == null) { + return null; + } + + var user = userRepository.getUserById(userId); + if (user == null) { + return null; + } + + return new UserResponse(user.id(), user.name()); + } + @ExceptionHandler(UnknownTaskException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public void handleUnknownTask() { + } +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UnknownTaskException.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UnknownTaskException.java new file mode 100644 index 0000000000..1635ca8796 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UnknownTaskException.java @@ -0,0 +1,4 @@ +package com.baeldung.apiservice.adapters.http; + +public class UnknownTaskException extends RuntimeException { +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UserResponse.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UserResponse.java new file mode 100644 index 0000000000..f311b895a8 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/http/UserResponse.java @@ -0,0 +1,4 @@ +package com.baeldung.apiservice.adapters.http; + +public record UserResponse(String id, String name) { +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/Task.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/Task.java new file mode 100644 index 0000000000..a83192f188 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/Task.java @@ -0,0 +1,11 @@ +package com.baeldung.apiservice.adapters.tasks; + +import java.time.Instant; + +public record Task(String id, + String title, + Instant created, + String createdBy, + String assignedTo, + String status) { +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/TaskRepository.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/TaskRepository.java new file mode 100644 index 0000000000..49ffa51818 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/tasks/TaskRepository.java @@ -0,0 +1,30 @@ +package com.baeldung.apiservice.adapters.tasks; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Repository; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Repository +public class TaskRepository { + @Autowired + private RestTemplate restTemplate; + + @Value("${tasks-service.url}") + private String tasksService; + + public Task getTaskById(String id) { + var uri = UriComponentsBuilder.fromUriString(tasksService) + .path(id) + .build() + .toUri(); + + try { + return restTemplate.getForObject(uri, Task.class); + } catch (HttpClientErrorException.NotFound e) { + return null; + } + } +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/User.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/User.java new file mode 100644 index 0000000000..a3a53c0805 --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/User.java @@ -0,0 +1,4 @@ +package com.baeldung.apiservice.adapters.users; + +public record User(String id, String name) { +} diff --git a/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/UserRepository.java b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/UserRepository.java new file mode 100644 index 0000000000..5a0e4eb64f --- /dev/null +++ b/lightrun/api-service/src/main/java/com/baeldung/apiservice/adapters/users/UserRepository.java @@ -0,0 +1,31 @@ +package com.baeldung.apiservice.adapters.users; + +import com.baeldung.apiservice.adapters.users.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Repository; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Repository +public class UserRepository { + @Autowired + private RestTemplate restTemplate; + + @Value("${users-service.url}") + private String usersService; + + public User getUserById(String id) { + var uri = UriComponentsBuilder.fromUriString(usersService) + .path(id) + .build() + .toUri(); + + try { + return restTemplate.getForObject(uri, User.class); + } catch (HttpClientErrorException.NotFound e) { + return null; + } + } +} diff --git a/lightrun/api-service/src/main/resources/application.properties b/lightrun/api-service/src/main/resources/application.properties new file mode 100644 index 0000000000..f3f227f46f --- /dev/null +++ b/lightrun/api-service/src/main/resources/application.properties @@ -0,0 +1,2 @@ +users-service.url=http://localhost:8081 +tasks-service.url=http://localhost:8082 \ No newline at end of file diff --git a/lightrun/pom.xml b/lightrun/pom.xml new file mode 100644 index 0000000000..cfe275848f --- /dev/null +++ b/lightrun/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + com.baelduung + lightrun-demo + 0.0.1-SNAPSHOT + pom + lightrun + Services for LightRun Article + + + tasks-service + users-service + api-service + + diff --git a/lightrun/tasks-service/.gitignore b/lightrun/tasks-service/.gitignore new file mode 100644 index 0000000000..549e00a2a9 --- /dev/null +++ b/lightrun/tasks-service/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/lightrun/tasks-service/pom.xml b/lightrun/tasks-service/pom.xml new file mode 100644 index 0000000000..e56a3a9edf --- /dev/null +++ b/lightrun/tasks-service/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.7 + + + com.baeldung + tasks-service + 0.0.1-SNAPSHOT + tasks-service + Tasks Service for LightRun Article + + 17 + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-artemis + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.flywaydb + flyway-core + + + + com.h2database + h2 + runtime + + + org.apache.activemq + artemis-jms-server + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/ArtemisConfig.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/ArtemisConfig.java new file mode 100644 index 0000000000..56ee3bbc93 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/ArtemisConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.tasksservice; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.jms.artemis.ArtemisConfigurationCustomizer; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ArtemisConfig implements ArtemisConfigurationCustomizer { + @Value("${spring.artemis.host}") + private String hostname; + + @Value("${spring.artemis.port}") + private int port; + + @Override + public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) { + try { + configuration.addAcceptorConfiguration("remote", "tcp://" + hostname + ":" + port); + } catch (Exception e) { + throw new RuntimeException("Failed to configure Artemis listener", e); + } + } +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/TasksServiceApplication.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/TasksServiceApplication.java new file mode 100644 index 0000000000..f8e0d64c0c --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/TasksServiceApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.tasksservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TasksServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(TasksServiceApplication.class, args); + } + +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/CreateTaskRequest.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/CreateTaskRequest.java new file mode 100644 index 0000000000..64acea8b1b --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/CreateTaskRequest.java @@ -0,0 +1,15 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.adapters.http; + +public record CreateTaskRequest(String title, String createdBy) { +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/PatchTaskRequest.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/PatchTaskRequest.java new file mode 100644 index 0000000000..20974b1c1d --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/PatchTaskRequest.java @@ -0,0 +1,17 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.adapters.http; + +import java.util.Optional; + +public record PatchTaskRequest(Optional status, Optional assignedTo) { +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TaskResponse.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TaskResponse.java new file mode 100644 index 0000000000..ca13b2ee3d --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TaskResponse.java @@ -0,0 +1,22 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.adapters.http; + +import java.time.Instant; + +public record TaskResponse(String id, + String title, + Instant created, + String createdBy, + String assignedTo, + String status) { +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TasksController.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TasksController.java new file mode 100644 index 0000000000..6502e43883 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/TasksController.java @@ -0,0 +1,86 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.adapters.http; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import com.baeldung.tasksservice.adapters.repository.TaskRecord; +import com.baeldung.tasksservice.service.TasksService; +import com.baeldung.tasksservice.service.UnknownTaskException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/") +class TasksController { + @Autowired + private TasksService tasksService; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public TaskResponse createTask(@RequestBody CreateTaskRequest body) { + var task = tasksService.createTask(body.title(), body.createdBy()); + return buildResponse(task); + } + + @GetMapping + public List searchTasks(@RequestParam("status") Optional status, + @RequestParam("createdBy") Optional createdBy) { + var tasks = tasksService.search(status, createdBy); + + return tasks.stream() + .map(this::buildResponse) + .collect(Collectors.toList()); + } + + @GetMapping("/{id}") + public TaskResponse getTask(@PathVariable("id") String id) { + var task = tasksService.getTaskById(id); + return buildResponse(task); + } + + @DeleteMapping("/{id}") + public void deleteTask(@PathVariable("id") String id) { + tasksService.deleteTaskById(id); + } + + @PatchMapping("/{id}") + public TaskResponse patchTask(@PathVariable("id") String id, + @RequestBody PatchTaskRequest body) { + var task = tasksService.updateTask(id, body.status(), body.assignedTo()); + + return buildResponse(task); + } + + private TaskResponse buildResponse(final TaskRecord task) { + return new TaskResponse(task.getId(), task.getTitle(), task.getCreated(), task.getCreatedBy(), + task.getAssignedTo(), task.getStatus()); + } + + @ExceptionHandler(UnknownTaskException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public void handleUnknownTask() { + } +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/http-client.env.json b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/http-client.env.json new file mode 100644 index 0000000000..f27fc4325b --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/http-client.env.json @@ -0,0 +1,5 @@ +{ + "local-tasks": { + "host": "localhost:8082" + } +} \ No newline at end of file diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/tasks.http b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/tasks.http new file mode 100644 index 0000000000..eb7d578ac9 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/http/tasks.http @@ -0,0 +1,35 @@ +GET http://{{host}}/createdemoapplication1 HTTP/1.1 + +### +GET http://{{host}}/unknown HTTP/1.1 + +### +GET http://{{host}}?status=PENDING + +### +GET http://{{host}}?createdBy=baeldung + +### +GET http://{{host}}?createdBy=baeldung&status=COMPLETE + +### +DELETE http://{{host}}/createdemoapplication1 HTTP/1.1 + +### +DELETE http://{{host}}/unknown HTTP/1.1 + +### +POST http://{{host}} HTTP/1.1 +Content-Type: application/json + +{ + "title": "My Task", + "createdBy": "graham" +} +### +PATCH http://{{host}}/createdemoapplication1 HTTP/1.1 +Content-Type: application/json + +{ + "status": "COMPLETE" +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/jms/JmsConsumer.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/jms/JmsConsumer.java new file mode 100644 index 0000000000..d5a705f56f --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/jms/JmsConsumer.java @@ -0,0 +1,18 @@ +package com.baeldung.tasksservice.adapters.jms; + +import org.springframework.stereotype.Service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jms.annotation.JmsListener; + +import com.baeldung.tasksservice.service.DeletedUserService; + +@Service +public class JmsConsumer { + @Autowired + private DeletedUserService deletedUserService; + + @JmsListener(destination = "deleted_user") + public void receive(String user) { + deletedUserService.handleDeletedUser(user); + } +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TaskRecord.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TaskRecord.java new file mode 100644 index 0000000000..6646258c22 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TaskRecord.java @@ -0,0 +1,80 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.adapters.repository; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.Instant; + +@Entity +@Table(name = "tasks") +public class TaskRecord { + @Id + @Column(name = "task_id") + private String id; + private String title; + @Column(name = "created_at") + private Instant created; + @Column(name = "created_by") + private String createdBy; + @Column(name = "assigned_to") + private String assignedTo; + private String status; + + public TaskRecord(final String id, final String title, final Instant created, final String createdBy, + final String assignedTo, final String status) { + this.id = id; + this.title = title; + this.created = created; + this.createdBy = createdBy; + this.assignedTo = assignedTo; + this.status = status; + } + + private TaskRecord() { + // Needed for JPA + } + + public String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public Instant getCreated() { + return created; + } + + public String getCreatedBy() { + return createdBy; + } + + public String getAssignedTo() { + return assignedTo; + } + + public String getStatus() { + return status; + } + + public void setAssignedTo(final String assignedTo) { + this.assignedTo = assignedTo; + } + + public void setStatus(final String status) { + this.status = status; + } +} \ No newline at end of file diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TasksRepository.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TasksRepository.java new file mode 100644 index 0000000000..9b6f041fd2 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/adapters/repository/TasksRepository.java @@ -0,0 +1,28 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.adapters.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TasksRepository extends JpaRepository { + List findByStatus(String status); + + List findByCreatedBy(String createdBy); + + List findByStatusAndCreatedBy(String status, String createdBy); + + List findByAssignedTo(String assignedTo); +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/DeletedUserService.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/DeletedUserService.java new file mode 100644 index 0000000000..50d35d3f93 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/DeletedUserService.java @@ -0,0 +1,27 @@ +package com.baeldung.tasksservice.service; + +import javax.transaction.Transactional; + +import com.baeldung.tasksservice.adapters.repository.TaskRecord; +import com.baeldung.tasksservice.adapters.repository.TasksRepository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DeletedUserService { + @Autowired + private TasksRepository tasksRepository; + + @Transactional + public void handleDeletedUser(String user) { + var ownedByUser = tasksRepository.findByCreatedBy(user); + tasksRepository.deleteAll(ownedByUser); + + var assignedToUser = tasksRepository.findByAssignedTo(user); + for (TaskRecord record : assignedToUser) { + record.setAssignedTo(null); + record.setStatus("PENDING"); + } + } +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/TasksService.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/TasksService.java new file mode 100644 index 0000000000..e9ba1a9f70 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/TasksService.java @@ -0,0 +1,72 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.service; + +import javax.transaction.Transactional; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import com.baeldung.tasksservice.adapters.repository.TaskRecord; +import com.baeldung.tasksservice.adapters.repository.TasksRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TasksService { + @Autowired + private TasksRepository tasksRepository; + + public TaskRecord getTaskById(String id) { + return tasksRepository.findById(id).orElseThrow(() -> new UnknownTaskException(id)); + } + + @Transactional + public void deleteTaskById(String id) { + var task = tasksRepository.findById(id).orElseThrow(() -> new UnknownTaskException(id)); + tasksRepository.delete(task); + } + + public List search(Optional createdBy, Optional status) { + if (createdBy.isPresent() && status.isPresent()) { + return tasksRepository.findByStatusAndCreatedBy(status.get(), createdBy.get()); + } else if (createdBy.isPresent()) { + return tasksRepository.findByCreatedBy(createdBy.get()); + } else if (status.isPresent()) { + return tasksRepository.findByStatus(status.get()); + } else { + return tasksRepository.findAll(); + } + } + + @Transactional + public TaskRecord updateTask(String id, Optional newStatus, Optional newAssignedTo) { + var task = tasksRepository.findById(id).orElseThrow(() -> new UnknownTaskException(id)); + + newStatus.ifPresent(task::setStatus); + newAssignedTo.ifPresent(task::setAssignedTo); + + return task; + } + + public TaskRecord createTask(String title, String createdBy) { + var task = new TaskRecord(UUID.randomUUID().toString(), + title, + Instant.now(), + createdBy, + null, + "PENDING"); + tasksRepository.save(task); + return task; + } +} diff --git a/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/UnknownTaskException.java b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/UnknownTaskException.java new file mode 100644 index 0000000000..fd9fce4d16 --- /dev/null +++ b/lightrun/tasks-service/src/main/java/com/baeldung/tasksservice/service/UnknownTaskException.java @@ -0,0 +1,24 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.tasksservice.service; + +public class UnknownTaskException extends RuntimeException { + private final String id; + + public UnknownTaskException(final String id) { + this.id = id; + } + + public String getId() { + return id; + } +} diff --git a/lightrun/tasks-service/src/main/resources/application.properties b/lightrun/tasks-service/src/main/resources/application.properties new file mode 100644 index 0000000000..83bbf1a1b8 --- /dev/null +++ b/lightrun/tasks-service/src/main/resources/application.properties @@ -0,0 +1,13 @@ +server.port=8082 + +spring.artemis.mode=EMBEDDED +spring.artemis.host=localhost +spring.artemis.port=61616 + +spring.artemis.embedded.enabled=true + +spring.jms.template.default-destination=my-queue-1 + +logging.level.org.apache.activemq.audit.base=WARN +logging.level.org.apache.activemq.audit.message=WARN + diff --git a/lightrun/tasks-service/src/main/resources/db/migration/V1_0_0__create-tasks-table.sql b/lightrun/tasks-service/src/main/resources/db/migration/V1_0_0__create-tasks-table.sql new file mode 100644 index 0000000000..f2365c2687 --- /dev/null +++ b/lightrun/tasks-service/src/main/resources/db/migration/V1_0_0__create-tasks-table.sql @@ -0,0 +1,13 @@ +CREATE TABLE tasks ( + task_id VARCHAR(36) PRIMARY KEY, + title VARCHAR(100) NOT NULL, + created_at DATETIME NOT NULL, + created_by VARCHAR(36) NOT NULL, + assigned_to VARCHAR(36) NULL, + status VARCHAR(20) NOT NULL +); + +INSERT INTO tasks(task_id, title, created_at, created_by, assigned_to, status) VALUES + ('createdemoapplication1', 'Create demo applications - Tasks', '2022-05-05 12:34:56', 'baeldung', 'coxg', 'IN_PROGRESS'), + ('createdemoapplication2', 'Create demo applications - Users', '2022-05-05 12:34:56', 'baeldung', NULL, 'PENDING'), + ('createdemoapplication3', 'Create demo applications - API', '2022-05-05 12:34:56', 'baeldung', NULL, 'PENDING'); \ No newline at end of file diff --git a/lightrun/users-service/.gitignore b/lightrun/users-service/.gitignore new file mode 100644 index 0000000000..549e00a2a9 --- /dev/null +++ b/lightrun/users-service/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/lightrun/users-service/README.md b/lightrun/users-service/README.md new file mode 100644 index 0000000000..7c713e6638 --- /dev/null +++ b/lightrun/users-service/README.md @@ -0,0 +1,29 @@ +# Lightrun Example Application - Tasks Management + +This application exists as an example for the Lightrun series of articles. + +## Building +This application requires [Apache Maven](https://maven.apache.org/) and [Java 17+](https://www.oracle.com/java/technologies/downloads/). It does use the Maven Wrapper, so it can be built with only Java available on the path. + +As such, building the code is done by executing: +``` +$ ./mvnw install +``` +from the top level. + +## Running +The application consists of three services: +* Tasks +* Users +* API + +These are all Spring Boot applications. + +The Tasks and Users services exist as microservices for managing one facet of data. Each uses a database, and utilise a JMS queue between them as well. For convenience this infrastructure is all embedded in the applications. + +This does mean that the startup order is important. The JMS queue exists within the Tasks service and is connected to from the Users service. As such, the Tasks service must be started before the others. + +Each service can be started either by executing `mvn spring-boot:run` from within the appropriate directory. Alternatively, as Spring Boot applications, the build will produce an executable JAR file within the `target` directory that can be executed as, for example: +``` +$ java -jar ./target/tasks-service-0.0.1-SNAPSHOT.jar +``` diff --git a/lightrun/users-service/pom.xml b/lightrun/users-service/pom.xml new file mode 100644 index 0000000000..a961e4093b --- /dev/null +++ b/lightrun/users-service/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.7 + + + com.baeldung + users-service + 0.0.1-SNAPSHOT + users-service + Users Service for LightRun Article + + 17 + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-artemis + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.flywaydb + flyway-core + + + + com.h2database + h2 + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/JmsConfig.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/JmsConfig.java new file mode 100644 index 0000000000..c803c9af13 --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/JmsConfig.java @@ -0,0 +1,29 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.support.converter.MappingJackson2MessageConverter; +import org.springframework.jms.support.converter.MessageConverter; +import org.springframework.jms.support.converter.MessageType; + +@Configuration +public class JmsConfig { + @Bean + public MessageConverter jacksonJmsMessageConverter() { + MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); + converter.setTargetType(MessageType.TEXT); + converter.setTypeIdPropertyName("_type"); + return converter; + } +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/UsersServiceApplication.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/UsersServiceApplication.java new file mode 100644 index 0000000000..487e8de45b --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/UsersServiceApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.usersservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class UsersServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(UsersServiceApplication.class, args); + } + +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/CreateUserRequest.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/CreateUserRequest.java new file mode 100644 index 0000000000..c3dfc8d068 --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/CreateUserRequest.java @@ -0,0 +1,15 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.http; + +public record CreateUserRequest(String name) { +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/PatchUserRequest.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/PatchUserRequest.java new file mode 100644 index 0000000000..acaf7e635f --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/PatchUserRequest.java @@ -0,0 +1,17 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.http; + +import java.util.Optional; + +public record PatchUserRequest(Optional name) { +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UserResponse.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UserResponse.java new file mode 100644 index 0000000000..b9a20c415b --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UserResponse.java @@ -0,0 +1,16 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.http; + +public record UserResponse(String id, + String name) { +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UsersController.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UsersController.java new file mode 100644 index 0000000000..a5138e31d6 --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/UsersController.java @@ -0,0 +1,69 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.http; + +import com.baeldung.usersservice.adapters.repository.UserRecord; +import com.baeldung.usersservice.service.UsersService; +import com.baeldung.usersservice.service.UnknownUserException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/") +class UsersController { + @Autowired + private UsersService usersService; + + @GetMapping("/{id}") + public UserResponse getUser(@PathVariable("id") String id) { + var user = usersService.getUserById(id); + return buildResponse(user); + } + + @DeleteMapping("/{id}") + public void deleteUser(@PathVariable("id") String id) { + usersService.deleteUserById(id); + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public UserResponse createUser(@RequestBody CreateUserRequest body) { + var user = usersService.createUser(body.name()); + return buildResponse(user); + } + + @PatchMapping("/{id}") + public UserResponse patchUser(@PathVariable("id") String id, + @RequestBody PatchUserRequest body) { + var user = usersService.updateUser(id, body.name()); + + return buildResponse(user); + } + private UserResponse buildResponse(final UserRecord user) { + return new UserResponse(user.getId(), user.getName()); + } + + @ExceptionHandler(UnknownUserException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public void handleUnknownUser() { + } +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/http-client.env.json b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/http-client.env.json new file mode 100644 index 0000000000..3be2f710ff --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/http-client.env.json @@ -0,0 +1,5 @@ +{ + "local-users": { + "host": "localhost:8081" + } +} \ No newline at end of file diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/users.http b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/users.http new file mode 100644 index 0000000000..904c5f1cf1 --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/http/users.http @@ -0,0 +1,25 @@ +GET http://{{host}}/baeldung HTTP/1.1 + +### +GET http://{{host}}/unknown HTTP/1.1 + +### +DELETE http://{{host}}/baeldung HTTP/1.1 + +### +DELETE http://{{host}}/unknown HTTP/1.1 + +### +POST http://{{host}} HTTP/1.1 +Content-Type: application/json + +{ + "name": "Testing" +} +### +PATCH http://{{host}}/coxg HTTP/1.1 +Content-Type: application/json + +{ + "name": "Test Name" +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/jms/JmsSender.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/jms/JmsSender.java new file mode 100644 index 0000000000..f5d5d7900f --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/jms/JmsSender.java @@ -0,0 +1,26 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.jms; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.stereotype.Repository; + +@Repository +public class JmsSender { + @Autowired + private JmsTemplate jmsTemplate; + + public void sendDeleteUserMessage(String userId) { + jmsTemplate.convertAndSend("deleted_user", userId); + } +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UserRecord.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UserRecord.java new file mode 100644 index 0000000000..fe87ac3ffe --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UserRecord.java @@ -0,0 +1,47 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.repository; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "users") +public class UserRecord { + @Id + @Column(name = "user_id") + private String id; + private String name; + + public UserRecord(final String id, final String name) { + this.id = id; + this.name = name; + } + + private UserRecord() { + // Needed for JPA + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UsersRepository.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UsersRepository.java new file mode 100644 index 0000000000..ed193a4955 --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/adapters/repository/UsersRepository.java @@ -0,0 +1,19 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.adapters.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UsersRepository extends JpaRepository { +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UnknownUserException.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UnknownUserException.java new file mode 100644 index 0000000000..d0ca79850c --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UnknownUserException.java @@ -0,0 +1,24 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.service; + +public class UnknownUserException extends RuntimeException { + private final String id; + + public UnknownUserException(final String id) { + this.id = id; + } + + public String getId() { + return id; + } +} diff --git a/lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UsersService.java b/lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UsersService.java new file mode 100644 index 0000000000..46954b1ee0 --- /dev/null +++ b/lightrun/users-service/src/main/java/com/baeldung/usersservice/service/UsersService.java @@ -0,0 +1,61 @@ +/**************************************************************************************************************** + * + * Copyright (c) 2022 OCLC, Inc. All Rights Reserved. + * + * OCLC proprietary information: the enclosed materials contain + * proprietary information of OCLC, Inc. and shall not be disclosed in whole or in + * any part to any third party or used by any person for any purpose, without written + * consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice. + * + ******************************************************************************************************************/ + +package com.baeldung.usersservice.service; + +import javax.transaction.Transactional; + +import java.time.Instant; +import java.util.Optional; +import java.util.UUID; + +import com.baeldung.usersservice.adapters.jms.JmsSender; +import com.baeldung.usersservice.adapters.repository.UserRecord; +import com.baeldung.usersservice.adapters.repository.UsersRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.stereotype.Service; + +@Service +public class UsersService { + @Autowired + private UsersRepository usersRepository; + + @Autowired + private JmsSender jmsSender; + + public UserRecord getUserById(String id) { + return usersRepository.findById(id).orElseThrow(() -> new UnknownUserException(id)); + } + + @Transactional + public void deleteUserById(String id) { + var user = usersRepository.findById(id).orElseThrow(() -> new UnknownUserException(id)); + usersRepository.delete(user); + + jmsSender.sendDeleteUserMessage(id); + } + + @Transactional + public UserRecord updateUser(String id, Optional newName) { + var user = usersRepository.findById(id).orElseThrow(() -> new UnknownUserException(id)); + + newName.ifPresent(user::setName); + + return user; + } + + public UserRecord createUser(String name) { + var user = new UserRecord(UUID.randomUUID().toString(), name); + usersRepository.save(user); + return user; + } +} diff --git a/lightrun/users-service/src/main/resources/application.properties b/lightrun/users-service/src/main/resources/application.properties new file mode 100644 index 0000000000..8cc8f67d92 --- /dev/null +++ b/lightrun/users-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8081 + +spring.artemis.host=localhost +spring.artemis.port=61616 + +spring.jms.template.default-destination=my-queue-1 + +logging.level.org.apache.activemq.audit.base=WARN +logging.level.org.apache.activemq.audit.message=WARN + diff --git a/lightrun/users-service/src/main/resources/db/migration/V1_0_0__create-users-table.sql b/lightrun/users-service/src/main/resources/db/migration/V1_0_0__create-users-table.sql new file mode 100644 index 0000000000..d1ec9387e6 --- /dev/null +++ b/lightrun/users-service/src/main/resources/db/migration/V1_0_0__create-users-table.sql @@ -0,0 +1,8 @@ +CREATE TABLE users ( + user_id VARCHAR(36) PRIMARY KEY, + name VARCHAR(100) NOT NULL +); + +INSERT INTO users(user_id, name) VALUES + ('baeldung', 'Baeldung'), + ('coxg', 'Graham'); \ No newline at end of file diff --git a/pom.xml b/pom.xml index 106bb7516a..963267fee5 100644 --- a/pom.xml +++ b/pom.xml @@ -1329,6 +1329,7 @@ spring-boot-modules/spring-boot-camel testing-modules/testing-assertions persistence-modules/fauna + lightrun @@ -1396,6 +1397,7 @@ spring-boot-modules/spring-boot-camel testing-modules/testing-assertions persistence-modules/fauna + lightrun From f05171163b381e998fffed390cfb9f9cad78bf79 Mon Sep 17 00:00:00 2001 From: 515882294 <515882294@qq.com> Date: Wed, 18 May 2022 01:51:16 +0800 Subject: [PATCH 08/12] BAEL-4463: change method name --- .../java/com/baeldung/reflection/proxy/AdvancedOperation.java | 2 +- .../main/java/com/baeldung/reflection/proxy/BasicOperation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java index 3262b255f0..b3f0dc8ec0 100644 --- a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java +++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/AdvancedOperation.java @@ -1,7 +1,7 @@ package com.baeldung.reflection.proxy; public interface AdvancedOperation { - int multiple(int a, int b); + int multiply(int a, int b); int divide(int a, int b); } \ No newline at end of file diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java index b39eb0118e..168367b690 100644 --- a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java +++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/proxy/BasicOperation.java @@ -3,5 +3,5 @@ package com.baeldung.reflection.proxy; public interface BasicOperation { int add(int a, int b); - int sub(int a, int b); + int subtract(int a, int b); } \ No newline at end of file From f57604bef02552b57fc4ea0bf6ed6e7a1047b941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Aragon=C3=A9s=20L=C3=B3pez?= Date: Tue, 17 May 2022 21:02:03 +0200 Subject: [PATCH 09/12] Request Mapping value in properties file (#12226) * Exception Handler implemented for Spring Security Resource Server * Renamed test class name to solve PMD Failure * Code formatting * Using property parameter as Request Mapping value * Renamed test class name to solve PMD Failure --- .../WelcomeController.java | 15 +++++++++++ .../src/main/resources/application.properties | 1 + .../WelcomeControllerUnitTest.java | 25 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestmappingvalue/WelcomeController.java create mode 100644 spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/requestmappingvalue/WelcomeControllerUnitTest.java diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestmappingvalue/WelcomeController.java b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestmappingvalue/WelcomeController.java new file mode 100644 index 0000000000..bbc978ccd4 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/main/java/com/baeldung/requestmappingvalue/WelcomeController.java @@ -0,0 +1,15 @@ +package com.baeldung.requestmappingvalue; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/${request.value}") +public class WelcomeController { + + @GetMapping + public String getWelcomeMessage() { + return "Welcome to Baeldung!"; + } +} diff --git a/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties index 935f91554b..61a0755b93 100644 --- a/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties +++ b/spring-web-modules/spring-mvc-basics-5/src/main/resources/application.properties @@ -1 +1,2 @@ server.servlet.context-path=/spring-mvc-basics +request.value=welcome diff --git a/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/requestmappingvalue/WelcomeControllerUnitTest.java b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/requestmappingvalue/WelcomeControllerUnitTest.java new file mode 100644 index 0000000000..ac5140733b --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-5/src/test/java/com/baeldung/requestmappingvalue/WelcomeControllerUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.requestmappingvalue; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +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; + +@SpringBootTest +@AutoConfigureMockMvc +class WelcomeControllerUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenUserAccessToWelcome_thenReturnOK() throws Exception { + this.mockMvc.perform(get("/welcome")) + .andExpect(status().isOk()); + } + +} \ No newline at end of file From 7e3cddafaad586287c99f2f23426ddee554fc93d Mon Sep 17 00:00:00 2001 From: Ashley Frieze Date: Wed, 18 May 2022 08:54:10 +0100 Subject: [PATCH 10/12] BAEL-5562 Check if character is vowel (#12221) --- .../core-java-string-operations-4/pom.xml | 6 +++ .../com/baeldung/checkvowels/CheckVowels.java | 38 ++++++++++++++ .../checkvowels/CheckVowelsUnitTest.java | 51 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/checkvowels/CheckVowels.java create mode 100644 core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/checkvowels/CheckVowelsUnitTest.java diff --git a/core-java-modules/core-java-string-operations-4/pom.xml b/core-java-modules/core-java-string-operations-4/pom.xml index 7f71ea8da5..0f1e377d18 100644 --- a/core-java-modules/core-java-string-operations-4/pom.xml +++ b/core-java-modules/core-java-string-operations-4/pom.xml @@ -30,6 +30,12 @@ commons-lang3 ${apache-commons-lang3.version} + + org.assertj + assertj-core + ${assertj.version} + test + diff --git a/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/checkvowels/CheckVowels.java b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/checkvowels/CheckVowels.java new file mode 100644 index 0000000000..fd60427a4e --- /dev/null +++ b/core-java-modules/core-java-string-operations-4/src/main/java/com/baeldung/checkvowels/CheckVowels.java @@ -0,0 +1,38 @@ +package com.baeldung.checkvowels; + +import java.util.regex.Pattern; + +public class CheckVowels { + private static final String VOWELS = "aeiouAEIOU"; + private static final Pattern VOWELS_PATTERN = Pattern.compile("[aeiou]", Pattern.CASE_INSENSITIVE); + + public static boolean isInVowelsString(char c) { + return VOWELS.indexOf(c) != -1; + } + + public static boolean isInVowelsString(String c) { + return VOWELS.contains(c); + } + + public static boolean isVowelBySwitch(char c) { + switch (c) { + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': + case 'A': + case 'E': + case 'I': + case 'O': + case 'U': + return true; + default: + return false; + } + } + + public static boolean isVowelByRegex(String c) { + return VOWELS_PATTERN.matcher(c).matches(); + } +} diff --git a/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/checkvowels/CheckVowelsUnitTest.java b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/checkvowels/CheckVowelsUnitTest.java new file mode 100644 index 0000000000..52b0e55692 --- /dev/null +++ b/core-java-modules/core-java-string-operations-4/src/test/java/com/baeldung/checkvowels/CheckVowelsUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.checkvowels; + +import org.junit.jupiter.api.Test; + +import static com.baeldung.checkvowels.CheckVowels.*; +import static org.assertj.core.api.Assertions.*; + +class CheckVowelsUnitTest { + + @Test + void givenAVowelCharacter_thenInVowelString() { + assertThat(isInVowelsString('e')).isTrue(); + } + + @Test + void givenAConsonantCharacter_thenNotInVowelString() { + assertThat(isInVowelsString('z')).isFalse(); + } + + @Test + void givenAVowelString_thenInVowelString() { + assertThat(isInVowelsString("e")).isTrue(); + } + + @Test + void givenAConsonantString_thenNotInVowelString() { + assertThat(isInVowelsString("z")).isFalse(); + } + + @Test + void givenAVowelCharacter_thenInVowelSwitch() { + assertThat(isVowelBySwitch('e')).isTrue(); + } + + @Test + void givenAConsonantCharacter_thenNotInVowelSwitch() { + assertThat(isVowelBySwitch('z')).isFalse(); + } + + @Test + void givenAVowelString_thenInVowelPattern() { + assertThat(isVowelByRegex("e")).isTrue(); + assertThat(isVowelByRegex("E")).isTrue(); + } + + @Test + void givenAVowelCharacter_thenInVowelPattern() { + assertThat(isVowelByRegex(Character.toString('e'))).isTrue(); + assertThat(isVowelByRegex("E")).isTrue(); + } +} From 75a751df3a5695b605472ff86a56b84861c11d4c Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Thu, 19 May 2022 01:34:23 +0200 Subject: [PATCH 11/12] JAVA-5484: New Java Http Client Timeout (#12223) Co-authored-by: Harpal Singh --- .../baeldung/http/JavaHttpClientTimeout.java | 12 +++++ .../JavaHttpClientTimeoutIntegrationTest.java | 54 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 core-java-modules/core-java-networking-3/src/main/java/com/baeldung/http/JavaHttpClientTimeout.java create mode 100644 core-java-modules/core-java-networking-3/src/test/java/com/baeldung/http/JavaHttpClientTimeoutIntegrationTest.java diff --git a/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/http/JavaHttpClientTimeout.java b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/http/JavaHttpClientTimeout.java new file mode 100644 index 0000000000..d7ab002e77 --- /dev/null +++ b/core-java-modules/core-java-networking-3/src/main/java/com/baeldung/http/JavaHttpClientTimeout.java @@ -0,0 +1,12 @@ +package com.baeldung.http; + +import java.net.http.HttpClient; +import java.time.Duration; + +public class JavaHttpClientTimeout { + static HttpClient getHttpClientWithTimeout(int seconds) { + return HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(seconds)) + .build(); + } +} diff --git a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/http/JavaHttpClientTimeoutIntegrationTest.java b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/http/JavaHttpClientTimeoutIntegrationTest.java new file mode 100644 index 0000000000..df635621ad --- /dev/null +++ b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/http/JavaHttpClientTimeoutIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.http; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpConnectTimeoutException; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static com.baeldung.http.JavaHttpClientTimeout.getHttpClientWithTimeout; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class JavaHttpClientTimeoutIntegrationTest { + + private HttpClient httpClient; + private HttpRequest httpRequest; + + @BeforeEach + public void setUp() { + httpClient = getHttpClientWithTimeout(3); + httpClient.connectTimeout().map(Duration::toSeconds) + .ifPresent(sec -> System.out.println("Timeout in seconds: " + sec)); + + httpRequest = HttpRequest.newBuilder().uri(URI.create("http://10.255.255.1")).GET().build(); + } + + @Test + void shouldThrowExceptionWhenMakingSyncCall() { + HttpConnectTimeoutException thrown = assertThrows( + HttpConnectTimeoutException.class, + () -> httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()), + "Expected doThing() to throw, but it didn't" + ); + assertTrue(thrown.getMessage().contains("timed out")); + } + + @Test + void shouldThrowExceptionWhenMakingASyncCall() throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture completableFuture = + httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString()) + .thenApply(HttpResponse::body) + .exceptionally(Throwable::getMessage); + String response = completableFuture.get(5, TimeUnit.SECONDS); + assertTrue(response.contains("timed out")); + } +} \ No newline at end of file From f8ce24823675e0e32b3e965755812b27b3cfce2b Mon Sep 17 00:00:00 2001 From: opokharel <66694687+opokharel@users.noreply.github.com> Date: Wed, 18 May 2022 18:36:27 -0600 Subject: [PATCH 12/12] [BAEL-5554] Find files that match a wildcard string in Java by @opokharel (#12190) * BAEL-5554 by @opokharel * deletedToMoveToSrcFolder * movedToSrcFolder * redoingForJenkins * newPR for [BAEL-5554] Find files that match a wildcard string in Java by @opokharel * @opokharel * [BAEL-5554] @opokharel * [BAEL-5554] Find files that match a wildcard string in Java by @opokharel * Update SearchFileByWildcardTest.java * Update SearchFileByWildcard.java * Update SearchFileByWildcard.java * Create SearchFileByWildcardUnitTest.java * Delete SearchFileByWildcardTest.java * [BAEL-5554] Find files that match a wildcard string in Java by @opokharel * Update SearchFileByWildcardUnitTest.java * Update SearchFileByWildcardUnitTest.java * [BAEL-5554] UnitTestFiles by @opokharel * Update core-java-modules/core-java-nio-2/src/test/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcardUnitTest.java Co-authored-by: KevinGilmore * updated curly braces and assertions Co-authored-by: KevinGilmore --- .../SearchFileByWildcard.java | 37 ++++++++++++++++++ .../SearchFileByWildcardUnitTest.java | 30 ++++++++++++++ .../src/test/resources/sfbw/test/five.csv | 0 .../src/test/resources/sfbw/test/four.xlsx | Bin 0 -> 6169 bytes .../src/test/resources/sfbw/test/one.txt | 0 .../test/resources/sfbw/test/test2/six.txt | 0 .../src/test/resources/sfbw/test/three.txt | 0 .../src/test/resources/sfbw/test/two.docx | 0 8 files changed, 67 insertions(+) create mode 100644 core-java-modules/core-java-nio-2/src/main/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcard.java create mode 100644 core-java-modules/core-java-nio-2/src/test/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcardUnitTest.java create mode 100644 core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/five.csv create mode 100644 core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/four.xlsx create mode 100644 core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/one.txt create mode 100644 core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/test2/six.txt create mode 100644 core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/three.txt create mode 100644 core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/two.docx diff --git a/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcard.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcard.java new file mode 100644 index 0000000000..2deaa60ec6 --- /dev/null +++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcard.java @@ -0,0 +1,37 @@ +package com.baeldung.searchfilesbywildcards; + +import java.io.IOException; + +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +import java.util.ArrayList; +import java.util.List; + +public class SearchFileByWildcard { + public static List matchesList = new ArrayList(); + public List searchWithWc(Path rootDir, String pattern) throws IOException { + matchesList.clear(); + FileVisitor matcherVisitor = new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attribs) throws IOException { + FileSystem fs = FileSystems.getDefault(); + PathMatcher matcher = fs.getPathMatcher(pattern); + Path name = file.getFileName(); + if (matcher.matches(name)) { + matchesList.add(name.toString()); + } + return FileVisitResult.CONTINUE; + } + }; + Files.walkFileTree(rootDir, matcherVisitor); + return matchesList; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcardUnitTest.java b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcardUnitTest.java new file mode 100644 index 0000000000..71cee036ec --- /dev/null +++ b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/searchfilesbywildcards/SearchFileByWildcardUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.searchfilesbywildcards; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import java.nio.file.Paths; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class SearchFileByWildcardUnitTest { + @Test + public void whenFourFilenameMatch_thenListOfFour() throws IOException { + SearchFileByWildcard sfbw = new SearchFileByWildcard(); + List actual = sfbw.searchWithWc(Paths.get("src/test/resources/sfbw"), "glob:*.{txt,docx}"); + + assertEquals(new HashSet<>(Arrays.asList("six.txt", "three.txt", "two.docx", "one.txt")), new HashSet<>(actual)); + } + @Test + public void whenOneFilenameMatch_thenListOfOne() throws IOException { + SearchFileByWildcard sfbw = new SearchFileByWildcard(); + List actual = sfbw.searchWithWc(Paths.get("src/test/resources/sfbw"), "glob:????.{csv}"); + + assertEquals(new HashSet<>(Arrays.asList("five.csv")), new HashSet<>(actual)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/five.csv b/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/five.csv new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/four.xlsx b/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/four.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1091dafe75e41a1e45f2c0b8df3dfe6d7f6f9af6 GIT binary patch literal 6169 zcmeHLcQoAFw;yfv5H(5&Awh^Xdan_^_Yxx_7}0yp=!{_W1R+X@8odn?o#-_f1c``V zM+tf3=H2UFzx&==@BepZ%{epYeD|JNpWV*>XsTdgQviSfJOBW|1jyCt7*xjq0PwH@ z0CMz>iJapzH|u9^7P{U})~;svy&NFL34Q8qJfsRJrJr)kTv5mhX*_`qXct)n8{?zJ zhv0E;@7a-a33AkX>1;|nq4(gySyu`E%uj+76!sAXh@z>~SVN4`L*>RA@ayQ>-FV8> zT%8dwT*?{DiqHFpPb#K>tsGQ;8 z0))zfcA5{dU`CVlZG$_MWpvYXB9V{cCUD{x*2Z4xypS?3k@t7aoOoxl0;%G7ovD-DCC1EKi&hEGzcU+Pcor}M; zU-uY47(YyVpzO`&fr#ZOsw>D=>6yQ+IJzVMo^Hk$@#0qQV}Am>mzBD-L7Dp&!v9d5T=7;T0NboBDUq=OczmR zZ;Qu});;-GE#zl@TqVDY;Xf$KN9NGi_ z6CBHj_@t5Olj~Rj04W-r$BtH-E{;yF+?GyG7mk?@mvNloAqw5XI$fpetkoMgH2~o zeVF7mg)|GG#DU{i@9;{qz6e@WwD8k@MNj_NB?#vMcCoxlqQ3SUhiv}3M>uE3&m*m_$+IIF-B`O}TO>C+RJ4!xz zTPXsD6dVPVFC?W$N3GU8vZ%<(xu29?YiA!5E`Yn%>4nWY5B$OKsk|!2nWp-O?Raor zDxq7TmxIBZBL`Aoy7K-VG4hD_z?m^vwT6mIsOx}`d78$_UEiCHk3YtT>KwF%+W09o zdfDTdPkKx0&P+TmIL1+5lO!IKaO68>dW?Ko9)2>u*TN%yzO>(VuB={Mx6o_Or=C^f9?NOo%!e zR8{JF_NZaM#InTKbWe@tW+w-;-m$anZakX@A@V#OV{ePp2T3Q}Dp6}DMRG-kwWPB? zXze@dm)L=4hU%ZtJDW$_U+a*#+3YXw^nj(PtD-|#gNjD{ba|Kh()}(g+Utllhh#J+ z*gyb)_%|-DZr%`U*9$yybxrJNcqjrG*QM|fjTJ~?73f9Mc;97 zRDo$E`J&5qQCr$;FQCXR8dtnqiT&Gi^-mNcxKOIvzS(s73mPRcxz}_nZ`bg`^d~If z&~{7VyKt9K-;gBEU%2wxdtOhW+I?Z7&0nF7R^g%XoCdXGdBjM9tZ7Al<2QmYUwOfX z(#)~rn?Tb)rp*9s!|wemhwwExCqCDp65v!cmyOAC_HO3eYW;yX+Kh?8yI2i(5k9&n zjT}F@9oG@NW9QNux{B?SgE__=zZlTUw_bW zDM%I~8?+MUG+mTUH|)p++}Ncc*i6;JVS5_K_<}gZfQL>(bp=JTm66@WrhbQ7iJC{F zc3PJwdc_BpFHTwPAw9N@oO`VB%+W7EUu~b*(Hi%A!@7y719KqSs$FiWhP5RRp~Jzi3RmlhR1` zc{b||&vrd3X{_WicX|{2h34G5^1OU@mcqFlZ!-FkM-Ti_TCtD}U!%FBU=}B>GeBI zYq`tLkl2!*7a&FcxfuNCaPfmYO(hiz0{=BRc4E-bP|A5~Xo%q1bqRiWN!o$%tG@gy zR(r$TVb1|S*MVUnYO^Lc?)-u4>LQj8XG+Wq>aMAGLS*4aGYA3t#FwRQILdb-DzIyj ztlu{Ckg-w?5gzg(R_j6jA3Zf^VnR~468rp!`XekJxu&;Pva49JEC^;K-DMXAw(xRI zawKKZ--g$zL%~kI{-Uf_>qL1fo}OQuG`NJ(S<`IC5r5i9d9ae~$(=l`{!G4u%B25U*11dL>?0RL9sm5w;Rc<-Jw#UJ zVHrRdvUm~`FhnwOP63GN;u(QOZ;o!&G)PEw*=4PdEH+MlA1?x$?^(<*%I=GkYeaQsaEhP^Npma+C%JRZ+V22_mJ4#NzhmCcBAx%Nk%Qcbb zT7QzUwPs;k;PKvAQWW0w2c^p7rXc+Jr*J=dN%bDnDx}7Tq9U10DPND>?bV((3k?Pd zQST$yxmp+NDKnWK)mq=DM!no=ncpMgy|tSs9`9m5$n?a1| zHpO5``a`nSDUBnhL^hXaJeI**{CmXls5sn2h#JZP8sqkw3%gd@)LmKOdH3DuF?e5J zYTDKkT>ZK}2iCNsl8-8!|KKdK;`A4+Vn*PE9)#RHG8=13AX^i2|C$))*mj1S)EG|H zLrlco_wCbxOq~>7?P&}3ro-0mai4qk(5<-+W3!Ukr4m9Ed-lFGC;Qxz-Nt~W`AecK zEeDRV0T)F4s|QYLj^sqMoC>|257Uld5#Mjgx*9GRj0?JTx=!+MexeC?Z?V&-1N-&X zPD^ku`V00P7LC7~ef4DVLpP%XNFFh0I0<@ZzkIffGvZt7xNo$R3PQ3UoE_)1n6YUK&U~b6I*__}V+T7)plNOQ_e%XV6 zm|=sgd}~J|q6Uf<8P%i|v7hePKU3SKEdrAX7+Q~%)DSlfHB2b4WoedFw$oH@+N#&varlJr~pYsz{@Kib02(cZTS z_1a&c@RGqXC=B5yVTUSMc)UpO0X8wCk?%Bk{YkXT4J)6qEh36@cZlyFe7_bYR zsUyaA&U~u34DKPGZD6Q!GDj5!91dFpaJAgh0)4bL=w4eajvLK{@<#Wm`kS-gTl}%7 zQeAVl7cD34wuxIUQ#AJjn5U26XY)ops~jT;epW~w5;K=YebPU%@O+J)y?nAT+Em$3Erlbc`A z)hz=orW8k&zuJ@AG;hm>j0tQIB_FZ1Af(5=j%1ZAG@NAyNxIv@rea^z_LA00qu$6n zGkW9^X;Oi@@(`_37?Xmp^f^A=F-q=CEcsQn_~Cjx(1}D{($%?*D=|@XM?Vy+#+ox? zM?5+qS8S$wTkB)TuMRgA7k_wuRSI-5xDJtOak8DjDQ7kWQgi)8@_z7^hP$-KOPk7T z{pRJTrB*QkEcu?N2w(hy^4JYAxx~7>_Q;tOgs>n3xhcNeB=K3NxEaf6DbTcyn(-vQ zN}X!o2HwHAxu`(Z(YVUl`z;#u(qKo?#R8Pz}dAmR9IY3h}+dc zBQ-2kAUJE~h$~k>&HY5Tzf)&z{vY0ejV76JwZADUI$;p{p}ip!eJ#In=?$(=t*zZ$ zx&K)HxYoc%`k$d2dccD3YuO=0@@UB#Z96^?`-2Y~4`gk#N_9q-WjHQ1-@E4Kp^|Ut zum?HO_dFq;e97$xfq}n_9L%8xgQ*ochN}u%cA>-COJIZ5x33%5292%5rh?u^BuQFM zygC^Fp=A5oS6&~p-E=k6+mJTFAr`|$221gHRGXlcEPr5`i3v2Cx6rR<6u^gJI#yY( zy2V@IkkP^QS+2F4A3lVoa$N5zCu#qoIh-)=F#OB3_KlE&3{St8L;QOcM|h5T3y?Re zT+}Y3p9ByNTXVB?<;FOTe&3l{3lKz3WCth8g?dZ5k3X40|_} z7r#pLj!6yWSVJD07{}NbL>^il2Gb{%h18p-!HlNV`i_!ygSqI%1K%zgxS0*gB9*(W z%KE-lbwI4^pp-(jzf!7j!sZbQar2AasMrThv{JCGH8pLqAhkEZLz>x&y`BE0{irwrK& zZ4MqrCMU&#@MfOZERPLI>lpixk96|B4~QER^*-(OSQL#@iJeY6^YGBB5$_c}!C2!c zagm2pC}h=9C2_d!H=A`3Qiu#DKC0G_%OMx8;@sTgd&V|NC8$qV-i%3&19wS$MZbX% zqOj^h-AYq|%HcS_EqN>{?hr}5gsYF4nY&7_vaQN9=tKzXmzKB5UBDXgn`ywpdyx&q z?-f%egZ^q_D0UN~6SZDWOp;0~9~Ie5F9HSVvkEE^1m8>J5{xz(@|Dl>d%IkS6Ueo*`Q1S(E)PVFqoY!2|>T>GW@6OHKae2Ia{ z1-Q(ZSBY3O=zkmkLd$BZ{8PbID)CY}5N*i65sOy^uhMLng6Zi0`j_SZn{@jv{Xerk zm(n_DO8F}HbM?2ck{FlL4LJWBrEyiy)u#Va&j`AcLRX(l3gD{f)pqMrGy(r#o3E=1 zuGYFs1qNvP>q_POQ}`k^UXW#1Q{$zuHQ8Un|B)#F)bb~be>Ge$wNO+1&4hmjucitP T8WjM50R8eq+c=!^;@f`#F)1b5 literal 0 HcmV?d00001 diff --git a/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/one.txt b/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/one.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/test2/six.txt b/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/test2/six.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/three.txt b/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/three.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/two.docx b/core-java-modules/core-java-nio-2/src/test/resources/sfbw/test/two.docx new file mode 100644 index 0000000000..e69de29bb2