From b2e89f35748f30ab67abf11dc8d9cb15ca25d3f8 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Mon, 29 Jan 2024 14:46:50 +0100 Subject: [PATCH 01/88] BAEL-7131 version 1 - POST REPO re-writing the commit history issue. --- .../baeldung/inputstream/InputStreamTest.java | 58 +++++++++++++++++++ .../InputStreamReaderTest.java | 40 +++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java create mode 100644 core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java new file mode 100644 index 0000000000..7aca698446 --- /dev/null +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java @@ -0,0 +1,58 @@ +package com.baeldung.inputstream; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class InputStreamTest { + + @Test + public void givenAString_whenWrittenToFileInputStream_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + + Path sampleOut = tempDir.resolve("sample-out.txt"); + List lines = Arrays.asList("Hello. This is just a test. Good bye."); + Files.write(sampleOut, lines); + File sampleOutFile = sampleOut.toFile(); + try(InputStream inputStream = new FileInputStream(sampleOutFile)){ + Assert.assertTrue(readString(inputStream).contains(lines.get(0))); + } + } + + @Test + public void givenAString_whenWrittenToByteArrayInputStream_thenShouldMatchWhenRead() throws IOException { + byte[] byteArray = {104, 101, 108, 108,111}; + try(ByteArrayInputStream bais = new ByteArrayInputStream(byteArray)){ + int content; + StringBuilder actualReadText = new StringBuilder(); + while ((content = bais.read()) != -1) { + actualReadText.append((char) content); + } + Assert.assertEquals( "hello",actualReadText.toString()); + } + + } + + private static String readString(InputStream inputStream) throws IOException { + String strRet = ""; + int c; + StringBuilder sb = new StringBuilder(); + while(!((c = inputStream.read()) != -1)) { + sb.append((char) c); + } + strRet = sb.toString(); + + return strRet; + } + + +} diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java new file mode 100644 index 0000000000..7009297c86 --- /dev/null +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java @@ -0,0 +1,40 @@ +package com.baeldung.inputstreamreader; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class InputStreamReaderTest { + + @Test + public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + boolean isMatched = false; + String sampleTxt = "Good day. This is just a test. Good bye."; + Path sampleOut = tempDir.resolve("sample-out.txt"); + List lines = Arrays.asList(sampleTxt); + //create and write file + Files.write(sampleOut, lines); + try(FileInputStream fis = new FileInputStream(String.valueOf(sampleOut.toAbsolutePath())); + BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8));){ + String ln; + while((ln = br.readLine())!= null){ + if(ln.contains(sampleTxt)){ + isMatched = true; + break; + } + } + Assert.assertTrue(isMatched); + } + } + +} From 8aea75fd05c3db2de07e8afacdc5e4d10d3e6913 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Sat, 10 Feb 2024 23:44:42 +0100 Subject: [PATCH 02/88] BAEL-7131 version 2 - code review comments. --- .../baeldung/inputstream/InputStreamTest.java | 29 +++++-------------- .../InputStreamReaderTest.java | 10 ++----- 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java index 7aca698446..b238067654 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java @@ -13,46 +13,31 @@ import java.util.List; import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; - public class InputStreamTest { - @Test public void givenAString_whenWrittenToFileInputStream_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { - Path sampleOut = tempDir.resolve("sample-out.txt"); List lines = Arrays.asList("Hello. This is just a test. Good bye."); Files.write(sampleOut, lines); File sampleOutFile = sampleOut.toFile(); - try(InputStream inputStream = new FileInputStream(sampleOutFile)){ + try (InputStream inputStream = new FileInputStream(sampleOutFile)) { Assert.assertTrue(readString(inputStream).contains(lines.get(0))); } } - @Test public void givenAString_whenWrittenToByteArrayInputStream_thenShouldMatchWhenRead() throws IOException { - byte[] byteArray = {104, 101, 108, 108,111}; - try(ByteArrayInputStream bais = new ByteArrayInputStream(byteArray)){ - int content; - StringBuilder actualReadText = new StringBuilder(); - while ((content = bais.read()) != -1) { - actualReadText.append((char) content); - } - Assert.assertEquals( "hello",actualReadText.toString()); + byte[] byteArray = { 104, 101, 108, 108, 111 }; + try (ByteArrayInputStream bais = new ByteArrayInputStream(byteArray)) { + String expected = readString(bais); + Assert.assertEquals("hello", expected); } - } - private static String readString(InputStream inputStream) throws IOException { - String strRet = ""; int c; StringBuilder sb = new StringBuilder(); - while(!((c = inputStream.read()) != -1)) { + while ((c = inputStream.read()) != -1) { sb.append((char) c); } - strRet = sb.toString(); - - return strRet; + return sb.toString(); } - - } diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java index 7009297c86..d14a96c9a0 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java @@ -13,9 +13,7 @@ import java.util.List; import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; - public class InputStreamReaderTest { - @Test public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { boolean isMatched = false; @@ -24,11 +22,10 @@ public class InputStreamReaderTest { List lines = Arrays.asList(sampleTxt); //create and write file Files.write(sampleOut, lines); - try(FileInputStream fis = new FileInputStream(String.valueOf(sampleOut.toAbsolutePath())); - BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8));){ + try (FileInputStream fis = new FileInputStream(String.valueOf(sampleOut.toAbsolutePath())); BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8))) { String ln; - while((ln = br.readLine())!= null){ - if(ln.contains(sampleTxt)){ + while ((ln = br.readLine()) != null) { + if (ln.contains(sampleTxt)) { isMatched = true; break; } @@ -36,5 +33,4 @@ public class InputStreamReaderTest { Assert.assertTrue(isMatched); } } - } From 94fceedf7c2de5963add1f23f6ed6bcc38baf418 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Sun, 11 Feb 2024 19:11:39 +0100 Subject: [PATCH 03/88] BAEL-7131 version 3 - code review comments. --- .../baeldung/inputstream/InputStreamTest.java | 24 +++++++++++++++++++ .../InputStreamReaderTest.java | 1 + 2 files changed, 25 insertions(+) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java index b238067654..553085d2fe 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java @@ -13,6 +13,7 @@ import java.util.List; import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; + public class InputStreamTest { @Test public void givenAString_whenWrittenToFileInputStream_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { @@ -24,6 +25,28 @@ public class InputStreamTest { Assert.assertTrue(readString(inputStream).contains(lines.get(0))); } } + + @Test + public void givenAString_whenWrittenToFileInputStreamWithStringConstructor_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + Path sampleOut = tempDir.resolve("sample-out.txt"); + String expectedText = "Hello. Hi."; + List lines = Arrays.asList(expectedText); + Files.write(sampleOut, lines); + String fileAbsolutePath = sampleOut.toFile() + .getAbsolutePath(); + try (FileInputStream fis = new FileInputStream(fileAbsolutePath)) { + int content; + int availabeBytes = fis.available(); + Assert.assertTrue(availabeBytes > 0); + StringBuilder actualReadText = new StringBuilder(); + while ((content = fis.read()) != -1) { + actualReadText.append((char) content); + } + Assert.assertTrue(actualReadText.toString() + .contains(expectedText)); + } + } + @Test public void givenAString_whenWrittenToByteArrayInputStream_thenShouldMatchWhenRead() throws IOException { byte[] byteArray = { 104, 101, 108, 108, 111 }; @@ -32,6 +55,7 @@ public class InputStreamTest { Assert.assertEquals("hello", expected); } } + private static String readString(InputStream inputStream) throws IOException { int c; StringBuilder sb = new StringBuilder(); diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java index d14a96c9a0..e52bb99363 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java @@ -13,6 +13,7 @@ import java.util.List; import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; + public class InputStreamReaderTest { @Test public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { From 17172ba21ae8b2bda3f1cf2cb0ca9cff3c0029d9 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Sun, 11 Feb 2024 19:48:18 +0100 Subject: [PATCH 04/88] BAEL-7131 version 4 - code review comments. --- .../baeldung/inputstream/InputStreamTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java index 553085d2fe..0a00affbd8 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java @@ -1,14 +1,21 @@ package com.baeldung.inputstream; +import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.Assert; import org.junit.jupiter.api.Test; @@ -64,4 +71,28 @@ public class InputStreamTest { } return sb.toString(); } + + @Test + public void givenKeyValuePairs_whenWrittenInATextFile_thenSuccessWhenParsedWithObjectInputStream( + @TempDir(cleanup = ALWAYS) Path tempDir) throws IOException, ClassNotFoundException { + Path sampleOut = tempDir.resolve("sample-out.txt"); + File fileText = sampleOut.toFile(); + //Serialize a Hashmap then write it into a file. + Map kv = new HashMap<>(); + try (FileOutputStream fileOutStream = new FileOutputStream(fileText)) { + try (ObjectOutputStream objectOutStream = new ObjectOutputStream(fileOutStream)) { + kv.put("baseURL", "baeldung.com"); + kv.put("apiKey", "this_is_a_test_key"); + objectOutStream.writeObject(kv); + } + } + //Deserialize the contents of a file then transform it back into a Hashmap + try (FileInputStream fileStream = new FileInputStream(fileText)) { + try (ObjectInputStream input = new ObjectInputStream(fileStream)) { + HashMap inputKv = (HashMap) input.readObject(); + Assert.assertEquals(kv.get("baseURL"), inputKv.get("baseURL")); + Assert.assertEquals(kv.get("apiKey"), inputKv.get("apiKey")); + } + } + } } From 8a0d5939f11ddab1fe39057dd27820bcd3d1707d Mon Sep 17 00:00:00 2001 From: adalagandev Date: Mon, 12 Feb 2024 10:12:12 +0100 Subject: [PATCH 05/88] BAEL-7131 version 5 - renamed class name to end with UnitTest --- .../{InputStreamTest.java => InputStreamUnitTest.java} | 2 +- ...nputStreamReaderTest.java => InputStreamReaderUnitTest.java} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/{InputStreamTest.java => InputStreamUnitTest.java} (99%) rename core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/{InputStreamReaderTest.java => InputStreamReaderUnitTest.java} (97%) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java similarity index 99% rename from core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java rename to core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java index 0a00affbd8..a1b0ef251c 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java @@ -21,7 +21,7 @@ import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -public class InputStreamTest { +public class InputStreamUnitTest { @Test public void givenAString_whenWrittenToFileInputStream_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { Path sampleOut = tempDir.resolve("sample-out.txt"); diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java similarity index 97% rename from core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java rename to core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java index e52bb99363..ea4572fa5f 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java @@ -14,7 +14,7 @@ import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -public class InputStreamReaderTest { +public class InputStreamReaderUnitTest { @Test public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { boolean isMatched = false; From e6d37b867c74d037a685735993f955571a6883ac Mon Sep 17 00:00:00 2001 From: adalagandev Date: Tue, 20 Feb 2024 00:11:06 +0100 Subject: [PATCH 06/88] BAEL-7131 version 6 - updated for PR comments, renamed unit test method, added assertJ dependency and used that in unit tests instead. --- core-java-modules/core-java-io-apis-2/pom.xml | 9 ++- .../inputstream/InputStreamUnitTest.java | 65 +++++++++---------- .../InputStreamReaderUnitTest.java | 10 +-- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/pom.xml b/core-java-modules/core-java-io-apis-2/pom.xml index 579fa4a589..976cbd62e4 100644 --- a/core-java-modules/core-java-io-apis-2/pom.xml +++ b/core-java-modules/core-java-io-apis-2/pom.xml @@ -81,6 +81,12 @@ 7.1.0 test + + org.assertj + assertj-core + 3.4.1 + test + core-java-io-apis-2 @@ -94,4 +100,5 @@ 5.9.3 - \ No newline at end of file + + diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java index a1b0ef251c..e253690762 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java @@ -1,6 +1,6 @@ package com.baeldung.inputstream; -import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; +import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayInputStream; import java.io.File; @@ -20,21 +20,20 @@ import java.util.Map; import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; - public class InputStreamUnitTest { - @Test - public void givenAString_whenWrittenToFileInputStream_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + @Test //givenAStringWrittenToAFile_whenReadByX_thenY + public void givenAStringWrittenToFile_whenReadWithFileInputStream_thenItShouldExitsInTheInputStream(@TempDir Path tempDir) throws IOException { Path sampleOut = tempDir.resolve("sample-out.txt"); List lines = Arrays.asList("Hello. This is just a test. Good bye."); Files.write(sampleOut, lines); File sampleOutFile = sampleOut.toFile(); try (InputStream inputStream = new FileInputStream(sampleOutFile)) { - Assert.assertTrue(readString(inputStream).contains(lines.get(0))); + assertThat(readString(inputStream)).contains(lines.get(0)); } } @Test - public void givenAString_whenWrittenToFileInputStreamWithStringConstructor_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + public void givenAStringWrittenToFile_whenReadWithFileInputStreamWithStringConstructor_thenItShouldExitsInTheInputStream(@TempDir Path tempDir) throws IOException { Path sampleOut = tempDir.resolve("sample-out.txt"); String expectedText = "Hello. Hi."; List lines = Arrays.asList(expectedText); @@ -43,23 +42,40 @@ public class InputStreamUnitTest { .getAbsolutePath(); try (FileInputStream fis = new FileInputStream(fileAbsolutePath)) { int content; - int availabeBytes = fis.available(); - Assert.assertTrue(availabeBytes > 0); + int availableBytes = fis.available(); + Assert.assertTrue(availableBytes > 0); StringBuilder actualReadText = new StringBuilder(); while ((content = fis.read()) != -1) { actualReadText.append((char) content); } - Assert.assertTrue(actualReadText.toString() - .contains(expectedText)); + assertThat(actualReadText.toString()).contains(expectedText); } } @Test - public void givenAString_whenWrittenToByteArrayInputStream_thenShouldMatchWhenRead() throws IOException { + public void givenAByteArray_whenReadWithByteArrayInputStream_thenTheStringValueOfTheByteArrayShouldMatchTheExpectedString() throws IOException { byte[] byteArray = { 104, 101, 108, 108, 111 }; try (ByteArrayInputStream bais = new ByteArrayInputStream(byteArray)) { - String expected = readString(bais); - Assert.assertEquals("hello", expected); + assertThat(readString(bais)).isEqualTo("hello"); + } + } + @Test + public void givenKeyValuePairsWrittenInAFile_whenPassedInOutputStreams_thenThePairsShouldExistsInObjectInputStreams( + @TempDir Path tempDir) throws IOException, ClassNotFoundException { + Path sampleOut = tempDir.resolve("sample-out.txt"); + File fileText = sampleOut.toFile(); + //Serialize a Hashmap then write it into a file. + Map kv = new HashMap<>(); + try (ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream(fileText))) { + kv.put("baseURL", "baeldung.com"); + kv.put("apiKey", "this_is_a_test_key"); + objectOutStream.writeObject(kv); + } + //Deserialize the contents of a file then transform it back into a Hashmap + try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(fileText))) { + HashMap inputKv = (HashMap) input.readObject(); + assertThat(kv.get("baseURL")).isEqualTo( inputKv.get("baseURL")); + assertThat(kv.get("apiKey")).isEqualTo( inputKv.get("apiKey")); } } @@ -72,27 +88,4 @@ public class InputStreamUnitTest { return sb.toString(); } - @Test - public void givenKeyValuePairs_whenWrittenInATextFile_thenSuccessWhenParsedWithObjectInputStream( - @TempDir(cleanup = ALWAYS) Path tempDir) throws IOException, ClassNotFoundException { - Path sampleOut = tempDir.resolve("sample-out.txt"); - File fileText = sampleOut.toFile(); - //Serialize a Hashmap then write it into a file. - Map kv = new HashMap<>(); - try (FileOutputStream fileOutStream = new FileOutputStream(fileText)) { - try (ObjectOutputStream objectOutStream = new ObjectOutputStream(fileOutStream)) { - kv.put("baseURL", "baeldung.com"); - kv.put("apiKey", "this_is_a_test_key"); - objectOutStream.writeObject(kv); - } - } - //Deserialize the contents of a file then transform it back into a Hashmap - try (FileInputStream fileStream = new FileInputStream(fileText)) { - try (ObjectInputStream input = new ObjectInputStream(fileStream)) { - HashMap inputKv = (HashMap) input.readObject(); - Assert.assertEquals(kv.get("baseURL"), inputKv.get("baseURL")); - Assert.assertEquals(kv.get("apiKey"), inputKv.get("apiKey")); - } - } - } } diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java index ea4572fa5f..2dfcc4f9e7 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java @@ -1,5 +1,7 @@ package com.baeldung.inputstreamreader; +import static org.assertj.core.api.Assertions.assertThat; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; @@ -10,10 +12,8 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.List; -import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; - public class InputStreamReaderUnitTest { @Test public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { @@ -21,9 +21,9 @@ public class InputStreamReaderUnitTest { String sampleTxt = "Good day. This is just a test. Good bye."; Path sampleOut = tempDir.resolve("sample-out.txt"); List lines = Arrays.asList(sampleTxt); - //create and write file Files.write(sampleOut, lines); - try (FileInputStream fis = new FileInputStream(String.valueOf(sampleOut.toAbsolutePath())); BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8))) { + String absolutePath = String.valueOf(sampleOut.toAbsolutePath()); + try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8))) { String ln; while ((ln = br.readLine()) != null) { if (ln.contains(sampleTxt)) { @@ -31,7 +31,7 @@ public class InputStreamReaderUnitTest { break; } } - Assert.assertTrue(isMatched); + assertThat(isMatched).isTrue(); } } } From ed1e58c45e3e0b948be7fbe9f3e3503a1e78f687 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Tue, 20 Feb 2024 15:08:05 +0100 Subject: [PATCH 07/88] BAEL-7131 version 7 --- .../com/baeldung/inputstream/InputStreamUnitTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java index e253690762..6488e91c3e 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java @@ -21,7 +21,7 @@ import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; public class InputStreamUnitTest { - @Test //givenAStringWrittenToAFile_whenReadByX_thenY + @Test public void givenAStringWrittenToFile_whenReadWithFileInputStream_thenItShouldExitsInTheInputStream(@TempDir Path tempDir) throws IOException { Path sampleOut = tempDir.resolve("sample-out.txt"); List lines = Arrays.asList("Hello. This is just a test. Good bye."); @@ -60,19 +60,18 @@ public class InputStreamUnitTest { } } @Test - public void givenKeyValuePairsWrittenInAFile_whenPassedInOutputStreams_thenThePairsShouldExistsInObjectInputStreams( - @TempDir Path tempDir) throws IOException, ClassNotFoundException { + public void givenKeyValuePairsWrittenInAFile_whenPassedInOutputStreams_thenThePairsShouldExistsInObjectInputStreams(@TempDir Path tempDir) throws IOException, ClassNotFoundException { Path sampleOut = tempDir.resolve("sample-out.txt"); - File fileText = sampleOut.toFile(); + File textFile = sampleOut.toFile(); //Serialize a Hashmap then write it into a file. Map kv = new HashMap<>(); - try (ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream(fileText))) { + try (ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream(textFile))) { kv.put("baseURL", "baeldung.com"); kv.put("apiKey", "this_is_a_test_key"); objectOutStream.writeObject(kv); } //Deserialize the contents of a file then transform it back into a Hashmap - try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(fileText))) { + try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(textFile))) { HashMap inputKv = (HashMap) input.readObject(); assertThat(kv.get("baseURL")).isEqualTo( inputKv.get("baseURL")); assertThat(kv.get("apiKey")).isEqualTo( inputKv.get("apiKey")); From 9178b53dc94f5297cd3bb8c2fd16919c41116ae3 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Wed, 21 Feb 2024 11:10:39 +0100 Subject: [PATCH 08/88] BAEL-7131 - reapplied Baeldung Formatter, code changes from PR. --- .../inputstream/InputStreamUnitTest.java | 24 ++++++++----------- .../InputStreamReaderUnitTest.java | 3 ++- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java index 6488e91c3e..7fa5d760a5 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java @@ -17,9 +17,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; + public class InputStreamUnitTest { @Test public void givenAStringWrittenToFile_whenReadWithFileInputStream_thenItShouldExitsInTheInputStream(@TempDir Path tempDir) throws IOException { @@ -41,14 +41,9 @@ public class InputStreamUnitTest { String fileAbsolutePath = sampleOut.toFile() .getAbsolutePath(); try (FileInputStream fis = new FileInputStream(fileAbsolutePath)) { - int content; int availableBytes = fis.available(); - Assert.assertTrue(availableBytes > 0); - StringBuilder actualReadText = new StringBuilder(); - while ((content = fis.read()) != -1) { - actualReadText.append((char) content); - } - assertThat(actualReadText.toString()).contains(expectedText); + assertThat(availableBytes > 0); + assertThat(readString(fis)).contains(expectedText); } } @@ -59,6 +54,7 @@ public class InputStreamUnitTest { assertThat(readString(bais)).isEqualTo("hello"); } } + @Test public void givenKeyValuePairsWrittenInAFile_whenPassedInOutputStreams_thenThePairsShouldExistsInObjectInputStreams(@TempDir Path tempDir) throws IOException, ClassNotFoundException { Path sampleOut = tempDir.resolve("sample-out.txt"); @@ -66,15 +62,15 @@ public class InputStreamUnitTest { //Serialize a Hashmap then write it into a file. Map kv = new HashMap<>(); try (ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream(textFile))) { - kv.put("baseURL", "baeldung.com"); - kv.put("apiKey", "this_is_a_test_key"); - objectOutStream.writeObject(kv); + kv.put("baseURL", "baeldung.com"); + kv.put("apiKey", "this_is_a_test_key"); + objectOutStream.writeObject(kv); } //Deserialize the contents of a file then transform it back into a Hashmap try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(textFile))) { - HashMap inputKv = (HashMap) input.readObject(); - assertThat(kv.get("baseURL")).isEqualTo( inputKv.get("baseURL")); - assertThat(kv.get("apiKey")).isEqualTo( inputKv.get("apiKey")); + HashMap inputKv = (HashMap) input.readObject(); + assertThat(kv.get("baseURL")).isEqualTo(inputKv.get("baseURL")); + assertThat(kv.get("apiKey")).isEqualTo(inputKv.get("apiKey")); } } diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java index 2dfcc4f9e7..358ed5dea0 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java @@ -14,10 +14,10 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; + public class InputStreamReaderUnitTest { @Test public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { - boolean isMatched = false; String sampleTxt = "Good day. This is just a test. Good bye."; Path sampleOut = tempDir.resolve("sample-out.txt"); List lines = Arrays.asList(sampleTxt); @@ -25,6 +25,7 @@ public class InputStreamReaderUnitTest { String absolutePath = String.valueOf(sampleOut.toAbsolutePath()); try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8))) { String ln; + boolean isMatched = false; while ((ln = br.readLine()) != null) { if (ln.contains(sampleTxt)) { isMatched = true; From c84563ff4dc805574d8592a0963ca4a68a8c49d9 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Thu, 22 Feb 2024 11:33:25 +0100 Subject: [PATCH 09/88] BAEL-7131 - fixed incomplete Assertion --- .../test/java/com/baeldung/inputstream/InputStreamUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java index 7fa5d760a5..6ad3c03d8b 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java @@ -42,7 +42,7 @@ public class InputStreamUnitTest { .getAbsolutePath(); try (FileInputStream fis = new FileInputStream(fileAbsolutePath)) { int availableBytes = fis.available(); - assertThat(availableBytes > 0); + assertThat(availableBytes).isGreaterThan(0); assertThat(readString(fis)).contains(expectedText); } } From 05f652e4bf69806c7dc25c77ded75f055712a3ff Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Sun, 3 Mar 2024 15:20:06 +0530 Subject: [PATCH 10/88] BAEL-7521 - dynamically registering spring beans --- spring-di-4/src/main/resources/application.yml | 10 +++++++++- spring-di-4/src/test/resources/application.yml | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/spring-di-4/src/main/resources/application.yml b/spring-di-4/src/main/resources/application.yml index 5c09fdb8b0..51d20e5b40 100644 --- a/spring-di-4/src/main/resources/application.yml +++ b/spring-di-4/src/main/resources/application.yml @@ -1 +1,9 @@ -ambiguous-bean: 'A' \ No newline at end of file +ambiguous-bean: 'A' +api: + clients: + - name: example + url: https://api.example.com + key: 12345 + - name: anotherexample + url: https://api.anotherexample.com + key: 67890 \ No newline at end of file diff --git a/spring-di-4/src/test/resources/application.yml b/spring-di-4/src/test/resources/application.yml index da23e59c24..09ec2c0921 100644 --- a/spring-di-4/src/test/resources/application.yml +++ b/spring-di-4/src/test/resources/application.yml @@ -1 +1,9 @@ -ambiguous-bean: 'B' \ No newline at end of file +ambiguous-bean: 'B' +api: + clients: + - name: example + url: https://api.example.com + apiKey: 12345 + - name: anotherexample + url: https://api.anotherexample.com + apiKey: 67890 \ No newline at end of file From 4581d73fcedfe83b76a927cc032908cc05709b3c Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Sun, 3 Mar 2024 15:20:33 +0530 Subject: [PATCH 11/88] BAEL-7521 - dynamically registering spring beans --- .../ApiClientConfiguration.java | 42 +++++++++++++++++ .../RegistryPostProcessorApplication.java | 22 +++++++++ .../registrypostprocessor/bean/ApiClient.java | 45 +++++++++++++++++++ .../ApiClientConfigurationTest.java | 23 ++++++++++ 4 files changed, 132 insertions(+) create mode 100644 spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java create mode 100644 spring-di-4/src/main/java/com/baeldung/registrypostprocessor/RegistryPostProcessorApplication.java create mode 100644 spring-di-4/src/main/java/com/baeldung/registrypostprocessor/bean/ApiClient.java create mode 100644 spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java diff --git a/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java new file mode 100644 index 0000000000..db9d7f42f4 --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java @@ -0,0 +1,42 @@ +package com.baeldung.registrypostprocessor; + +import com.baeldung.registrypostprocessor.bean.ApiClient; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.core.env.Environment; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ApiClientConfiguration implements BeanDefinitionRegistryPostProcessor { + private static final String API_CLIENT_BEAN_NAME = "apiClient_"; + List clients; + + public ApiClientConfiguration(Environment environment) { + Binder binder = Binder.get(environment); + List properties = binder.bind("api.clients", Bindable.listOf(HashMap.class)).get(); + clients = properties.stream().map(client -> new ApiClient(String.valueOf(client.get("name")), + String.valueOf(client.get("url")), String.valueOf(client.get("key")))).toList(); + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + clients.forEach(client -> { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ApiClient.class); + builder.addPropertyValue("name", client.getName()); + builder.addPropertyValue("url", client.getUrl()); + builder.addPropertyValue("key", client.getKey()); + registry.registerBeanDefinition(API_CLIENT_BEAN_NAME + client.getName(), builder.getBeanDefinition()); + }); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + } +} \ No newline at end of file diff --git a/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/RegistryPostProcessorApplication.java b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/RegistryPostProcessorApplication.java new file mode 100644 index 0000000000..311f72e0fa --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/RegistryPostProcessorApplication.java @@ -0,0 +1,22 @@ +package com.baeldung.registrypostprocessor; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.ConfigurableEnvironment; + + +@SpringBootApplication +public class RegistryPostProcessorApplication { + + public static void main(String[] args) { + SpringApplication.run(RegistryPostProcessorApplication.class, args); + } + + @Bean + public ApiClientConfiguration apiClientConfiguration(ConfigurableEnvironment environment) { + return new ApiClientConfiguration(environment); + } + +} + diff --git a/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/bean/ApiClient.java b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/bean/ApiClient.java new file mode 100644 index 0000000000..00d7f58a9a --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/bean/ApiClient.java @@ -0,0 +1,45 @@ +package com.baeldung.registrypostprocessor.bean; + +public class ApiClient { + private String name; + private String url; + private String key; + + public ApiClient(String name, String url, String key) { + this.name = name; + this.url = url; + this.key = key; + } + + public ApiClient() { + } + + public String getName() { + return name; + } + + public String getUrl() { + return url; + } + + public String getKey() { + return key; + } + + public String getConnectionProperties() { + return "Connecting to " + name + " at " + url; + } + + public void setName(String name) { + this.name = name; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setKey(String key) { + this.key = key; + } + +} \ No newline at end of file diff --git a/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java b/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java new file mode 100644 index 0000000000..6e38152332 --- /dev/null +++ b/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java @@ -0,0 +1,23 @@ +package com.baeldung.registrypostprocessor; + +import com.baeldung.registrypostprocessor.bean.ApiClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; + +@SpringBootTest(classes = RegistryPostProcessorApplication.class) +public class ApiClientConfigurationTest { + @Autowired + private ApplicationContext context; + + @Test + void givenBeansRegistered_whenConnect_thenConnected() { + ApiClient exampleClient = (ApiClient) context.getBean("apiClient_example"); + Assertions.assertEquals("Connecting to example at https://api.example.com", exampleClient.getConnectionProperties()); + + ApiClient anotherExampleClient = (ApiClient) context.getBean("apiClient_anotherexample"); + Assertions.assertEquals("Connecting to anotherexample at https://api.anotherexample.com", anotherExampleClient.getConnectionProperties()); + } +} \ No newline at end of file From bbd70d96038866bf141bc5adf3c61b54a8529a72 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Sun, 3 Mar 2024 15:33:36 +0530 Subject: [PATCH 12/88] BAEL-7521 - dynamically registering spring beans --- .../baeldung/registrypostprocessor/ApiClientConfiguration.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java index db9d7f42f4..5faf5d2707 100644 --- a/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java +++ b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java @@ -12,7 +12,6 @@ import org.springframework.core.env.Environment; import java.util.HashMap; import java.util.List; -import java.util.Map; public class ApiClientConfiguration implements BeanDefinitionRegistryPostProcessor { private static final String API_CLIENT_BEAN_NAME = "apiClient_"; From 619842cd596ed29d3af983b932c8ec2139e130d0 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Sun, 3 Mar 2024 15:38:04 +0530 Subject: [PATCH 13/88] BAEL-7521 - dynamically registering spring beans --- ...nfigurationTest.java => ApiClientConfigurationUnitTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-di-4/src/test/java/com/baeldung/registrypostprocessor/{ApiClientConfigurationTest.java => ApiClientConfigurationUnitTest.java} (95%) diff --git a/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java b/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationUnitTest.java similarity index 95% rename from spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java rename to spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationUnitTest.java index 6e38152332..80e578166c 100644 --- a/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationTest.java +++ b/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationUnitTest.java @@ -8,7 +8,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; @SpringBootTest(classes = RegistryPostProcessorApplication.class) -public class ApiClientConfigurationTest { +public class ApiClientConfigurationUnitTest { @Autowired private ApplicationContext context; From 9d7262f27d4c95f32450feccebe4862eab5c5b31 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Sun, 3 Mar 2024 15:45:41 +0530 Subject: [PATCH 14/88] BAEL-7521 - adding main class in properties --- spring-di-4/pom.xml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/spring-di-4/pom.xml b/spring-di-4/pom.xml index 1eec8efcf0..a486b19e51 100644 --- a/spring-di-4/pom.xml +++ b/spring-di-4/pom.xml @@ -24,5 +24,15 @@ spring-boot-starter-test - + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.registrypostprocessor.RegistryPostProcessorApplication + + + + \ No newline at end of file From 028a0dbe9f88927c16d13af07b3e0549a6a643a1 Mon Sep 17 00:00:00 2001 From: ovidiu-mihai98 <138307181+ovidiumihaitacu@users.noreply.github.com> Date: Sun, 3 Mar 2024 20:25:07 +0200 Subject: [PATCH 15/88] [BAEL-7421] - Creating Postgres Schema with Liquibase --- persistence-modules/liquibase/pom.xml | 54 ++++++++++++++++--- .../LiquibaseCreateSchemaApplication.java | 12 +++++ .../configuration/SchemaInitializer.java | 31 +++++++++++ .../com/baeldung/liquibase/entity/User.java | 30 +++++++++++ .../src/main/resources/application.properties | 5 ++ .../main/resources/liquibase/changelog.xml | 23 ++++++++ .../resources/preliquibase/postgresql.sql | 1 + 7 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java create mode 100644 persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java create mode 100644 persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java create mode 100644 persistence-modules/liquibase/src/main/resources/application.properties create mode 100644 persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml create mode 100644 persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql diff --git a/persistence-modules/liquibase/pom.xml b/persistence-modules/liquibase/pom.xml index a6e0ed85e9..9ed1791e81 100644 --- a/persistence-modules/liquibase/pom.xml +++ b/persistence-modules/liquibase/pom.xml @@ -4,13 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 liquibase + com.baeldung liquibase - - - com.baeldung - persistence-modules - 1.0.0-SNAPSHOT - + 0.0.1-SNAPSHOT @@ -18,6 +14,38 @@ mysql-connector-j ${mysql-connector-java.version} + + org.springframework.boot + spring-boot-starter-web + 3.2.3 + + + org.slf4j + slf4j-log4j12 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + 3.2.3 + + + org.liquibase + liquibase-core + 4.24.0 + + + org.postgresql + postgresql + 42.6.1 + runtime + + + net.lbruun.springboot + preliquibase-spring-boot-starter + 1.5.0 + @@ -32,12 +60,26 @@ liquibase/db-changelog.xml + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.release} + --enable-preview + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + 8.2.0 4.25.0 + 17 + 17 + 17 + 17 \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java new file mode 100644 index 0000000000..f501cbf82a --- /dev/null +++ b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/LiquibaseCreateSchemaApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.liquibase; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LiquibaseCreateSchemaApplication { + + public static void main(String[] args) { + SpringApplication.run(LiquibaseCreateSchemaApplication.class, args); + } +} diff --git a/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java new file mode 100644 index 0000000000..cf122070c2 --- /dev/null +++ b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/configuration/SchemaInitializer.java @@ -0,0 +1,31 @@ +package com.baeldung.liquibase.configuration; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.BeanPostProcessor; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class SchemaInitializer implements BeanPostProcessor { + + @Value("${spring.liquibase.default-schema}") + private String schemaName; + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof DataSource) { + DataSource dataSource = (DataSource) bean; + try { + Connection conn = dataSource.getConnection(); + Statement statement = conn.createStatement(); + statement.execute(String.format("CREATE SCHEMA IF NOT EXISTS %s", schemaName)); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return bean; + } +} \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java new file mode 100644 index 0000000000..9beedfb55f --- /dev/null +++ b/persistence-modules/liquibase/src/main/java/com/baeldung/liquibase/entity/User.java @@ -0,0 +1,30 @@ +package com.baeldung.liquibase.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "users") +public class User { + + @Id + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/liquibase/src/main/resources/application.properties b/persistence-modules/liquibase/src/main/resources/application.properties new file mode 100644 index 0000000000..77740c8e2b --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/application.properties @@ -0,0 +1,5 @@ +#spring.datasource.url=jdbc:postgresql://some-postgresql-host/some-postgresql-database +#spring.datasource.username=your-postgresql-username +#spring.datasource.password=your-postgresql-password +#spring.liquibase.change-log=classpath:liquibase/changelog.xml +#spring.liquibase.default-schema=user_management \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml new file mode 100644 index 0000000000..cec8ae138f --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql b/persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql new file mode 100644 index 0000000000..03aad1cbd4 --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/preliquibase/postgresql.sql @@ -0,0 +1 @@ +CREATE SCHEMA IF NOT EXISTS user_management; \ No newline at end of file From 069952c65c366476d35f2feeea304e75a0edaab6 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Wed, 6 Mar 2024 01:22:17 +0100 Subject: [PATCH 16/88] BAEL-7131 - updated based on review comments from Final Review. --- .../inputstream/InputStreamUnitTest.java | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java index 6ad3c03d8b..e45e406f75 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java @@ -5,17 +5,12 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -32,21 +27,6 @@ public class InputStreamUnitTest { } } - @Test - public void givenAStringWrittenToFile_whenReadWithFileInputStreamWithStringConstructor_thenItShouldExitsInTheInputStream(@TempDir Path tempDir) throws IOException { - Path sampleOut = tempDir.resolve("sample-out.txt"); - String expectedText = "Hello. Hi."; - List lines = Arrays.asList(expectedText); - Files.write(sampleOut, lines); - String fileAbsolutePath = sampleOut.toFile() - .getAbsolutePath(); - try (FileInputStream fis = new FileInputStream(fileAbsolutePath)) { - int availableBytes = fis.available(); - assertThat(availableBytes).isGreaterThan(0); - assertThat(readString(fis)).contains(expectedText); - } - } - @Test public void givenAByteArray_whenReadWithByteArrayInputStream_thenTheStringValueOfTheByteArrayShouldMatchTheExpectedString() throws IOException { byte[] byteArray = { 104, 101, 108, 108, 111 }; @@ -55,25 +35,6 @@ public class InputStreamUnitTest { } } - @Test - public void givenKeyValuePairsWrittenInAFile_whenPassedInOutputStreams_thenThePairsShouldExistsInObjectInputStreams(@TempDir Path tempDir) throws IOException, ClassNotFoundException { - Path sampleOut = tempDir.resolve("sample-out.txt"); - File textFile = sampleOut.toFile(); - //Serialize a Hashmap then write it into a file. - Map kv = new HashMap<>(); - try (ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream(textFile))) { - kv.put("baseURL", "baeldung.com"); - kv.put("apiKey", "this_is_a_test_key"); - objectOutStream.writeObject(kv); - } - //Deserialize the contents of a file then transform it back into a Hashmap - try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(textFile))) { - HashMap inputKv = (HashMap) input.readObject(); - assertThat(kv.get("baseURL")).isEqualTo(inputKv.get("baseURL")); - assertThat(kv.get("apiKey")).isEqualTo(inputKv.get("apiKey")); - } - } - private static String readString(InputStream inputStream) throws IOException { int c; StringBuilder sb = new StringBuilder(); From 03b2f8bb58e4aabe7063f1b89cfcc3ecb0dbd45d Mon Sep 17 00:00:00 2001 From: adalagandev Date: Thu, 7 Mar 2024 23:53:35 +0100 Subject: [PATCH 17/88] BAEL-7131 - Updated pom.xml under core-java-io-apis-2 --- core-java-modules/core-java-io-apis-2/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/pom.xml b/core-java-modules/core-java-io-apis-2/pom.xml index 976cbd62e4..03ec8fc6cb 100644 --- a/core-java-modules/core-java-io-apis-2/pom.xml +++ b/core-java-modules/core-java-io-apis-2/pom.xml @@ -81,12 +81,6 @@ 7.1.0 test - - org.assertj - assertj-core - 3.4.1 - test - core-java-io-apis-2 From c3b389f4dcec431fa374a1ef366af925121da2fd Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Sat, 9 Mar 2024 00:09:04 +0100 Subject: [PATCH 18/88] [happy-number] happy number --- .../happynumber/HappyNumberUnitTest.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java new file mode 100644 index 0000000000..5cdf1a82c5 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java @@ -0,0 +1,82 @@ +package com.baeldung.algorithms.happynumber; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +class HappyNumberDecider { + + public static boolean isHappyNumber(int n) { + Set checkedNumbers = new HashSet<>(); + while (true) { + n = sumDigitsSquare(n); + if (n == 1) { + return true; + } + if (checkedNumbers.contains(n)) { + return false; + } + checkedNumbers.add(n); + } + } + + public static boolean isHappyNumber2(int n) { + int slow = n; + int fast = n; + do { + slow = sumDigitsSquare(slow); + fast = sumDigitsSquare(sumDigitsSquare(fast)); + } while (slow != fast); + + return slow == 1; + } + + private static int sumDigitsSquare(int n) { + int squareSum = 0; + while (n != 0) { + squareSum += (n % 10) * (n % 10); + n /= 10; + } + return squareSum; + } +} + +public class HappyNumberUnitTest { + + @Test + void whenUsingIsHappyNumber_thenGetTheExpectedResult() { + assertTrue(HappyNumberDecider.isHappyNumber(7)); + assertTrue(HappyNumberDecider.isHappyNumber(10)); + assertTrue(HappyNumberDecider.isHappyNumber(13)); + assertTrue(HappyNumberDecider.isHappyNumber(19)); + assertTrue(HappyNumberDecider.isHappyNumber(23)); + + assertFalse(HappyNumberDecider.isHappyNumber(4)); + assertFalse(HappyNumberDecider.isHappyNumber(6)); + assertFalse(HappyNumberDecider.isHappyNumber(11)); + assertFalse(HappyNumberDecider.isHappyNumber(15)); + assertFalse(HappyNumberDecider.isHappyNumber(20)); + + } + + @Test + void whenUsingIsHappyNumber2_thenGetTheExpectedResult() { + assertTrue(HappyNumberDecider.isHappyNumber2(7)); + assertTrue(HappyNumberDecider.isHappyNumber2(10)); + assertTrue(HappyNumberDecider.isHappyNumber2(13)); + assertTrue(HappyNumberDecider.isHappyNumber2(19)); + assertTrue(HappyNumberDecider.isHappyNumber2(23)); + + assertFalse(HappyNumberDecider.isHappyNumber2(4)); + assertFalse(HappyNumberDecider.isHappyNumber2(6)); + assertFalse(HappyNumberDecider.isHappyNumber2(11)); + assertFalse(HappyNumberDecider.isHappyNumber2(15)); + assertFalse(HappyNumberDecider.isHappyNumber2(20)); + + } + +} \ No newline at end of file From 11ee2130ccb2d084fd4385b89b47eec167d57926 Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Sun, 10 Mar 2024 18:05:49 +0100 Subject: [PATCH 19/88] [happy-number] renaming method --- .../happynumber/HappyNumberUnitTest.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java index 5cdf1a82c5..2056688659 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/happynumber/HappyNumberUnitTest.java @@ -24,7 +24,7 @@ class HappyNumberDecider { } } - public static boolean isHappyNumber2(int n) { + public static boolean isHappyNumberFloyd(int n) { int slow = n; int fast = n; do { @@ -65,17 +65,17 @@ public class HappyNumberUnitTest { @Test void whenUsingIsHappyNumber2_thenGetTheExpectedResult() { - assertTrue(HappyNumberDecider.isHappyNumber2(7)); - assertTrue(HappyNumberDecider.isHappyNumber2(10)); - assertTrue(HappyNumberDecider.isHappyNumber2(13)); - assertTrue(HappyNumberDecider.isHappyNumber2(19)); - assertTrue(HappyNumberDecider.isHappyNumber2(23)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(7)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(10)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(13)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(19)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(23)); - assertFalse(HappyNumberDecider.isHappyNumber2(4)); - assertFalse(HappyNumberDecider.isHappyNumber2(6)); - assertFalse(HappyNumberDecider.isHappyNumber2(11)); - assertFalse(HappyNumberDecider.isHappyNumber2(15)); - assertFalse(HappyNumberDecider.isHappyNumber2(20)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(4)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(6)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(11)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(15)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(20)); } From 63741db3d9a38bcf741e383e2c6bd72a0bd42254 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Sun, 10 Mar 2024 22:34:19 +0100 Subject: [PATCH 20/88] BAEL-7131 - Updated for final review comments --- .../inputstreamreader/InputStreamReaderUnitTest.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java index 358ed5dea0..d67b56e10b 100644 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java @@ -2,7 +2,6 @@ package com.baeldung.inputstreamreader; import static org.assertj.core.api.Assertions.assertThat; -import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; @@ -23,11 +22,13 @@ public class InputStreamReaderUnitTest { List lines = Arrays.asList(sampleTxt); Files.write(sampleOut, lines); String absolutePath = String.valueOf(sampleOut.toAbsolutePath()); - try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8))) { - String ln; + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8)) { boolean isMatched = false; - while ((ln = br.readLine()) != null) { - if (ln.contains(sampleTxt)) { + int b; + StringBuilder sb = new StringBuilder(); + while ((b = reader.read()) != -1) { + sb.append((char) b); + if (sb.toString().contains(sampleTxt)) { isMatched = true; break; } From 5eca855e375839c1e814d4a4e6d0f5884fe3ed85 Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Mon, 11 Mar 2024 03:05:52 +0000 Subject: [PATCH 21/88] Creating a Spring Security Key for Signing a JWT Token --- .../spring-security-core-2/pom.xml | 16 ++++ .../com/baeldung/jwtsignkey/JwtResponse.java | 54 +++++++++++ .../jwtsignkey/SpringJwtApplication.java | 4 + .../controller/JwtAuthController.java | 70 ++++++++++++++ .../jwtconfig/AuthEntryPointJwt.java | 39 ++++++++ .../jwtsignkey/jwtconfig/AuthTokenFilter.java | 63 +++++++++++++ .../jwtsignkey/jwtconfig/JwtUtils.java | 69 ++++++++++++++ .../com/baeldung/jwtsignkey/model/User.java | 45 +++++++++ .../jwtsignkey/repository/UserRepository.java | 12 +++ .../securityconfig/SecurityConfiguration.java | 80 ++++++++++++++++ .../userservice/UserDetailsImpl.java | 92 +++++++++++++++++++ .../userservice/UserDetailsServiceImpl.java | 28 ++++++ .../src/main/resources/application.properties | 4 +- 13 files changed, 575 insertions(+), 1 deletion(-) create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/model/User.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java diff --git a/spring-security-modules/spring-security-core-2/pom.xml b/spring-security-modules/spring-security-core-2/pom.xml index ace629eef1..94940f2613 100644 --- a/spring-security-modules/spring-security-core-2/pom.xml +++ b/spring-security-modules/spring-security-core-2/pom.xml @@ -17,6 +17,7 @@ com.baeldung.authresolver.AuthResolverApplication + 0.12.5 @@ -61,6 +62,21 @@ org.springframework.security spring-security-core + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java new file mode 100644 index 0000000000..371491d49e --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java @@ -0,0 +1,54 @@ +package com.baeldung.jwtsignkey; + +public class JwtResponse { + private String token; + private String type = "Bearer"; + + private String username; + + + public JwtResponse(String accessToken, String username) { + this.token = accessToken; + this.username = username; + } + + public String getAccessToken() { + return token; + } + + public void setAccessToken(String accessToken) { + this.token = accessToken; + } + + public String getTokenType() { + return type; + } + + public void setTokenType(String tokenType) { + this.type = tokenType; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java new file mode 100644 index 0000000000..72917323c2 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java @@ -0,0 +1,4 @@ +package com.baeldung.jwtsignkey; + +public class SpringJwtApplication { +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java new file mode 100644 index 0000000000..57b49ec9b8 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java @@ -0,0 +1,70 @@ +package com.baeldung.jwtsignkey.controller; + +import com.baeldung.jwtsignkey.jwtconfig.JwtUtils; +import com.baeldung.jwtsignkey.model.User; +import com.baeldung.jwtsignkey.repository.UserRepository; +import com.baeldung.jwtsignkey.userservice.UserDetailsImpl; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.io.UnsupportedEncodingException; + +@CrossOrigin(origins = "*", maxAge = 3600) +@RestController +public class JwtAuthController { + + @Autowired + AuthenticationManager authenticationManager; + + @Autowired + PasswordEncoder encoder; + + @Autowired + JwtUtils jwtUtils; + + @Autowired + UserRepository userRepository; + + @PostMapping("/signup") + public ResponseEntity registerUser(@RequestBody User signUpRequest, HttpServletRequest request) throws UnsupportedEncodingException { + + + // Create new user's account + User user = new User(); + user.setUsername(signUpRequest.getUsername()); + user.setPassword(encoder.encode(signUpRequest.getPassword())); + + userRepository.save(user); + + return ResponseEntity.ok(user); + } + + @PostMapping("/signin") + public ResponseEntity authenticateUser( @RequestBody LoginRequest loginRequest) { + + Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); + + SecurityContextHolder.getContext() + .setAuthentication(authentication); + UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal(); + + String jwt = jwtUtils.generateJwtToken(authentication); + + + + return ResponseEntity.ok( + new JwtResponse(jwt, userDetails.getUsername())); + + } + +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java new file mode 100644 index 0000000000..1fe3b6aa63 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java @@ -0,0 +1,39 @@ +package com.baeldung.jwtsignkey.jwtconfig; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@Component +public class AuthEntryPointJwt implements AuthenticationEntryPoint { + + private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class); + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + logger.error("Unauthorized error: {}", authException.getMessage()); + + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + + final Map body = new HashMap<>(); + body.put("status", HttpServletResponse.SC_UNAUTHORIZED); + body.put("error", "Unauthorized"); + body.put("message", authException.getMessage()); + body.put("path", request.getServletPath()); + + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(response.getOutputStream(), body); + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java new file mode 100644 index 0000000000..64dc102cff --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java @@ -0,0 +1,63 @@ +package com.baeldung.jwtsignkey.jwtconfig; + +import com.baeldung.jwtsignkey.userservice.UserDetailsServiceImpl; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +public class AuthTokenFilter extends OncePerRequestFilter { + @Autowired + private JwtUtils jwtUtils; + + @Autowired + private UserDetailsServiceImpl userDetailsService; + + private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class); + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + try { + String jwt = parseJwt(request); + if (jwt != null && jwtUtils.validateJwtToken(jwt)) { + String username = jwtUtils.getUserNameFromJwtToken(jwt); + + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken( + userDetails, + null, + userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } catch (Exception e) { + logger.error("Cannot set user authentication: {}", e); + } + + filterChain.doFilter(request, response); + } + + private String parseJwt(HttpServletRequest request) { + String headerAuth = request.getHeader("Authorization"); + + if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { + return headerAuth.substring(7, headerAuth.length()); + } + + return null; + } +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java new file mode 100644 index 0000000000..a5c3ac9556 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java @@ -0,0 +1,69 @@ +package com.baeldung.jwtsignkey.jwtconfig; + +import com.baeldung.jwtsignkey.userservice.UserDetailsImpl; +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Date; + +@Component +public class JwtUtils { + private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); + + @Value("${baeldung.app.jwtSecret}") + private String jwtSecret; + + @Value("${baeldung.app.jwtExpirationMs}") + private int jwtExpirationMs; + + public String generateJwtToken(Authentication authentication) { + + UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); + + return Jwts.builder() + .setSubject((userPrincipal.getUsername())) + .setIssuedAt(new Date()) + .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs)) + .signWith(getSigningKey()) + .compact(); + + } + + private Key getSigningKey() { + byte[] keyBytes = this.jwtSecret.getBytes(StandardCharsets.UTF_8); + return Keys.hmacShaKeyFor(keyBytes); + } + + public String getUserNameFromJwtToken(String token) { + //return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject(); + return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody().getSubject(); + + } + + public boolean validateJwtToken(String authToken) { + try { + Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(authToken); + return true; + } catch (SignatureException e) { + logger.error("Invalid JWT signature: {}", e.getMessage()); + } catch (MalformedJwtException e) { + logger.error("Invalid JWT token: {}", e.getMessage()); + } catch (ExpiredJwtException e) { + logger.error("JWT token is expired: {}", e.getMessage()); + } catch (UnsupportedJwtException e) { + logger.error("JWT token is unsupported: {}", e.getMessage()); + } catch (IllegalArgumentException e) { + logger.error("JWT claims string is empty: {}", e.getMessage()); + } + + return false; + } + +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/model/User.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/model/User.java new file mode 100644 index 0000000000..c7acda047a --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/model/User.java @@ -0,0 +1,45 @@ +package com.baeldung.jwtsignkey.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String username; + + private String password; + + public User() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java new file mode 100644 index 0000000000..8d2706f756 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.jwtsignkey.repository; + +import com.baeldung.jwtsignkey.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + + Optional findByUsername(String username); + +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java new file mode 100644 index 0000000000..be980966c8 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java @@ -0,0 +1,80 @@ +package com.baeldung.jwtsignkey.securityconfig; + +import com.baeldung.jwtsignkey.jwtconfig.AuthEntryPointJwt; +import com.baeldung.jwtsignkey.jwtconfig.AuthTokenFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity +public class SecurityConfiguration { + + @Autowired + UserDetailsService userDetailsService; + @Autowired + private AuthEntryPointJwt unauthorizedHandler; + + private static final String[] WHITE_LIST_URL = { "/signin", "/signup" + }; + + @Bean + public AuthTokenFilter authenticationJwtTokenFilter() { + return new AuthTokenFilter(); + } + + + + @Bean + public DaoAuthenticationProvider authenticationProvider() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + + authProvider.setUserDetailsService(userDetailsService); + authProvider.setPasswordEncoder(passwordEncoder()); + + return authProvider; + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { + return authConfig.getAuthenticationManager(); + } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.csrf(AbstractHttpConfigurer::disable) + .cors(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(req -> req.requestMatchers(WHITE_LIST_URL) + .permitAll() + .anyRequest() + .authenticated()) + .exceptionHandling( ex -> ex.authenticationEntryPoint(unauthorizedHandler)) + .sessionManagement(session -> session.sessionCreationPolicy(STATELESS)) + .authenticationProvider(authenticationProvider()) + .addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); + + return http.build(); + } + +} + diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java new file mode 100644 index 0000000000..7c145d50c8 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java @@ -0,0 +1,92 @@ +package com.baeldung.jwtsignkey.userservice; + +import com.baeldung.jwtsignkey.model.User; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Objects; + +public class UserDetailsImpl implements UserDetails { + private static final long serialVersionUID = 1L; + + private Long id; + + private String username; + + @JsonIgnore + private String password; + + + public UserDetailsImpl(Long id, String username, String password) { + this.id = id; + this.username = username; + this.password = password; + + } + + public static UserDetailsImpl build(User user) { + + + return new UserDetailsImpl(user.getId(), user.getUsername(), user.getPassword()); + } + + + public Long getId() { + return id; + } + + + + public static long getSerialversionuid() { + return serialVersionUID; + } + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + UserDetailsImpl user = (UserDetailsImpl) o; + return Objects.equals(id, user.id); + } +} diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java new file mode 100644 index 0000000000..dcaa4ec716 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java @@ -0,0 +1,28 @@ +package com.baeldung.jwtsignkey.userservice; + +import com.baeldung.jwtsignkey.model.User; +import com.baeldung.jwtsignkey.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +; + +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + + @Autowired + UserRepository userRepository; + + @Override + @Transactional + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username)); + + return UserDetailsImpl.build(user); + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-core-2/src/main/resources/application.properties b/spring-security-modules/spring-security-core-2/src/main/resources/application.properties index 9d154c9cc0..d6d6a6f507 100644 --- a/spring-security-modules/spring-security-core-2/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-core-2/src/main/resources/application.properties @@ -1 +1,3 @@ -spring.thymeleaf.prefix=classpath:/templates/ \ No newline at end of file +spring.thymeleaf.prefix=classpath:/templates/ +baeldung.app.jwtSecret= 404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970 +baeldung.app.jwtExpirationMs= 8640000 \ No newline at end of file From 1fea1bf611afd79c7a6d3fe1097834c37be2ff9b Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Mon, 11 Mar 2024 17:52:07 +0000 Subject: [PATCH 22/88] Creating a Spring Security Key for Signing a JWT Token --- .../jwtsignkey/SpringJwtApplication.java | 10 ++ .../controller/JwtAuthController.java | 33 ++++--- .../jwtconfig/AuthEntryPointJwt.java | 28 +++--- .../jwtsignkey/jwtconfig/AuthTokenFilter.java | 60 ++++++------ .../jwtsignkey/jwtconfig/JwtUtils.java | 98 +++++++++++-------- .../jwtsignkey/repository/UserRepository.java | 2 + .../{ => response}/JwtResponse.java | 3 +- .../securityconfig/SecurityConfiguration.java | 29 +++--- .../userservice/UserDetailsImpl.java | 7 -- .../userservice/UserDetailsServiceImpl.java | 18 ++-- .../com/baeldung/request/LoginRequest.java | 24 +++++ .../src/main/resources/application.properties | 3 +- .../JwtSignKeyIntegrationTest.java | 40 ++++++++ 13 files changed, 218 insertions(+), 137 deletions(-) rename spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/{ => response}/JwtResponse.java (95%) create mode 100644 spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/request/LoginRequest.java create mode 100644 spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/jwtsecuritykey/JwtSignKeyIntegrationTest.java diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java index 72917323c2..611935e566 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java @@ -1,4 +1,14 @@ package com.baeldung.jwtsignkey; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +@SpringBootApplication +@EnableWebMvc public class SpringJwtApplication { + + public static void main(String[] args) { + SpringApplication.run(com.baeldung.jwtsignkey.SpringJwtApplication.class); + } } diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java index 57b49ec9b8..37de1682db 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java @@ -3,23 +3,25 @@ package com.baeldung.jwtsignkey.controller; import com.baeldung.jwtsignkey.jwtconfig.JwtUtils; import com.baeldung.jwtsignkey.model.User; import com.baeldung.jwtsignkey.repository.UserRepository; +import com.baeldung.jwtsignkey.response.JwtResponse; import com.baeldung.jwtsignkey.userservice.UserDetailsImpl; +import com.baeldung.request.LoginRequest; import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.bind.annotation.CrossOrigin; 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.RestController; import java.io.UnsupportedEncodingException; -@CrossOrigin(origins = "*", maxAge = 3600) @RestController public class JwtAuthController { @@ -38,8 +40,10 @@ public class JwtAuthController { @PostMapping("/signup") public ResponseEntity registerUser(@RequestBody User signUpRequest, HttpServletRequest request) throws UnsupportedEncodingException { - - // Create new user's account + if (userRepository.existsByUsername(signUpRequest.getUsername())) { + return ResponseEntity.badRequest() + .body("Error: Username is already taken!"); + } User user = new User(); user.setUsername(signUpRequest.getUsername()); user.setPassword(encoder.encode(signUpRequest.getPassword())); @@ -50,21 +54,24 @@ public class JwtAuthController { } @PostMapping("/signin") - public ResponseEntity authenticateUser( @RequestBody LoginRequest loginRequest) { + public ResponseEntity authenticateUser(@RequestBody LoginRequest loginRequest) { - Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); + Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); - SecurityContextHolder.getContext() - .setAuthentication(authentication); + SecurityContextHolder.getContext() + .setAuthentication(authentication); UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal(); - String jwt = jwtUtils.generateJwtToken(authentication); + String jwt = jwtUtils.generateJwtToken(authentication); - - - return ResponseEntity.ok( - new JwtResponse(jwt, userDetails.getUsername())); + return ResponseEntity.ok(new JwtResponse(jwt, userDetails.getUsername())); } + @RequestMapping("/user-dashboard") + @PreAuthorize("isAuthenticated()") + public String dashboard() { + return "My Dashboard"; + } + } diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java index 1fe3b6aa63..1cc64f3550 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthEntryPointJwt.java @@ -18,22 +18,22 @@ import java.util.Map; @Component public class AuthEntryPointJwt implements AuthenticationEntryPoint { - private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class); + private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class); - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - logger.error("Unauthorized error: {}", authException.getMessage()); + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + logger.error("Unauthorized error: {}", authException.getMessage()); - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - final Map body = new HashMap<>(); - body.put("status", HttpServletResponse.SC_UNAUTHORIZED); - body.put("error", "Unauthorized"); - body.put("message", authException.getMessage()); - body.put("path", request.getServletPath()); + final Map body = new HashMap<>(); + body.put("status", HttpServletResponse.SC_UNAUTHORIZED); + body.put("error", "Unauthorized"); + body.put("message", authException.getMessage()); + body.put("path", request.getServletPath()); - final ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(response.getOutputStream(), body); - } + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(response.getOutputStream(), body); + } } \ No newline at end of file diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java index 64dc102cff..a149c71121 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java @@ -18,46 +18,42 @@ import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; public class AuthTokenFilter extends OncePerRequestFilter { - @Autowired - private JwtUtils jwtUtils; + @Autowired + private JwtUtils jwtUtils; - @Autowired - private UserDetailsServiceImpl userDetailsService; + @Autowired + private UserDetailsServiceImpl userDetailsService; - private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class); + private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class); - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - try { - String jwt = parseJwt(request); - if (jwt != null && jwtUtils.validateJwtToken(jwt)) { - String username = jwtUtils.getUserNameFromJwtToken(jwt); + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + try { + String jwt = parseJwt(request); + if (jwt != null && jwtUtils.validateJwtToken(jwt)) { + String username = jwtUtils.getUserNameFromJwtToken(jwt); - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - UsernamePasswordAuthenticationToken authentication = - new UsernamePasswordAuthenticationToken( - userDetails, - null, - userDetails.getAuthorities()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } catch (Exception e) { - logger.error("Cannot set user authentication: {}", e); + SecurityContextHolder.getContext() + .setAuthentication(authentication); + } + } catch (Exception e) { + logger.error("Cannot set user authentication: {}", e); + } + + filterChain.doFilter(request, response); } - filterChain.doFilter(request, response); - } + private String parseJwt(HttpServletRequest request) { + String headerAuth = request.getHeader("Authorization"); - private String parseJwt(HttpServletRequest request) { - String headerAuth = request.getHeader("Authorization"); + if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { + return headerAuth.substring(7, headerAuth.length()); + } - if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { - return headerAuth.substring(7, headerAuth.length()); + return null; } - - return null; - } } diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java index a5c3ac9556..44b2128a3b 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java @@ -1,8 +1,13 @@ package com.baeldung.jwtsignkey.jwtconfig; import com.baeldung.jwtsignkey.userservice.UserDetailsImpl; -import io.jsonwebtoken.*; + +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SignatureException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -15,55 +20,62 @@ import java.util.Date; @Component public class JwtUtils { - private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); + private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); - @Value("${baeldung.app.jwtSecret}") - private String jwtSecret; + @Value("${baeldung.app.jwtSecret}") + private String jwtSecret; - @Value("${baeldung.app.jwtExpirationMs}") - private int jwtExpirationMs; + @Value("${baeldung.app.jwtExpirationMs}") + private int jwtExpirationMs; - public String generateJwtToken(Authentication authentication) { + public String generateJwtToken(Authentication authentication) { - UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); + UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); - return Jwts.builder() - .setSubject((userPrincipal.getUsername())) - .setIssuedAt(new Date()) - .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs)) - .signWith(getSigningKey()) - .compact(); + return Jwts.builder() + .subject((userPrincipal.getUsername())) + .issuedAt(new Date()) + .expiration(new Date((new Date()).getTime() + jwtExpirationMs)) + .signWith(getSigningKey()) + .compact(); - } - - private Key getSigningKey() { - byte[] keyBytes = this.jwtSecret.getBytes(StandardCharsets.UTF_8); - return Keys.hmacShaKeyFor(keyBytes); - } - - public String getUserNameFromJwtToken(String token) { - //return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject(); - return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody().getSubject(); - - } - - public boolean validateJwtToken(String authToken) { - try { - Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(authToken); - return true; - } catch (SignatureException e) { - logger.error("Invalid JWT signature: {}", e.getMessage()); - } catch (MalformedJwtException e) { - logger.error("Invalid JWT token: {}", e.getMessage()); - } catch (ExpiredJwtException e) { - logger.error("JWT token is expired: {}", e.getMessage()); - } catch (UnsupportedJwtException e) { - logger.error("JWT token is unsupported: {}", e.getMessage()); - } catch (IllegalArgumentException e) { - logger.error("JWT claims string is empty: {}", e.getMessage()); } - return false; - } + private Key getSigningKey() { + byte[] keyBytes = this.jwtSecret.getBytes(StandardCharsets.UTF_8); + return Keys.hmacShaKeyFor(keyBytes); + } + + public String getUserNameFromJwtToken(String token) { + return Jwts.parser() + .setSigningKey(getSigningKey()) + .build() + .parseSignedClaims(token) + .getPayload() + .getSubject(); + + } + + public boolean validateJwtToken(String authToken) { + try { + Jwts.parser() + .setSigningKey(getSigningKey()) + .build() + .parseSignedClaims(authToken); + return true; + } catch (SignatureException e) { + logger.error("Invalid JWT signature: {}", e.getMessage()); + } catch (MalformedJwtException e) { + logger.error("Invalid JWT token: {}", e.getMessage()); + } catch (ExpiredJwtException e) { + logger.error("JWT token is expired: {}", e.getMessage()); + } catch (UnsupportedJwtException e) { + logger.error("JWT token is unsupported: {}", e.getMessage()); + } catch (IllegalArgumentException e) { + logger.error("JWT claims string is empty: {}", e.getMessage()); + } + + return false; + } } diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java index 8d2706f756..886338242c 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java @@ -7,6 +7,8 @@ import java.util.Optional; public interface UserRepository extends JpaRepository { + Boolean existsByUsername(String username); + Optional findByUsername(String username); } diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java similarity index 95% rename from spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java rename to spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java index 371491d49e..1c367c4999 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/JwtResponse.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java @@ -1,4 +1,4 @@ -package com.baeldung.jwtsignkey; +package com.baeldung.jwtsignkey.response; public class JwtResponse { private String token; @@ -6,7 +6,6 @@ public class JwtResponse { private String username; - public JwtResponse(String accessToken, String username) { this.token = accessToken; this.username = username; diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java index be980966c8..5a83826065 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java @@ -3,6 +3,7 @@ package com.baeldung.jwtsignkey.securityconfig; import com.baeldung.jwtsignkey.jwtconfig.AuthEntryPointJwt; import com.baeldung.jwtsignkey.jwtconfig.AuthTokenFilter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -17,6 +18,8 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS; @@ -30,16 +33,13 @@ public class SecurityConfiguration { @Autowired private AuthEntryPointJwt unauthorizedHandler; - private static final String[] WHITE_LIST_URL = { "/signin", "/signup" - }; + private static final String[] WHITE_LIST_URL = { "/h2-console/**","/signin", "/signup", "/user-dashboard" }; @Bean public AuthTokenFilter authenticationJwtTokenFilter() { return new AuthTokenFilter(); } - - @Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); @@ -61,20 +61,19 @@ public class SecurityConfiguration { } @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { http.csrf(AbstractHttpConfigurer::disable) - .cors(AbstractHttpConfigurer::disable) - .authorizeHttpRequests(req -> req.requestMatchers(WHITE_LIST_URL) - .permitAll() - .anyRequest() - .authenticated()) - .exceptionHandling( ex -> ex.authenticationEntryPoint(unauthorizedHandler)) - .sessionManagement(session -> session.sessionCreationPolicy(STATELESS)) - .authenticationProvider(authenticationProvider()) - .addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); + .cors(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(req -> req.requestMatchers(WHITE_LIST_URL) + .permitAll() + .anyRequest() + .authenticated()) + .exceptionHandling(ex -> ex.authenticationEntryPoint(unauthorizedHandler)) + .sessionManagement(session -> session.sessionCreationPolicy(STATELESS)) + .authenticationProvider(authenticationProvider()) + .addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } } - diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java index 7c145d50c8..a651a1088a 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java @@ -18,7 +18,6 @@ public class UserDetailsImpl implements UserDetails { @JsonIgnore private String password; - public UserDetailsImpl(Long id, String username, String password) { this.id = id; this.username = username; @@ -28,17 +27,13 @@ public class UserDetailsImpl implements UserDetails { public static UserDetailsImpl build(User user) { - return new UserDetailsImpl(user.getId(), user.getUsername(), user.getPassword()); } - public Long getId() { return id; } - - public static long getSerialversionuid() { return serialVersionUID; } @@ -78,8 +73,6 @@ public class UserDetailsImpl implements UserDetails { return true; } - - @Override public boolean equals(Object o) { if (this == o) diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java index dcaa4ec716..c544f748cd 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsServiceImpl.java @@ -14,15 +14,15 @@ import org.springframework.transaction.annotation.Transactional; @Service public class UserDetailsServiceImpl implements UserDetailsService { - @Autowired - UserRepository userRepository; + @Autowired + UserRepository userRepository; - @Override - @Transactional - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - User user = userRepository.findByUsername(username) - .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username)); + @Override + @Transactional + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username)); - return UserDetailsImpl.build(user); - } + return UserDetailsImpl.build(user); + } } \ No newline at end of file diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/request/LoginRequest.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/request/LoginRequest.java new file mode 100644 index 0000000000..24555136c2 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/request/LoginRequest.java @@ -0,0 +1,24 @@ +package com.baeldung.request; + +public class LoginRequest { + + private String username; + + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/spring-security-modules/spring-security-core-2/src/main/resources/application.properties b/spring-security-modules/spring-security-core-2/src/main/resources/application.properties index d6d6a6f507..6005cdd2d2 100644 --- a/spring-security-modules/spring-security-core-2/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-core-2/src/main/resources/application.properties @@ -1,3 +1,2 @@ -spring.thymeleaf.prefix=classpath:/templates/ baeldung.app.jwtSecret= 404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970 -baeldung.app.jwtExpirationMs= 8640000 \ No newline at end of file +baeldung.app.jwtExpirationMs= 8640000 diff --git a/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/jwtsecuritykey/JwtSignKeyIntegrationTest.java b/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/jwtsecuritykey/JwtSignKeyIntegrationTest.java new file mode 100644 index 0000000000..73d1142ceb --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/test/java/com/baeldung/jwtsecuritykey/JwtSignKeyIntegrationTest.java @@ -0,0 +1,40 @@ +package com.baeldung.jwtsecuritykey; + +import com.baeldung.jwtsignkey.SpringJwtApplication; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(classes = SpringJwtApplication.class) +public class JwtSignKeyIntegrationTest { + + @Autowired + private WebApplicationContext context; + + private MockMvc mvc; + + @BeforeEach + private void setup() { + mvc = MockMvcBuilders.webAppContextSetup(context) + .apply(springSecurity()) + .build(); + } + + + @Test + public void givenAnonymous_whenAccessUserDashboard_thenForbidden() throws Exception { + mvc.perform(get("/user-dashboard")) + .andExpect(status().isUnauthorized()); + } + + +} + From 89963eefd7204d0716d8c0eb75a1fce334055075 Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Tue, 12 Mar 2024 02:45:48 +0000 Subject: [PATCH 23/88] Creating a Spring Security Key for Signing a JWT Token --- .../jwtsignkey/jwtconfig/JwtUtils.java | 22 +++++++++++-------- .../jwtsignkey/response/JwtResponse.java | 16 -------------- .../securityconfig/SecurityConfiguration.java | 2 +- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java index 44b2128a3b..7ee397481b 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java @@ -6,6 +6,7 @@ import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SignatureException; import org.slf4j.Logger; @@ -14,6 +15,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; +import javax.crypto.SecretKey; import java.nio.charset.StandardCharsets; import java.security.Key; import java.util.Date; @@ -28,15 +30,17 @@ public class JwtUtils { @Value("${baeldung.app.jwtExpirationMs}") private int jwtExpirationMs; + SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret)); + public String generateJwtToken(Authentication authentication) { UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); return Jwts.builder() - .subject((userPrincipal.getUsername())) - .issuedAt(new Date()) - .expiration(new Date((new Date()).getTime() + jwtExpirationMs)) - .signWith(getSigningKey()) + .subject((userPrincipal.getUsername())) + .issuedAt(new Date()) + .expiration(new Date((new Date()).getTime() + jwtExpirationMs)) + .signWith(key) .compact(); } @@ -48,10 +52,10 @@ public class JwtUtils { public String getUserNameFromJwtToken(String token) { return Jwts.parser() - .setSigningKey(getSigningKey()) - .build() - .parseSignedClaims(token) - .getPayload() + .verifyWith(key) + .build() + .parseSignedClaims(token) + .getPayload() .getSubject(); } @@ -59,7 +63,7 @@ public class JwtUtils { public boolean validateJwtToken(String authToken) { try { Jwts.parser() - .setSigningKey(getSigningKey()) + . verifyWith(key) .build() .parseSignedClaims(authToken); return true; diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java index 1c367c4999..f5b3148c42 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java @@ -27,22 +27,6 @@ public class JwtResponse { this.type = tokenType; } - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - public String getUsername() { return username; } diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java index 5a83826065..30e8c552c9 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java @@ -33,7 +33,7 @@ public class SecurityConfiguration { @Autowired private AuthEntryPointJwt unauthorizedHandler; - private static final String[] WHITE_LIST_URL = { "/h2-console/**","/signin", "/signup", "/user-dashboard" }; + private static final String[] WHITE_LIST_URL = { "/h2-console/**", "/signin", "/signup", "/user-dashboard" }; @Bean public AuthTokenFilter authenticationJwtTokenFilter() { From 9e46a49f20722b2e25dd0002321e1c1acad882fc Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Tue, 12 Mar 2024 11:44:53 +0000 Subject: [PATCH 24/88] Creating a Spring Security Key for Signing a JWT Token --- .../baeldung/jwtsignkey/jwtconfig/JwtUtils.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java index 7ee397481b..5fbd4c6de3 100644 --- a/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java @@ -16,8 +16,6 @@ import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; -import java.nio.charset.StandardCharsets; -import java.security.Key; import java.util.Date; @Component @@ -30,8 +28,6 @@ public class JwtUtils { @Value("${baeldung.app.jwtExpirationMs}") private int jwtExpirationMs; - SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret)); - public String generateJwtToken(Authentication authentication) { UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); @@ -40,19 +36,19 @@ public class JwtUtils { .subject((userPrincipal.getUsername())) .issuedAt(new Date()) .expiration(new Date((new Date()).getTime() + jwtExpirationMs)) - .signWith(key) + .signWith(getSigningKey()) .compact(); } - private Key getSigningKey() { - byte[] keyBytes = this.jwtSecret.getBytes(StandardCharsets.UTF_8); + private SecretKey getSigningKey() { + byte[] keyBytes = Decoders.BASE64.decode(jwtSecret); return Keys.hmacShaKeyFor(keyBytes); } public String getUserNameFromJwtToken(String token) { return Jwts.parser() - .verifyWith(key) + .verifyWith(getSigningKey()) .build() .parseSignedClaims(token) .getPayload() @@ -63,7 +59,7 @@ public class JwtUtils { public boolean validateJwtToken(String authToken) { try { Jwts.parser() - . verifyWith(key) + .verifyWith(getSigningKey()) .build() .parseSignedClaims(authToken); return true; From 09cc4a18ca94b0d9f3c964f166390c2cea5dad24 Mon Sep 17 00:00:00 2001 From: ovidiu-mihai98 <138307181+ovidiumihaitacu@users.noreply.github.com> Date: Thu, 14 Mar 2024 21:22:33 +0200 Subject: [PATCH 25/88] Updated versions --- persistence-modules/liquibase/pom.xml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/persistence-modules/liquibase/pom.xml b/persistence-modules/liquibase/pom.xml index 9ed1791e81..5caf7047ac 100644 --- a/persistence-modules/liquibase/pom.xml +++ b/persistence-modules/liquibase/pom.xml @@ -17,7 +17,7 @@ org.springframework.boot spring-boot-starter-web - 3.2.3 + ${spring-boot.version} org.slf4j @@ -28,23 +28,23 @@ org.springframework.boot spring-boot-starter-data-jpa - 3.2.3 + ${spring-boot.version} org.liquibase liquibase-core - 4.24.0 + ${liquibase.version} org.postgresql postgresql - 42.6.1 + ${postgresql.version} runtime net.lbruun.springboot preliquibase-spring-boot-starter - 1.5.0 + ${preliquibase.version} @@ -80,6 +80,10 @@ 17 17 17 + 3.2.3 + 4.26.0 + 42.7.2 + 1.5.0 \ No newline at end of file From 83cc0185150672e73ffaf3410f1e6e26fe264006 Mon Sep 17 00:00:00 2001 From: adalagandev Date: Fri, 15 Mar 2024 18:08:35 +0100 Subject: [PATCH 26/88] BAEL-7131 - Removed InputStreamUnitTest as per Final review sugestions. --- .../inputstream/InputStreamUnitTest.java | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java diff --git a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java deleted file mode 100644 index e45e406f75..0000000000 --- a/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstream/InputStreamUnitTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.inputstream; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -public class InputStreamUnitTest { - @Test - public void givenAStringWrittenToFile_whenReadWithFileInputStream_thenItShouldExitsInTheInputStream(@TempDir Path tempDir) throws IOException { - Path sampleOut = tempDir.resolve("sample-out.txt"); - List lines = Arrays.asList("Hello. This is just a test. Good bye."); - Files.write(sampleOut, lines); - File sampleOutFile = sampleOut.toFile(); - try (InputStream inputStream = new FileInputStream(sampleOutFile)) { - assertThat(readString(inputStream)).contains(lines.get(0)); - } - } - - @Test - public void givenAByteArray_whenReadWithByteArrayInputStream_thenTheStringValueOfTheByteArrayShouldMatchTheExpectedString() throws IOException { - byte[] byteArray = { 104, 101, 108, 108, 111 }; - try (ByteArrayInputStream bais = new ByteArrayInputStream(byteArray)) { - assertThat(readString(bais)).isEqualTo("hello"); - } - } - - private static String readString(InputStream inputStream) throws IOException { - int c; - StringBuilder sb = new StringBuilder(); - while ((c = inputStream.read()) != -1) { - sb.append((char) c); - } - return sb.toString(); - } - -} From e959114bc709ed59f445a0c569ca277168bec91b Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Sun, 17 Mar 2024 17:27:57 +0100 Subject: [PATCH 27/88] [add-to-immutable-list] wip --- .../AddElementsToImmutableListUnitTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java diff --git a/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java new file mode 100644 index 0000000000..f7ad690acb --- /dev/null +++ b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.addtoimmutablelist; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class AddElementsToImmutableListUnitTest { + + public static List appendAnElement(List immutableList, T element) { + List tmpList = new ArrayList<>(immutableList); + tmpList.add(element); + return List.copyOf(tmpList); + } + + public static List appendElements(List immutableList, T... elements) { + List tmpList = new ArrayList<>(immutableList); + tmpList.addAll(Arrays.asList(elements)); + return List.copyOf(tmpList); + } + + @Test + void whenCallingAppendAnElement_thenGetExpectedResult() { + List myList = List.of("A", "B", "C", "D", "E"); + List expected = List.of("A", "B", "C", "D", "E", "F"); + List result = appendAnElement(myList, "F"); + assertThat(result).isEqualTo(expected) + .isUnmodifiable(); + } + + @Test + void whenCallingAppendElements_thenGetExpectedResult() { + List myList = List.of("A", "B", "C", "D", "E"); + List expected1 = List.of("A", "B", "C", "D", "E", "F"); + List result1 = appendElements(myList, "F"); + assertThat(result1).isEqualTo(expected1) + .isUnmodifiable(); + + List expected2 = List.of("A", "B", "C", "D", "E", "F", "G", "H", "I"); + List result2 = appendElements(myList, "F", "G", "H", "I"); + assertThat(result2).isEqualTo(expected2) + .isUnmodifiable(); + } +} \ No newline at end of file From 5d5cb10315824c9305a78caef6588bdd75497b52 Mon Sep 17 00:00:00 2001 From: RizaFarheen Date: Mon, 18 Mar 2024 14:07:47 +0400 Subject: [PATCH 28/88] saga-pattern --- microservices-modules/saga-pattern/README.md | 200 ++++++++++++++++ .../saga-pattern/build.gradle | 34 +++ .../saga-pattern/settings.gradle | 2 + .../orkes/example/saga/SagaApplication.java | 28 +++ .../controller/OrderServiceController.java | 27 +++ .../io/orkes/example/saga/dao/BaseDAO.java | 221 ++++++++++++++++++ .../orkes/example/saga/dao/InventoryDAO.java | 33 +++ .../io/orkes/example/saga/dao/OrdersDAO.java | 135 +++++++++++ .../orkes/example/saga/dao/PaymentsDAO.java | 65 ++++++ .../orkes/example/saga/dao/ShipmentDAO.java | 75 ++++++ .../example/saga/pojos/CancelRequest.java | 8 + .../saga/pojos/CheckInventoryRequest.java | 11 + .../io/orkes/example/saga/pojos/Customer.java | 11 + .../io/orkes/example/saga/pojos/Driver.java | 10 + .../saga/pojos/DriverNotificationRequest.java | 11 + .../saga/pojos/FoodDeliveryRequest.java | 19 ++ .../io/orkes/example/saga/pojos/FoodItem.java | 11 + .../io/orkes/example/saga/pojos/Order.java | 24 ++ .../example/saga/pojos/OrderDetails.java | 11 + .../example/saga/pojos/OrderRequest.java | 18 ++ .../io/orkes/example/saga/pojos/Payment.java | 20 ++ .../example/saga/pojos/PaymentDetails.java | 12 + .../example/saga/pojos/PaymentMethod.java | 11 + .../example/saga/pojos/PaymentRequest.java | 11 + .../orkes/example/saga/pojos/Restaurant.java | 11 + .../io/orkes/example/saga/pojos/Shipment.java | 20 ++ .../example/saga/pojos/ShippingRequest.java | 10 + .../saga/service/InventoryService.java | 23 ++ .../example/saga/service/OrderService.java | 72 ++++++ .../example/saga/service/PaymentService.java | 85 +++++++ .../example/saga/service/ShipmentService.java | 64 +++++ .../example/saga/service/WorkflowService.java | 61 +++++ .../saga/workers/ConductorWorkers.java | 130 +++++++++++ .../src/main/resources/application.properties | 32 +++ .../example/saga/SagaApplicationTests.java | 13 ++ 35 files changed, 1529 insertions(+) create mode 100644 microservices-modules/saga-pattern/README.md create mode 100644 microservices-modules/saga-pattern/build.gradle create mode 100644 microservices-modules/saga-pattern/settings.gradle create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java create mode 100644 microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java create mode 100644 microservices-modules/saga-pattern/src/main/resources/application.properties create mode 100644 microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java diff --git a/microservices-modules/saga-pattern/README.md b/microservices-modules/saga-pattern/README.md new file mode 100644 index 0000000000..0376987f07 --- /dev/null +++ b/microservices-modules/saga-pattern/README.md @@ -0,0 +1,200 @@ +# Food Delivery Service implemented using Conductor +Sample Java Application demonstrating Saga microservice architecture pattern for a food delivery app. + +## Running this Example + +### Environment setup +1. Install JAVA 17 - https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html +2. Install Gradle - https://gradle.org/install/ +3. Generate Gradle Wrapper - https://www.baeldung.com/gradle-wrapper +4. Install sqlite (Only if necessary, i.e if SQLite JDBC Driver is not installed. If you are on Mac OS X or Linux, then SQLite is normally pre-installed) - https://www.tutorialspoint.com/sqlite/sqlite_installation.htm. + +### Workflow Setup on Orkes Playground + +#### Use existing out-of-the-box workflows +We have already setup these workflows with all the necessary permissions. These can be used directly, if you don't need to modify these workflows. +1. Food Delivery Workflow - https://play.orkes.io/workflowDef/FoodDeliveryWorkflow +2. Cancellation workflow - https://play.orkes.io/workflowDef/FoodDeliveryFailureWorkflow + +### Running the application and workers locally + +1. Clone the project to your local +2. Update following properties in [application.properties](src/main/resources/application.properties) + 1. `conductor.security.client.key-id` and `conductor.security.client.secret` are **NOT** set, please set them + * When connecting to playground - refer to this [article](https://orkes.io/content/how-to-videos/access-key-and-secret) to get a key and secret + * When connecting locally - follow the instructions [here (Install and Run Locally)](https://orkes.io/content/get-orkes-conductor) + 2. `conductor.worker.all.domain` is set to 'saga' by default, please change it to or something else to avoid conflicts with workflows and workers spun up by others +3. From the root project folder, run `gradlew bootRun` + +### Order Creation + +We can use two approaches: +1. Call the triggerRideBookingFlow API from within the Application + ``` + curl --location 'http://localhost:8081/triggerFoodDeliveryFlow' \ + --header 'Content-Type: application/json' \ + --data '{ + "customerEmail": "tester.qa@example.com", + "customerName": "Tester QA", + "customerContact": "+1(605)123-5674", + "address": "350 East 62nd Street, NY 10065", + "restaurantId": 2, + "foodItems": [ + { + "item": "Chicken with Broccoli", + "quantity": 1 + }, + { + "item": "Veggie Fried Rice", + "quantity": 1 + }, + { + "item": "Egg Drop Soup", + "quantity": 2 + } + ], + "additionalNotes": [ + "Do not put spice.", + "Send cutlery." + ], + "paymentMethod" : { + "type": "Credit Card", + "details": { + "number": "1234 4567 3325 1345", + "cvv": "123", + "expiry": "05/2022" + } + }, + "paymentAmount": 45.34, + "deliveryInstructions": "Leave at the door!" + }' + ``` +2. Directly call the Orkes API for creating a workflow + 1. Generate a JWT token by following steps mentioned [here](https://orkes.io/content/access-control-and-security/applications#generating-token) + 2. Make an HTTPS request from postman/curl similar to below after replacing \: +``` +curl --location 'https://play.orkes.io/api/workflow' \ +--header "Content-Type: application/json" \ +--header 'X-Authorization: ' \ +--request POST \ +--data \ +' +{ + "name": "FoodDeliveryWorkflow", + "version": 1, + "input": { + "customerEmail": "tester.qa@example.com", + "customerName": "Tester QA", + "customerContact": "+1(605)123-5674", + "address": "350 East 62nd Street, NY 10065", + "restaurantId": 2, + "foodItems": [ + { + "item": "Chicken with Broccoli", + "quantity": 1 + }, + { + "item": "Veggie Fried Rice", + "quantity": 1 + }, + { + "item": "Egg Drop Soup", + "quantity": 2 + }], + "additionalNotes": [ + "Do not put spice.", + "Send cutlery." + ], + "deliveryInstructions": "Leave at the door!", + "paymentAmount": 45.34, + "paymentMethod": { + "type" : "Credit Card", + "details" : { + "number": "1234 4567 3325 1345", + "expiry": "05/2025", + "cvv": "123" + } + } + } + "taskToDomain": { + "*": "saga" + } +} +' +``` + +A successful order creation workflow run will look like this: + +![Screenshot 2024-02-26 at 11 38 14 AM](https://github.com/conductor-sdk/conductor-examples-food-delivery/assets/127052609/377549ec-58b0-425c-922b-6318a20b68c8) + + +#### Triggering the cancellation workflow to simulate rollback of distributed transactions + +* Create an order with invalid payment expiry +``` +curl --location 'https://play.orkes.io/api/workflow' \ +--header "Content-Type: application/json" \ +--header 'X-Authorization: ' \ +--request POST \ +--data \ +' +{ + "name": "FoodDeliveryWorkflow", + "version": 1, + "input": { + "customerEmail": "tester.qa@example.com", + "customerName": "Tester QA", + "customerContact": "+1(605)123-5674", + "address": "350 East 62nd Street, NY 10065", + "restaurantId": 2, + "foodItems": [ + { + "item": "Chicken with Broccoli", + "quantity": 1 + }, + { + "item": "Veggie Fried Rice", + "quantity": 1 + }, + { + "item": "Egg Drop Soup", + "quantity": 2 + }], + "additionalNotes": [ + "Do not put spice.", + "Send cutlery." + ], + "deliveryInstructions": "Leave at the door!", + "paymentAmount": 45.34, + "paymentMethod": { + "type" : "Credit Card", + "details" : { + "number": "1234 4567 3325 1345", + "expiry": "05/2022", + "cvv": "123" + } + } + } + "taskToDomain": { + "*": "saga" + } +} +' +``` + +* This will cause the workflow to fail and trigger the cancellation workflow. +* Failed workflow run will look like this: + +![Screenshot 2024-02-26 at 1 14 02 PM](https://github.com/conductor-sdk/conductor-examples-food-delivery/assets/127052609/6078320f-f4d6-406e-98b9-7df110c70cb3) + + + +* A cancellation workflow run will look like this: + +![Screenshot 2024-02-26 at 1 15 07 PM](https://github.com/conductor-sdk/conductor-examples-food-delivery/assets/127052609/68c15035-82c1-4415-b502-93217ce40c80) + + +* In the above workflow diagram, the simulated distributed rollback can be seen. The rollback sequence in case of failure occurring while payment processing is as follows: + 1. Shipment is cancelled in the Shipment Service + 2. Payment is cancelled in the Payment Service + 3. Order is cancelled in the Order Service diff --git a/microservices-modules/saga-pattern/build.gradle b/microservices-modules/saga-pattern/build.gradle new file mode 100644 index 0000000000..adf0a913db --- /dev/null +++ b/microservices-modules/saga-pattern/build.gradle @@ -0,0 +1,34 @@ +buildscript { + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:3.2.3" + } +} + +plugins { + id 'java' + id 'org.springframework.boot' version '3.2.3' + id 'io.freefair.lombok' version '8.6' +} + +apply plugin: 'io.spring.dependency-management' + +group = 'io.orkes.example' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' + + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'io.orkes.conductor:orkes-conductor-client:2.1.0' + + implementation 'org.xerial:sqlite-jdbc:3.32.3.3' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/microservices-modules/saga-pattern/settings.gradle b/microservices-modules/saga-pattern/settings.gradle new file mode 100644 index 0000000000..8a06313387 --- /dev/null +++ b/microservices-modules/saga-pattern/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'conductor-examples-food-delivery' + diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java new file mode 100644 index 0000000000..17262cdf0a --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/SagaApplication.java @@ -0,0 +1,28 @@ +package io.orkes.example.saga; + +import io.orkes.example.saga.dao.BaseDAO; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import lombok.AllArgsConstructor; + + +@AllArgsConstructor +@SpringBootApplication +@ComponentScan(basePackages = {"io.orkes"}) +public class SagaApplication { + + private static final BaseDAO db = new BaseDAO("jdbc:sqlite:food_delivery.db"); + + public static void main(String[] args) { + SpringApplication.run(SagaApplication.class, args); + initDB(); + } + + public static void initDB() { + db.createTables("orders"); + db.createTables("inventory"); + db.createTables("payments"); + db.createTables("shipments"); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java new file mode 100644 index 0000000000..febc05e74b --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/controller/OrderServiceController.java @@ -0,0 +1,27 @@ +package io.orkes.example.saga.controller; + +import io.orkes.example.saga.pojos.FoodDeliveryRequest; +import io.orkes.example.saga.pojos.OrderRequest; +import io.orkes.example.saga.service.WorkflowService; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@Slf4j +@AllArgsConstructor +@RestController +public class OrderServiceController { + + private final WorkflowService workflowService; + + @PostMapping(value = "/triggerFoodDeliveryFlow", produces = "application/json") + public ResponseEntity> triggerFoodDeliveryFlow(@RequestBody FoodDeliveryRequest foodDeliveryRequest) { + return ResponseEntity.ok(workflowService.startFoodDeliveryWorkflow(foodDeliveryRequest)); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java new file mode 100644 index 0000000000..9f077929dc --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/BaseDAO.java @@ -0,0 +1,221 @@ +package io.orkes.example.saga.dao; + +import java.sql.*; + +public class BaseDAO { + + private String url; + + public BaseDAO(String url) { + this.url = url; + } + + protected Connection connect() { + Connection conn = null; + try { + conn = DriverManager.getConnection(this.url); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return conn; + } + + protected Boolean execute(String sql) { + try (Connection conn = DriverManager.getConnection(this.url); Statement stmt = conn.createStatement()) { + stmt.execute(sql); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return false; + } + return true; + } + + public void createTables(String service) { + switch (service) { + case "orders": + createOrdersTable(); + createOrderDetailsTable(); + createCustomerTable(); + break; + case "inventory": + createRestaurantsTable(); + break; + case "shipments": + createDriversTable(); + createShipmentTable(); + break; + case "payments": + createPaymentsTable(); + break; + default: + System.out.println("Service name not recognized"); + } + } + + private void createOrdersTable() { + if (!tableExists("orders")) { + + String sql = "CREATE TABLE orders (\n" + + " orderId text PRIMARY KEY,\n" + + " customerId integer NOT NULL,\n" + + " restaurantId integer NOT NULL,\n" + + " deliveryAddress text NOT NULL,\n" + + " createdAt TIMESTAMP NOT NULL,\n" + + " status text NOT NULL\n" + + ");"; + + execute(sql); + } + } + + private void createOrderDetailsTable() { + if (!tableExists("orders_details")) { + String sql = "CREATE TABLE orders_details (\n" + + " orderId text PRIMARY KEY,\n" + + " items text NOT NULL,\n" + + " notes text\n" + + ");"; + + execute(sql); + } + } + + private void createCustomerTable() { + if (tableExists("customers")) { + return; + } + + String sql = "CREATE TABLE customers (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " email text NOT NULL,\n" + + " name text NOT NULL,\n" + + " contact text\n" + + ");"; + + if(execute(sql)) { + seedCustomers(); + } + } + + private void createRestaurantsTable() { + if (!tableExists("restaurants")) { + String sql = "CREATE TABLE restaurants (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " name text NOT NULL,\n" + + " address text NOT NULL,\n" + + " contact text NOT NULL\n" + + ");"; + + if (execute(sql)) { + seedRestaurants(); + } + } + } + + + private void createPaymentsTable() { + if (tableExists("payments")) { + return; + } + + String sql = "CREATE TABLE payments (\n" + + " paymentId text PRIMARY KEY,\n" + + " orderId text NOT NULL,\n" + + " amount number NOT NULL,\n" + + " method text,\n" + + " status text,\n" + + " createdAt TIMESTAMP NOT NULL\n" + + ");"; + + execute(sql); + } + + private void createDriversTable() { + if (tableExists("drivers")) { + return; + } + + String sql = "CREATE TABLE drivers (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " name text NOT NULL,\n" + + " contact text\n" + + ");"; + + if(execute(sql)) { + seedDrivers(); + } + } + private void createShipmentTable() { + if (tableExists("shipments")) { + return; + } + + String sql = "CREATE TABLE shipments (\n" + + " id integer PRIMARY KEY AUTOINCREMENT,\n" + + " orderId text NOT NULL,\n" + + " driverId number NOT NULL,\n" + + " address text NOT NULL,\n" + + " instructions text,\n" + + " status text NOT NULL,\n" + + " createdAt TIMESTAMP NOT NULL\n" + + ");"; + + execute(sql); + } + + private void seedCustomers() { + String[] queries = { + "INSERT INTO customers(email, name, contact) VALUES('John Smith','john.smith@example.com','+12126781345');", + "INSERT INTO customers(email, name, contact) VALUES('Mike Ross','mike.ross@example.com','+15466711147');", + "INSERT INTO customers(email, name, contact) VALUES('Martha Williams','martha.williams@example.com','+12790581941');" + }; + + for (String query : queries) { + execute(query); + } + } + + private void seedRestaurants() { + String[] add = { + "5331 Redford Court, Montgomery AL 36116", + "43 West 4th Street, New York NY 10024", + "1693 Alice Court, Annapolis MD 21401" + }; + String[] queries = { + "INSERT INTO restaurants(name, address, contact) VALUES('Mikes','+12121231345','" + add[0] + "');", + "INSERT INTO restaurants(name, address, contact) VALUES('Tamarind','+12412311147','" + add[1] + "');", + "INSERT INTO restaurants(name, address, contact) VALUES('Thai Place','+14790981941','" + add[2] + "');", + }; + + for (String query : queries) { + execute(query); + } + } + + private void seedDrivers() { + String[] queries = { + "INSERT INTO drivers(name,contact) VALUES('Wayne Stevens','+12520711467');", + "INSERT INTO drivers(name,contact) VALUES('Jim Willis','+16466281981');", + "INSERT INTO drivers(name,contact) VALUES('Steven Carroll','+12612590430');", + "INSERT INTO drivers(name,contact) VALUES('Tom Cruise','+18659581430');" + }; + + for (String query : queries) { + execute(query); + } + } + + boolean tableExists(String tableName) { + try { + Connection conn = DriverManager.getConnection(this.url); + DatabaseMetaData meta = conn.getMetaData(); + ResultSet resultSet = meta.getTables(null, null, tableName, new String[] {"TABLE"}); + boolean exists = resultSet.next(); + conn.close(); + return exists; + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return false; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java new file mode 100644 index 0000000000..e347b90994 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/InventoryDAO.java @@ -0,0 +1,33 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Order; +import io.orkes.example.saga.pojos.Restaurant; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class InventoryDAO extends BaseDAO { + + public InventoryDAO(String url) { + super(url); + } + + public void readRestaurant(int restaurantId, Restaurant restaurant) { + String sql = "SELECT name, address, contact FROM restaurants WHERE id = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, restaurantId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + restaurant.setName(rs.getString("name")); + restaurant.setAddress(rs.getString("address")); + restaurant.setContact(rs.getString("contact")); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java new file mode 100644 index 0000000000..3a5187a86c --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/OrdersDAO.java @@ -0,0 +1,135 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Customer; +import io.orkes.example.saga.pojos.Order; + +import java.sql.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.TimeZone; +import java.util.Date; + +public class OrdersDAO extends BaseDAO { + + public OrdersDAO(String url) { + super(url); + } + + public String insertOrder(Order order) { + Date date = new Date(); + Timestamp nowAsTS = new Timestamp(date.getTime()); + + String itemsStr = String.join("", order.getOrderDetails().getItems().toString()); + + String notesStr = null; + + if(!order.getOrderDetails().getNotes().isEmpty()) { + notesStr = String.join("", order.getOrderDetails().getNotes().toString()); + } else { + notesStr = ""; + } + + String sql = "INSERT INTO orders(orderId,customerId,restaurantId,deliveryAddress,createdAt,status) VALUES(?,?,?,?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, order.getOrderId()); + pstmt.setInt(2, order.getCustomer().getId()); + pstmt.setInt(3, order.getRestaurantId()); + pstmt.setString(4, order.getDeliveryAddress()); + pstmt.setTimestamp(5, nowAsTS); + pstmt.setString(6, order.getStatus().name()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return e.getMessage(); + } + + sql = "INSERT INTO orders_details(orderId,items,notes) VALUES(?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, order.getOrderId()); + pstmt.setString(2, itemsStr); + pstmt.setString(3, notesStr); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return e.getMessage(); + } + + return ""; + } + + public void updateOrder(Order order) { + String sql = "UPDATE orders SET restaurantId=?,deliveryAddress=?,status=? WHERE orderId=?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, order.getRestaurantId()); + pstmt.setString(2, order.getDeliveryAddress()); + pstmt.setString(3, order.getStatus().name()); + pstmt.setString(4, order.getOrderId()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void readOrder(String orderId, Order order) { + String sql = "SELECT orderId, customerId, restaurantId, deliveryAddress, createdAt, status FROM orders WHERE orderId = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, orderId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + order.setOrderId(rs.getString("orderId")); + Customer customer = new Customer(); + customer.setId(rs.getInt("customerId")); + order.setCustomer(customer); + order.setRestaurantId(rs.getInt("restaurantId")); + order.setDeliveryAddress(rs.getString("deliveryAddress")); + order.setCreatedAt(rs.getLong("createdAt")); + order.setStatus(Order.Status.valueOf(rs.getString("status"))); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public int insertCustomer(Customer customer) { + int id = 0; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM customers WHERE email = ?")) { + pstmt.setString(1, customer.getEmail()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) { + id = rs.getInt("id"); + } + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + + if (id > 0) { + return id; + } + + String sql = "INSERT INTO customers(email,name,contact) VALUES(?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, customer.getEmail()); + pstmt.setString(2, customer.getName()); + pstmt.setString(3, customer.getContact()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM customers WHERE email = ?")) { + pstmt.setString(1, customer.getEmail()); + ResultSet rs = pstmt.executeQuery(); + id = rs.getInt("id"); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + return id; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java new file mode 100644 index 0000000000..a56d32dbf0 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/PaymentsDAO.java @@ -0,0 +1,65 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Payment; + +import java.sql.*; +import java.util.Date; + +public class PaymentsDAO extends BaseDAO { + + public PaymentsDAO(String url) { + super(url); + } + + public String insertPayment(Payment payment) { + Date date = new Date(); + Timestamp nowAsTS = new Timestamp(date.getTime()); + + String sql = "INSERT INTO payments(paymentId, orderId, amount, method, createdAt, status) VALUES(?,?,?,?,?,?);"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, payment.getPaymentId()); + pstmt.setString(2, payment.getOrderId()); + pstmt.setDouble(3, payment.getAmount()); + pstmt.setString(4, payment.getPaymentMethod().toString()); + pstmt.setTimestamp(5, nowAsTS); + pstmt.setString(6, payment.getStatus().name()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return e.getMessage(); + } + return ""; + } + + public void updatePaymentStatus(Payment payment) { + String sql = "UPDATE payments SET status=? WHERE paymentId=?;"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, payment.getStatus().name()); + pstmt.setString(2, payment.getPaymentId()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void readPayment(String orderId, Payment payment) { + String sql = "SELECT paymentId, orderId, amount, method, createdAt, status FROM payments WHERE orderId = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, orderId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + payment.setPaymentId(rs.getString("paymentId")); + payment.setOrderId(rs.getString("orderId")); + payment.setAmount(rs.getDouble("amount")); + payment.setCreatedAt(rs.getLong("createdAt")); + payment.setStatus(Payment.Status.valueOf(rs.getString("status"))); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java new file mode 100644 index 0000000000..f0597c553e --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/dao/ShipmentDAO.java @@ -0,0 +1,75 @@ +package io.orkes.example.saga.dao; + +import io.orkes.example.saga.pojos.Driver; +import io.orkes.example.saga.pojos.Shipment; + +import java.sql.*; +import java.util.Date; + +public class ShipmentDAO extends BaseDAO { + + public ShipmentDAO(String url) { + super(url); + } + + public boolean insertShipment(Shipment shipment) { + Date date = new Date(); + Timestamp nowAsTS = new Timestamp(date.getTime()); + + String sql = "INSERT INTO shipments(orderId,driverId,address,instructions,createdAt,status) VALUES(?,?,?,?,?,?)"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, shipment.getOrderId()); + pstmt.setInt(2, shipment.getDriverId()); + pstmt.setString(3, shipment.getDeliveryAddress()); + pstmt.setString(4, shipment.getDeliveryInstructions()); + pstmt.setTimestamp(5, nowAsTS); + pstmt.setString(6, Shipment.Status.SCHEDULED.name()); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + return false; + } + return true; + } + public void cancelShipment(String orderId) { + String sql = "UPDATE shipments SET status=? WHERE orderId=?;"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, Shipment.Status.CANCELED.name()); + pstmt.setString(2, orderId); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void confirmShipment(String orderId) { + String sql = "UPDATE shipments SET status=? WHERE orderId=?;"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setString(1, Shipment.Status.CONFIRMED.name()); + pstmt.setString(2, orderId); + pstmt.executeUpdate(); + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } + + public void readDriver(int driverId, Driver driver) { + String sql = "SELECT name, contact FROM drivers WHERE id = ?"; + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, driverId); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + driver.setId(driverId); + driver.setName(rs.getString("name")); + driver.setContact(rs.getString("contact")); + } + + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java new file mode 100644 index 0000000000..84094259cf --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CancelRequest.java @@ -0,0 +1,8 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class CancelRequest { + private String orderId; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java new file mode 100644 index 0000000000..35a776bfdd --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/CheckInventoryRequest.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + + +import lombok.Data; +import java.util.ArrayList; + +@Data +public class CheckInventoryRequest { + private int restaurantId; + private ArrayList items; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java new file mode 100644 index 0000000000..b0c6216016 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Customer.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Customer { + private int id; + private String email; + private String name; + private String contact; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java new file mode 100644 index 0000000000..ed8df6a4f9 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Driver.java @@ -0,0 +1,10 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Driver { + int id; + String name; + String contact; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java new file mode 100644 index 0000000000..31c39c0f9a --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/DriverNotificationRequest.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class DriverNotificationRequest { + int driverId; + String dropOff; + String pickUp; + String orderId; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java new file mode 100644 index 0000000000..28d031aba3 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodDeliveryRequest.java @@ -0,0 +1,19 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +import java.util.ArrayList; + +@Data +public class FoodDeliveryRequest { + private String customerEmail; + private String customerName; + private String customerContact; + private int restaurantId; + private ArrayList foodItems; + private ArrayList additionalNotes; + private String address; + private String deliveryInstructions; + private double paymentAmount; + private Object paymentMethod; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java new file mode 100644 index 0000000000..1a20c5f8ec --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/FoodItem.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class FoodItem { + private String item; + private int quantity; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java new file mode 100644 index 0000000000..7b68519196 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Order.java @@ -0,0 +1,24 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +import java.util.EnumMap; + +@Data +public class Order { + + public enum Status { + PENDING, + ASSIGNED, + CONFIRMED, + CANCELLED + } + + private String orderId; + private Customer customer; + private int restaurantId; + private String deliveryAddress; + private long createdAt; + private Status status; + private OrderDetails orderDetails; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java new file mode 100644 index 0000000000..9b55933d02 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderDetails.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import java.util.ArrayList; + +@Data +public class OrderDetails { + private String orderId; + private ArrayList items; + private ArrayList notes; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java new file mode 100644 index 0000000000..ab3c28b543 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/OrderRequest.java @@ -0,0 +1,18 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +import java.util.ArrayList; + +@Data +public class OrderRequest { + private String OrderRequestId; + private String customerEmail; + private String customerName; + private String customerContact; + private int restaurantId; + private ArrayList items; + private ArrayList notes; + private String deliveryAddress; + private String deliveryInstructions; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java new file mode 100644 index 0000000000..02a9d846ea --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Payment.java @@ -0,0 +1,20 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Payment { + public enum Status { + PENDING, + FAILED, + SUCCESSFUL, + CANCELED + } + private String paymentId; + private String orderId; + private double amount; + private PaymentMethod paymentMethod; + private Status status; + private long createdAt; + private String errorMsg; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java new file mode 100644 index 0000000000..a0679aaeed --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentDetails.java @@ -0,0 +1,12 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class PaymentDetails { + private String number; + private String expiry; + private int cvv; +} \ No newline at end of file diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java new file mode 100644 index 0000000000..ada06e5bec --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentMethod.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +public class PaymentMethod { + private String type; + private PaymentDetails details; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java new file mode 100644 index 0000000000..b0d2590c7b --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/PaymentRequest.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class PaymentRequest { + private String orderId; + private int customerId; + private float amount; + private PaymentMethod method; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java new file mode 100644 index 0000000000..aaa9cf8cb3 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Restaurant.java @@ -0,0 +1,11 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Restaurant { + int id; + String name; + String address; + String contact; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java new file mode 100644 index 0000000000..3a6a960e46 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/Shipment.java @@ -0,0 +1,20 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class Shipment { + public enum Status { + SCHEDULED, + CONFIRMED, + DELIVERED, + CANCELED + } + private int id; + private String orderId; + private int driverId; + private String deliveryAddress; + private String deliveryInstructions; + private long createdAt; + private String status; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java new file mode 100644 index 0000000000..296442f846 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/pojos/ShippingRequest.java @@ -0,0 +1,10 @@ +package io.orkes.example.saga.pojos; + +import lombok.Data; + +@Data +public class ShippingRequest { + private String orderId; + private String deliveryAddress; + private String deliveryInstructions; +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java new file mode 100644 index 0000000000..bd750ae47b --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/InventoryService.java @@ -0,0 +1,23 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.InventoryDAO; +import io.orkes.example.saga.pojos.FoodItem; +import io.orkes.example.saga.pojos.Restaurant; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Objects; + +@Slf4j +public class InventoryService { + + private static final InventoryDAO inventoryDAO = new InventoryDAO("jdbc:sqlite:food_delivery.db"); + + public static boolean checkAvailability(int restaurantId, ArrayList items) { + Restaurant restaurant = new Restaurant(); + restaurant.setId(restaurantId); + restaurant.setName(""); + inventoryDAO.readRestaurant(restaurantId, restaurant); + return !Objects.equals(restaurant.getName(), ""); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java new file mode 100644 index 0000000000..d42d999641 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/OrderService.java @@ -0,0 +1,72 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.OrdersDAO; +import io.orkes.example.saga.pojos.Customer; +import io.orkes.example.saga.pojos.Order; +import io.orkes.example.saga.pojos.OrderDetails; +import io.orkes.example.saga.pojos.OrderRequest; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Slf4j +@AllArgsConstructor +@Service +public class OrderService { + + private static final OrdersDAO ORDERS_DAO = new OrdersDAO("jdbc:sqlite:food_delivery.db"); + + public static String createOrder(OrderRequest orderRequest) { + UUID uuid = UUID.randomUUID(); + String uuidAsString = uuid.toString(); + + Order order = new Order(); + order.setOrderId(uuidAsString); + + Customer customer = new Customer(); + customer.setEmail(orderRequest.getCustomerEmail()); + customer.setName(orderRequest.getCustomerName()); + customer.setContact(orderRequest.getCustomerContact()); + customer.setId(ORDERS_DAO.insertCustomer(customer)); + + log.info("Upsert customer record in DB with id: {}", customer.getId()); + + order.setCustomer(customer); + order.setRestaurantId(orderRequest.getRestaurantId()); + order.setDeliveryAddress(orderRequest.getDeliveryAddress()); + order.setStatus(Order.Status.PENDING); + + OrderDetails orderDetails = new OrderDetails(); + orderDetails.setOrderId(uuidAsString); + orderDetails.setItems(orderRequest.getItems()); + orderDetails.setNotes(orderRequest.getNotes()); + + order.setOrderDetails(orderDetails); + + String error = ORDERS_DAO.insertOrder(order); + + if (error.isEmpty()) { + log.info("Created order with id: {}", order.getOrderId()); + } + else { + log.error("Order creation failure: {}", error); + return null; + } + + return uuidAsString; + } + + public static Order getOrder(String orderId) { + Order order = new Order(); + ORDERS_DAO.readOrder(orderId, order); + return order; + } + + public static void cancelOrder(Order order) { + order.setStatus(Order.Status.CANCELLED); + log.info("Cancelling order {}", order.getOrderId()); + ORDERS_DAO.updateOrder(order); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java new file mode 100644 index 0000000000..0693586e6f --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/PaymentService.java @@ -0,0 +1,85 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.PaymentsDAO; +import io.orkes.example.saga.pojos.Payment; +import io.orkes.example.saga.pojos.PaymentDetails; +import io.orkes.example.saga.pojos.PaymentMethod; +import io.orkes.example.saga.pojos.PaymentRequest; +import lombok.extern.slf4j.Slf4j; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; +import java.util.UUID; + +@Slf4j +public class PaymentService { + + private static final PaymentsDAO paymentsDAO = new PaymentsDAO("jdbc:sqlite:food_delivery.db"); + + public static Payment createPayment(PaymentRequest paymentRequest) { + UUID uuid = UUID.randomUUID(); + String uuidAsString = uuid.toString(); + + Payment payment = new Payment(); + payment.setPaymentId(uuidAsString); + payment.setOrderId(paymentRequest.getOrderId()); + payment.setAmount(paymentRequest.getAmount()); + payment.setPaymentMethod(paymentRequest.getMethod()); + payment.setStatus(Payment.Status.PENDING); + + // Check if returned error is non-empty, i.e failure + if (!paymentsDAO.insertPayment(payment).isEmpty()) { + log.error("Failed to process payment for order {}", paymentRequest.getOrderId()); + payment.setErrorMsg("Payment creation failure"); + payment.setStatus(Payment.Status.FAILED); + } + else { + if(makePayment(payment)) { + payment.setStatus(Payment.Status.SUCCESSFUL); + } else { + payment.setStatus(Payment.Status.FAILED); + } + } + + // Record final status + paymentsDAO.updatePaymentStatus(payment); + return payment; + } + + public static void cancelPayment(String orderId) { + // Cancel Payment in DB + Payment payment = new Payment(); + paymentsDAO.readPayment(orderId, payment); + payment.setStatus(Payment.Status.CANCELED); + paymentsDAO.updatePaymentStatus(payment); + } + + private static boolean makePayment(Payment payment) { + if (Objects.equals(payment.getPaymentMethod().getType(), "Credit Card")) { + PaymentDetails details = payment.getPaymentMethod().getDetails(); + + DateFormat dateFormat= new SimpleDateFormat("MM/yyyy"); + Date expiry = new Date(); + + try { + expiry = dateFormat.parse(details.getExpiry()); + } catch (ParseException e) { + payment.setErrorMsg("Invalid expiry date:" + details.getExpiry()); + return false; + } + + Date today = new Date(); + if (today.getTime() > expiry.getTime()) { + payment.setErrorMsg("Expired payment method:" + details.getExpiry()); + return false; + } + + } + // Ideally an async call would be made with a callback + // But, we're skipping that and assuming payment went through + return true; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java new file mode 100644 index 0000000000..059b1cb36f --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/ShipmentService.java @@ -0,0 +1,64 @@ +package io.orkes.example.saga.service; + +import io.orkes.example.saga.dao.ShipmentDAO; +import io.orkes.example.saga.pojos.Driver; +import io.orkes.example.saga.pojos.Shipment; +import io.orkes.example.saga.pojos.ShippingRequest; +import lombok.extern.slf4j.Slf4j; + +import java.util.Random; + +@Slf4j +public class ShipmentService { + + private static final ShipmentDAO shipmentDAO = new ShipmentDAO("jdbc:sqlite:food_delivery.db"); + + public static int createShipment(ShippingRequest shippingRequest) { + String orderId = shippingRequest.getOrderId(); + + Shipment shipment = new Shipment(); + shipment.setOrderId(orderId); + shipment.setDeliveryAddress(shippingRequest.getDeliveryAddress()); + shipment.setDeliveryInstructions(shippingRequest.getDeliveryInstructions()); + + int driverId = findDriver(); + shipment.setDriverId(driverId); + + if (!shipmentDAO.insertShipment(shipment)) { + log.error("Shipment creation for order {} failed.", orderId); + return 0; + } + + Driver driver = new Driver(); + driver.setName(""); + shipmentDAO.readDriver(driverId, driver); + + if (driver.getName().isBlank()) { + log.error("Shipment creation for order {} failed as driver in the area is not available.", orderId); + shipmentDAO.cancelShipment(orderId); + return 0; + } + else { + log.info("Assigned driver {} to order with id: {}", driverId, orderId); + shipmentDAO.confirmShipment(orderId); + } + + return driverId; + } + + public static void cancelDelivery(String orderId) { + shipmentDAO.cancelShipment(orderId); + } + + private static int findDriver() { + Random random = new Random(); + int driverId = 0; + int counter = 0; + while (counter < 10) { + driverId = random.nextInt(4); + if(driverId !=0) break; + counter += 1; + } + return driverId; + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java new file mode 100644 index 0000000000..d3914aecc8 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/service/WorkflowService.java @@ -0,0 +1,61 @@ +package io.orkes.example.saga.service; + +import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; +import io.orkes.conductor.client.WorkflowClient; +import io.orkes.example.saga.pojos.FoodDeliveryRequest; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@AllArgsConstructor +@Service +public class WorkflowService { + + private final WorkflowClient workflowClient; + private final Environment environment; + + public Map startFoodDeliveryWorkflow(FoodDeliveryRequest foodDeliveryRequest) { + StartWorkflowRequest request = new StartWorkflowRequest(); + request.setName("FoodDeliveryWorkflow"); + request.setVersion(1); + request.setCorrelationId("api-triggered"); + + String TASK_DOMAIN_PROPERTY = "conductor.worker.all.domain"; + String domain = environment.getProperty(TASK_DOMAIN_PROPERTY, String.class, ""); + + if (!domain.isEmpty()) { + Map taskToDomain = new HashMap<>(); + taskToDomain.put("*", domain); + request.setTaskToDomain(taskToDomain); + } + + Map inputData = new HashMap<>(); + inputData.put("customerEmail", foodDeliveryRequest.getCustomerEmail()); + inputData.put("customerName", foodDeliveryRequest.getCustomerName()); + inputData.put("customerContact", foodDeliveryRequest.getCustomerContact()); + inputData.put("restaurantId", foodDeliveryRequest.getRestaurantId()); + inputData.put("foodItems", foodDeliveryRequest.getFoodItems()); + inputData.put("additionalNotes", foodDeliveryRequest.getAdditionalNotes()); + inputData.put("address", foodDeliveryRequest.getAddress()); + inputData.put("deliveryInstructions", foodDeliveryRequest.getDeliveryInstructions()); + inputData.put("paymentAmount", foodDeliveryRequest.getPaymentAmount()); + inputData.put("paymentMethod", foodDeliveryRequest.getPaymentMethod()); + request.setInput(inputData); + + String workflowId = ""; + try { + workflowId = workflowClient.startWorkflow(request); + log.info("Workflow id: {}", workflowId); + } catch (Exception ex) { + ex.printStackTrace(System.out); + return Map.of("error", "Order creation failure", "detail", ex.toString()); + } + + return Map.of("workflowId", workflowId); + } +} diff --git a/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java new file mode 100644 index 0000000000..aeb51ddd11 --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/java/io/orkes/example/saga/workers/ConductorWorkers.java @@ -0,0 +1,130 @@ +package io.orkes.example.saga.workers; + +import com.netflix.conductor.common.metadata.tasks.TaskResult; +import com.netflix.conductor.sdk.workflow.task.WorkerTask; +import io.orkes.example.saga.pojos.*; +import io.orkes.example.saga.service.InventoryService; +import io.orkes.example.saga.service.OrderService; +import io.orkes.example.saga.service.PaymentService; +import io.orkes.example.saga.service.ShipmentService; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +@AllArgsConstructor +@Component +@ComponentScan(basePackages = {"io.orkes"}) +public class ConductorWorkers { + /** + * Note: Using this setting, up to 5 tasks will run in parallel, with tasks being polled every 200ms + */ + @WorkerTask(value = "order_food", threadCount = 3, pollingInterval = 300) + public TaskResult orderFoodTask(OrderRequest orderRequest) { + String orderId = OrderService.createOrder(orderRequest); + + TaskResult result = new TaskResult(); + Map output = new HashMap<>(); + + if(orderId != null) { + output.put("orderId", orderId); + result.setOutputData(output); + result.setStatus(TaskResult.Status.COMPLETED); + } else { + output.put("orderId", null); + result.setStatus(TaskResult.Status.FAILED); + } + return result; + } + + @WorkerTask(value = "check_inventory", threadCount = 2, pollingInterval = 300) + public TaskResult checkInventoryTask(CheckInventoryRequest checkInventoryRequest) { + int restaurantId = checkInventoryRequest.getRestaurantId(); + ArrayList items = checkInventoryRequest.getItems(); + boolean availability = InventoryService.checkAvailability(restaurantId, items); + + TaskResult result = new TaskResult(); + + if (availability) { + result.setStatus(TaskResult.Status.COMPLETED); + } else { + result.setReasonForIncompletion("Restaurant is closed"); + result.setStatus(TaskResult.Status.FAILED_WITH_TERMINAL_ERROR); + } + + return result; + } + + @WorkerTask(value = "make_payment", threadCount = 2, pollingInterval = 300) + public TaskResult makePaymentTask(PaymentRequest paymentRequest) { + TaskResult result = new TaskResult(); + + Payment payment = PaymentService.createPayment(paymentRequest); + Map output = new HashMap<>(); + output.put("orderId", payment.getOrderId()); + output.put("paymentId", payment.getPaymentId()); + output.put("paymentStatus", payment.getStatus().name()); + + if(payment.getStatus() == Payment.Status.SUCCESSFUL) { + result.setStatus(TaskResult.Status.COMPLETED); + } else { + output.put("error", payment.getErrorMsg()); + result.setStatus(TaskResult.Status.FAILED_WITH_TERMINAL_ERROR); + } + + result.setOutputData(output); + + return result; + } + + @WorkerTask(value = "ship_food", threadCount = 2, pollingInterval = 300) + public TaskResult shipFoodTask(ShippingRequest shippingRequest) { + TaskResult result = new TaskResult(); + Map output = new HashMap<>(); + int driverId = ShipmentService.createShipment(shippingRequest); + if (driverId != 0) { + result.setStatus(TaskResult.Status.COMPLETED); + } else { + result.setStatus(TaskResult.Status.FAILED); + } + return result; + } + + @WorkerTask(value = "notify_driver", threadCount = 2, pollingInterval = 300) + public Map checkForDriverNotifications(DriverNotificationRequest driverNotificationRequest) { + Map result = new HashMap<>(); + return result; + } + + @WorkerTask(value = "notify_customer", threadCount = 2, pollingInterval = 300) + public Map checkForCustomerNotifications(Order order) { + Map result = new HashMap<>(); + return result; + } +// + @WorkerTask(value = "cancel_payment", threadCount = 2, pollingInterval = 300) + public Map cancelPaymentTask(CancelRequest cancelRequest) { + Map result = new HashMap<>(); + PaymentService.cancelPayment(cancelRequest.getOrderId()); + return result; + } + + @WorkerTask(value = "cancel_delivery", threadCount = 2, pollingInterval = 300) + public Map cancelDeliveryTask(CancelRequest cancelRequest) { + Map result = new HashMap<>(); + ShipmentService.cancelDelivery(cancelRequest.getOrderId()); + return result; + } + + @WorkerTask(value = "cancel_order", threadCount = 2, pollingInterval = 300) + public Map cancelOrderTask(CancelRequest cancelRequest) { + Map result = new HashMap<>(); + Order order = OrderService.getOrder(cancelRequest.getOrderId()); + OrderService.cancelOrder(order); + return result; + } + +} diff --git a/microservices-modules/saga-pattern/src/main/resources/application.properties b/microservices-modules/saga-pattern/src/main/resources/application.properties new file mode 100644 index 0000000000..8df5f3e82e --- /dev/null +++ b/microservices-modules/saga-pattern/src/main/resources/application.properties @@ -0,0 +1,32 @@ + +spring.mvc.pathmatch.matching-strategy=ant_path_matcher + +springdoc.swagger-ui.path=/swagger-ui.html + +management.endpoints.enabled-by-default=false +management.endpoint.info.enabled=false + +# Local app server port +server.port=8081 + +# Playground + +# Obtain key and secret by logging into https://play.orkes.io/ +# and navigating to applications menu, create an application and generate key/secret +conductor.server.url=https://play.orkes.io/api +conductor.security.client.key-id= +conductor.security.client.secret= + + +# Task Domain +conductor.worker.all.domain=saga +conductor.worker.all.pollingInterval=22 + + +# DB Setup +spring.jpa.database-platform=com.springboot.sqlite.SQLDialect +spring.jpa.hibernate.ddl-auto=update +spring.datasource.url=jdbc:sqlite:food_delivery.db +spring.datasource.driver-class-name = org.sqlite.JDBC +spring.datasource.username=admin +spring.datasource.password=admin diff --git a/microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java b/microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java new file mode 100644 index 0000000000..dfdebf099f --- /dev/null +++ b/microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java @@ -0,0 +1,13 @@ +package io.orkes.example.saga; + +//import org.junit.jupiter.api.Test; +//import org.springframework.boot.test.context.SpringBootTest; +// +//@SpringBootTest +//class SagaApplicationTests { +// +// @Test +// void contextLoads() { +// } +// +//} From af3e6ea20e2946a6261ca2f3d53463eba27e49a3 Mon Sep 17 00:00:00 2001 From: RizaFarheen Date: Mon, 18 Mar 2024 14:09:49 +0400 Subject: [PATCH 29/88] Update README.md --- microservices-modules/saga-pattern/README.md | 205 +------------------ 1 file changed, 9 insertions(+), 196 deletions(-) diff --git a/microservices-modules/saga-pattern/README.md b/microservices-modules/saga-pattern/README.md index 0376987f07..853cce4c5e 100644 --- a/microservices-modules/saga-pattern/README.md +++ b/microservices-modules/saga-pattern/README.md @@ -1,200 +1,13 @@ -# Food Delivery Service implemented using Conductor -Sample Java Application demonstrating Saga microservice architecture pattern for a food delivery app. +# Saga Pattern Using Orkes Conductor -## Running this Example +This is an example project showing how to build event driven applications using [Conductor](https://github.com/conductor-oss/conductor) -### Environment setup -1. Install JAVA 17 - https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html -2. Install Gradle - https://gradle.org/install/ -3. Generate Gradle Wrapper - https://www.baeldung.com/gradle-wrapper -4. Install sqlite (Only if necessary, i.e if SQLite JDBC Driver is not installed. If you are on Mac OS X or Linux, then SQLite is normally pre-installed) - https://www.tutorialspoint.com/sqlite/sqlite_installation.htm. +# Pre-requisites +1. Docker +2. Running conductor server -### Workflow Setup on Orkes Playground +**Start the conductor server** -#### Use existing out-of-the-box workflows -We have already setup these workflows with all the necessary permissions. These can be used directly, if you don't need to modify these workflows. -1. Food Delivery Workflow - https://play.orkes.io/workflowDef/FoodDeliveryWorkflow -2. Cancellation workflow - https://play.orkes.io/workflowDef/FoodDeliveryFailureWorkflow - -### Running the application and workers locally - -1. Clone the project to your local -2. Update following properties in [application.properties](src/main/resources/application.properties) - 1. `conductor.security.client.key-id` and `conductor.security.client.secret` are **NOT** set, please set them - * When connecting to playground - refer to this [article](https://orkes.io/content/how-to-videos/access-key-and-secret) to get a key and secret - * When connecting locally - follow the instructions [here (Install and Run Locally)](https://orkes.io/content/get-orkes-conductor) - 2. `conductor.worker.all.domain` is set to 'saga' by default, please change it to or something else to avoid conflicts with workflows and workers spun up by others -3. From the root project folder, run `gradlew bootRun` - -### Order Creation - -We can use two approaches: -1. Call the triggerRideBookingFlow API from within the Application - ``` - curl --location 'http://localhost:8081/triggerFoodDeliveryFlow' \ - --header 'Content-Type: application/json' \ - --data '{ - "customerEmail": "tester.qa@example.com", - "customerName": "Tester QA", - "customerContact": "+1(605)123-5674", - "address": "350 East 62nd Street, NY 10065", - "restaurantId": 2, - "foodItems": [ - { - "item": "Chicken with Broccoli", - "quantity": 1 - }, - { - "item": "Veggie Fried Rice", - "quantity": 1 - }, - { - "item": "Egg Drop Soup", - "quantity": 2 - } - ], - "additionalNotes": [ - "Do not put spice.", - "Send cutlery." - ], - "paymentMethod" : { - "type": "Credit Card", - "details": { - "number": "1234 4567 3325 1345", - "cvv": "123", - "expiry": "05/2022" - } - }, - "paymentAmount": 45.34, - "deliveryInstructions": "Leave at the door!" - }' - ``` -2. Directly call the Orkes API for creating a workflow - 1. Generate a JWT token by following steps mentioned [here](https://orkes.io/content/access-control-and-security/applications#generating-token) - 2. Make an HTTPS request from postman/curl similar to below after replacing \: -``` -curl --location 'https://play.orkes.io/api/workflow' \ ---header "Content-Type: application/json" \ ---header 'X-Authorization: ' \ ---request POST \ ---data \ -' -{ - "name": "FoodDeliveryWorkflow", - "version": 1, - "input": { - "customerEmail": "tester.qa@example.com", - "customerName": "Tester QA", - "customerContact": "+1(605)123-5674", - "address": "350 East 62nd Street, NY 10065", - "restaurantId": 2, - "foodItems": [ - { - "item": "Chicken with Broccoli", - "quantity": 1 - }, - { - "item": "Veggie Fried Rice", - "quantity": 1 - }, - { - "item": "Egg Drop Soup", - "quantity": 2 - }], - "additionalNotes": [ - "Do not put spice.", - "Send cutlery." - ], - "deliveryInstructions": "Leave at the door!", - "paymentAmount": 45.34, - "paymentMethod": { - "type" : "Credit Card", - "details" : { - "number": "1234 4567 3325 1345", - "expiry": "05/2025", - "cvv": "123" - } - } - } - "taskToDomain": { - "*": "saga" - } -} -' -``` - -A successful order creation workflow run will look like this: - -![Screenshot 2024-02-26 at 11 38 14 AM](https://github.com/conductor-sdk/conductor-examples-food-delivery/assets/127052609/377549ec-58b0-425c-922b-6318a20b68c8) - - -#### Triggering the cancellation workflow to simulate rollback of distributed transactions - -* Create an order with invalid payment expiry -``` -curl --location 'https://play.orkes.io/api/workflow' \ ---header "Content-Type: application/json" \ ---header 'X-Authorization: ' \ ---request POST \ ---data \ -' -{ - "name": "FoodDeliveryWorkflow", - "version": 1, - "input": { - "customerEmail": "tester.qa@example.com", - "customerName": "Tester QA", - "customerContact": "+1(605)123-5674", - "address": "350 East 62nd Street, NY 10065", - "restaurantId": 2, - "foodItems": [ - { - "item": "Chicken with Broccoli", - "quantity": 1 - }, - { - "item": "Veggie Fried Rice", - "quantity": 1 - }, - { - "item": "Egg Drop Soup", - "quantity": 2 - }], - "additionalNotes": [ - "Do not put spice.", - "Send cutlery." - ], - "deliveryInstructions": "Leave at the door!", - "paymentAmount": 45.34, - "paymentMethod": { - "type" : "Credit Card", - "details" : { - "number": "1234 4567 3325 1345", - "expiry": "05/2022", - "cvv": "123" - } - } - } - "taskToDomain": { - "*": "saga" - } -} -' -``` - -* This will cause the workflow to fail and trigger the cancellation workflow. -* Failed workflow run will look like this: - -![Screenshot 2024-02-26 at 1 14 02 PM](https://github.com/conductor-sdk/conductor-examples-food-delivery/assets/127052609/6078320f-f4d6-406e-98b9-7df110c70cb3) - - - -* A cancellation workflow run will look like this: - -![Screenshot 2024-02-26 at 1 15 07 PM](https://github.com/conductor-sdk/conductor-examples-food-delivery/assets/127052609/68c15035-82c1-4415-b502-93217ce40c80) - - -* In the above workflow diagram, the simulated distributed rollback can be seen. The rollback sequence in case of failure occurring while payment processing is as follows: - 1. Shipment is cancelled in the Shipment Service - 2. Payment is cancelled in the Payment Service - 3. Order is cancelled in the Order Service +```shell +docker run --init -p 8080:8080 -p 1234:5000 conductoross/conductor-standalone:3.15.0 +``` \ No newline at end of file From 614d91076694c4454f97d845757ab325faab53df Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Mon, 18 Mar 2024 20:02:15 +0100 Subject: [PATCH 30/88] [map-stream-to-map] merge a stream of maps to a single map --- .../MapStreamToMapUnitTest.java | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java diff --git a/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java new file mode 100644 index 0000000000..cbefd58396 --- /dev/null +++ b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java @@ -0,0 +1,153 @@ +package com.baeldung.streams.mapstreamtomap; + +import static java.lang.Math.max; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.Lists; + +public class MapStreamToMapUnitTest { + + Map playerMap1 = new HashMap() {{ + put("Kai", 92); + put("Liam", 100); + }}; + Map playerMap2 = new HashMap() {{ + put("Eric", 42); + put("Kevin", 77); + }}; + Map playerMap3 = new HashMap() {{ + put("Saajan", 35); + }}; + Map playerMap4 = new HashMap() {{ + put("Kai", 76); + }}; + Map playerMap5 = new HashMap() {{ + put("Kai", null); + put("Jerry", null); + }}; + + static Stream> getMapStream(Map... playerMaps) { + List> theList = Lists.newArrayList(playerMaps); + Collections.shuffle(theList); + return theList.stream(); + } + + @Test + void givenMapsStream_whenUsingFlatMapAndToMap_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); + put("Eric", 42); + put("Kevin", 77); + }}; + + Map mergedMap = getMapStream(playerMap1, playerMap2, playerMap3).flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + assertEquals(expectedMap, mergedMap); + } + + @Test + void givenMapsWithDuplicateKeys_whenUsingFlatMapAndToMap_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); // max of 76 and 92 + put("Eric", 42); + put("Kevin", 77); + }}; + + assertThrows(IllegalStateException.class, () -> getMapStream(playerMap1, playerMap2, playerMap3, playerMap4).flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)), "Duplicate key Kai (attempted merging values 92 and 76)"); + + Map mergedMap = getMapStream(playerMap1, playerMap2, playerMap3, playerMap4).flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max)); + + assertEquals(expectedMap, mergedMap); + } + + private Integer maxInteger(Integer int1, Integer int2) { + if (int1 == null) { + return int2; + } + if (int2 == null) { + return int1; + } + return max(int1, int2); + } + + @Test + void givenMapsWithDuplicateKeysAndNullValues_whenUsingFlatMapWithForEach_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); // max of 92, 76, and null + put("Eric", 42); + put("Kevin", 77); + put("Jerry", null); + }}; + + assertThrows(NullPointerException.class, () -> getMapStream(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5).flatMap(map -> map.entrySet() + .stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max))); + + Map mergedMap = new HashMap<>(); + getMapStream(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5).flatMap(map -> map.entrySet() + .stream()) + .forEach(entry -> { + String k = entry.getKey(); + Integer v = entry.getValue(); + if (mergedMap.containsKey(k)) { + mergedMap.put(k, maxInteger(mergedMap.get(k), v)); + } else { + mergedMap.put(k, v); + } + }); + assertEquals(expectedMap, mergedMap); + + } + + @Test + void givenMapsWithDuplicateKeysAndNullValues_whenUsingReduce_thenMultipleMapsMergedIntoOneMap() { + + Map expectedMap = new HashMap() {{ + put("Saajan", 35); + put("Liam", 100); + put("Kai", 92); // max of 92, 76, and null + put("Eric", 42); + put("Kevin", 77); + put("Jerry", null); + }}; + Stream> mapStream = getMapStream(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5); + Map mergedMap = mapStream.reduce(new HashMap<>(), (resultMap, theMap) -> { + theMap.forEach((k, v) -> { + if (resultMap.containsKey(k)) { + resultMap.put(k, maxInteger(resultMap.get(k), v)); + } else { + resultMap.put(k, v); + } + }); + return resultMap; + }); + + assertEquals(expectedMap, mergedMap); + + } +} \ No newline at end of file From 9456b4b953c7e95c22b85ae66a934d123d8eecfc Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Tue, 19 Mar 2024 09:32:58 +0100 Subject: [PATCH 31/88] [map-stream-to-map] updates.. 1 --- .../MapStreamToMapUnitTest.java | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java index cbefd58396..b23dd07fc8 100644 --- a/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java +++ b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java @@ -1,20 +1,20 @@ package com.baeldung.streams.mapstreamtomap; import static java.lang.Math.max; +import static java.util.stream.Collectors.flatMapping; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.reducing; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; -import com.google.common.collect.Lists; - public class MapStreamToMapUnitTest { Map playerMap1 = new HashMap() {{ @@ -36,12 +36,6 @@ public class MapStreamToMapUnitTest { put("Jerry", null); }}; - static Stream> getMapStream(Map... playerMaps) { - List> theList = Lists.newArrayList(playerMaps); - Collections.shuffle(theList); - return theList.stream(); - } - @Test void givenMapsStream_whenUsingFlatMapAndToMap_thenMultipleMapsMergedIntoOneMap() { @@ -53,7 +47,8 @@ public class MapStreamToMapUnitTest { put("Kevin", 77); }}; - Map mergedMap = getMapStream(playerMap1, playerMap2, playerMap3).flatMap(map -> map.entrySet() + Map mergedMap = Stream.of(playerMap1, playerMap2, playerMap3) + .flatMap(map -> map.entrySet() .stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); @@ -71,11 +66,13 @@ public class MapStreamToMapUnitTest { put("Kevin", 77); }}; - assertThrows(IllegalStateException.class, () -> getMapStream(playerMap1, playerMap2, playerMap3, playerMap4).flatMap(map -> map.entrySet() + assertThrows(IllegalStateException.class, () -> Stream.of(playerMap1, playerMap2, playerMap3, playerMap4) + .flatMap(map -> map.entrySet() .stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)), "Duplicate key Kai (attempted merging values 92 and 76)"); - Map mergedMap = getMapStream(playerMap1, playerMap2, playerMap3, playerMap4).flatMap(map -> map.entrySet() + Map mergedMap = Stream.of(playerMap1, playerMap2, playerMap3, playerMap4) + .flatMap(map -> map.entrySet() .stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max)); @@ -104,12 +101,14 @@ public class MapStreamToMapUnitTest { put("Jerry", null); }}; - assertThrows(NullPointerException.class, () -> getMapStream(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5).flatMap(map -> map.entrySet() + assertThrows(NullPointerException.class, () -> Stream.of(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5) + .flatMap(map -> map.entrySet() .stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max))); Map mergedMap = new HashMap<>(); - getMapStream(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5).flatMap(map -> map.entrySet() + Stream.of(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5) + .flatMap(map -> map.entrySet() .stream()) .forEach(entry -> { String k = entry.getKey(); @@ -135,19 +134,10 @@ public class MapStreamToMapUnitTest { put("Kevin", 77); put("Jerry", null); }}; - Stream> mapStream = getMapStream(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5); - Map mergedMap = mapStream.reduce(new HashMap<>(), (resultMap, theMap) -> { - theMap.forEach((k, v) -> { - if (resultMap.containsKey(k)) { - resultMap.put(k, maxInteger(resultMap.get(k), v)); - } else { - resultMap.put(k, v); - } - }); - return resultMap; - }); - + Map mergedMap = Stream.of(playerMap1, playerMap2, playerMap3, playerMap4, playerMap5) + .flatMap(x -> x.entrySet() + .stream()) + .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, reducing(null, this::maxInteger)))); assertEquals(expectedMap, mergedMap); - } } \ No newline at end of file From 356624bf222f79648cc4e0a74fca727150c6dc56 Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Tue, 19 Mar 2024 23:54:56 +0100 Subject: [PATCH 32/88] [add-to-immutable-list] add elements to immutable list --- .../addtoimmutablelist/AddElementsToImmutableListUnitTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java index f7ad690acb..13484b6dcb 100644 --- a/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java +++ b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java @@ -16,6 +16,7 @@ public class AddElementsToImmutableListUnitTest { return List.copyOf(tmpList); } + @SafeVarargs public static List appendElements(List immutableList, T... elements) { List tmpList = new ArrayList<>(immutableList); tmpList.addAll(Arrays.asList(elements)); From 0242528345012c6300cc4463fe873c033febf077 Mon Sep 17 00:00:00 2001 From: "Kai.Yuan" Date: Wed, 20 Mar 2024 17:20:04 +0100 Subject: [PATCH 33/88] [add-to-immutable-list] replace list.copyof with collections.unmodifiableList --- .../AddElementsToImmutableListUnitTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java index 13484b6dcb..397aca8906 100644 --- a/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java +++ b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; @@ -13,14 +14,14 @@ public class AddElementsToImmutableListUnitTest { public static List appendAnElement(List immutableList, T element) { List tmpList = new ArrayList<>(immutableList); tmpList.add(element); - return List.copyOf(tmpList); + return Collections.unmodifiableList(tmpList); } @SafeVarargs public static List appendElements(List immutableList, T... elements) { List tmpList = new ArrayList<>(immutableList); tmpList.addAll(Arrays.asList(elements)); - return List.copyOf(tmpList); + return Collections.unmodifiableList(tmpList); } @Test From 9dc79459fb2eef481a8897af963bc4530ee18e4f Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:10:40 +0800 Subject: [PATCH 34/88] Update README.md --- .../core-java-arrays-operations-advanced-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/README.md b/core-java-modules/core-java-arrays-operations-advanced-2/README.md index 88bda5c6d7..e762508bcd 100644 --- a/core-java-modules/core-java-arrays-operations-advanced-2/README.md +++ b/core-java-modules/core-java-arrays-operations-advanced-2/README.md @@ -2,3 +2,4 @@ - [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item) - [Find the Equilibrium Indexes of an Array in Java](https://www.baeldung.com/java-equilibrium-index-array) - [Moves Zeros to the End of an Array in Java](https://www.baeldung.com/java-array-sort-move-zeros-end) +- [Finding the Majority Element of an Array in Java](https://www.baeldung.com/java-array-find-majority-element) From 3019e85e4fb8fa4d68afc6dbc15efaece2ab73cd Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:12:06 +0800 Subject: [PATCH 35/88] Update README.md --- core-java-modules/core-java-collections-array-list-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-array-list-2/README.md b/core-java-modules/core-java-collections-array-list-2/README.md index 575e0dbb07..aec8b90fb5 100644 --- a/core-java-modules/core-java-collections-array-list-2/README.md +++ b/core-java-modules/core-java-collections-array-list-2/README.md @@ -4,3 +4,4 @@ This module contains articles about the Java ArrayList collection ### Relevant Articles: - [Create an ArrayList with Multiple Object Types](https://www.baeldung.com/java-arraylist-multiple-object-types) +- [Finding the Peak Elements of a List](https://www.baeldung.com/java-list-find-peak) From debd762c512f700d1bd40ba0e23c76a67216a32a Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:14:03 +0800 Subject: [PATCH 36/88] Update README.md --- core-java-modules/core-java-networking-4/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-modules/core-java-networking-4/README.md b/core-java-modules/core-java-networking-4/README.md index 88eed162af..13b82f6c10 100644 --- a/core-java-modules/core-java-networking-4/README.md +++ b/core-java-modules/core-java-networking-4/README.md @@ -8,4 +8,5 @@ - [Normalize a URL in Java](https://www.baeldung.com/java-url-normalization) - [Translating Space Characters in URLEncoder](https://www.baeldung.com/java-urlencoder-translate-space-characters) - [Creating a Custom URL Connection](https://www.baeldung.com/java-custom-url-connection) -- [[<-- Prev]](/core-java-modules/core-java-networking-3) \ No newline at end of file +- [Obtaining the Last Path Segment of a URI in Java](https://www.baeldung.com/java-uri-get-last-path-segment) +- [[<-- Prev]](/core-java-modules/core-java-networking-3) From 2ee6cb41917314a77b2f026b64938ee7eabdc98f Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:15:29 +0800 Subject: [PATCH 37/88] Update README.md --- libraries-cli/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries-cli/README.md b/libraries-cli/README.md index b31bb2853d..0f561ef7db 100644 --- a/libraries-cli/README.md +++ b/libraries-cli/README.md @@ -6,4 +6,5 @@ This module contains articles about cli libraries. - [Create a Java Command Line Program with Picocli](https://www.baeldung.com/java-picocli-create-command-line-program) - [Parsing Command-Line Parameters with JCommander](https://www.baeldung.com/jcommander-parsing-command-line-parameters) -- [Parsing Command-Line Parameters with Airline](https://www.baeldung.com/java-airline) \ No newline at end of file +- [Parsing Command-Line Parameters with Airline](https://www.baeldung.com/java-airline) +- [Intro to the Apache Commons CLI](https://www.baeldung.com/apache-commons-cli) From 0824bee7cd24af60ce5f808c51152ff634bf9153 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:17:11 +0800 Subject: [PATCH 38/88] Update README.md --- algorithms-modules/algorithms-miscellaneous-7/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms-modules/algorithms-miscellaneous-7/README.md b/algorithms-modules/algorithms-miscellaneous-7/README.md index 1d53235990..d58e645b8b 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/README.md +++ b/algorithms-modules/algorithms-miscellaneous-7/README.md @@ -12,4 +12,5 @@ - [Count the Number of Unique Digits in an Integer using Java](https://www.baeldung.com/java-int-count-unique-digits) - [Generate Juggler Sequence in Java](https://www.baeldung.com/java-generate-juggler-sequence) - [Finding the Parent of a Node in a Binary Search Tree with Java](https://www.baeldung.com/java-find-parent-node-binary-search-tree) +- [Check if a Number Is a Happy Number in Java](https://www.baeldung.com/java-happy-sad-number-test) - More articles: [[<-- prev]](/algorithms-miscellaneous-6) From 191b9092568f7ca81166d2c803163f7043b80aa2 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:20:37 +0800 Subject: [PATCH 39/88] Create README.md --- messaging-modules/java-redpanda/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 messaging-modules/java-redpanda/README.md diff --git a/messaging-modules/java-redpanda/README.md b/messaging-modules/java-redpanda/README.md new file mode 100644 index 0000000000..36ee68b5bb --- /dev/null +++ b/messaging-modules/java-redpanda/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Introduction to Redpanda](https://www.baeldung.com/redpanda) From 3cf8f57e88346aa48de1b7bcbe67b837536536d4 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:22:27 +0800 Subject: [PATCH 40/88] Update README.md --- .../spring-boot-basic-customization-3/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-boot-modules/spring-boot-basic-customization-3/README.md b/spring-boot-modules/spring-boot-basic-customization-3/README.md index 2641427608..0c12a370f9 100644 --- a/spring-boot-modules/spring-boot-basic-customization-3/README.md +++ b/spring-boot-modules/spring-boot-basic-customization-3/README.md @@ -2,4 +2,5 @@ This module contains articles about Spring Boot customization 3 -### Relevant Articles: \ No newline at end of file +### Relevant Articles: +- [How to Autowire a Spring Bean in a Servlet Filter](https://www.baeldung.com/spring-autowire-bean-servlet-filter) From d93df50e271ddd853743ca3ade31945113477c5c Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:23:37 +0800 Subject: [PATCH 41/88] Update README.md --- testing-modules/groovy-spock/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/groovy-spock/README.md b/testing-modules/groovy-spock/README.md index 14c4b145f9..bcca7b9c6c 100644 --- a/testing-modules/groovy-spock/README.md +++ b/testing-modules/groovy-spock/README.md @@ -4,3 +4,4 @@ - [Difference Between Stub, Mock, and Spy in the Spock Framework](https://www.baeldung.com/spock-stub-mock-spy) - [Guide to Spock Extensions](https://www.baeldung.com/spock-extensions) - [Improving Test Coverage and Readability With Spock’s Data Pipes and Tables](https://www.baeldung.com/java-spock-improve-test-coverage-data-feeds-tables) +- [Capturing Method Arguments When Running Spock Tests](https://www.baeldung.com/groovy/spock-capture-passed-parameters) From 26c5a38a28cd5b444d6f3d13f1ae05ce9632e076 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:24:39 +0800 Subject: [PATCH 42/88] Update README.md --- core-java-modules/core-java-numbers-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-numbers-2/README.md b/core-java-modules/core-java-numbers-2/README.md index 54f6cf30e8..59d29a9d74 100644 --- a/core-java-modules/core-java-numbers-2/README.md +++ b/core-java-modules/core-java-numbers-2/README.md @@ -13,4 +13,5 @@ This module contains articles about numbers in Java. - [Binary Numbers in Java](https://www.baeldung.com/java-binary-numbers) - [Finding the Least Common Multiple in Java](https://www.baeldung.com/java-least-common-multiple) - [Binary Numbers in Java](https://www.baeldung.com/java-binary-numbers) +- [RGB Representation as an Integer in Java](https://www.baeldung.com/java-rgb-color-representation) - More articles: [[<-- prev]](../core-java-numbers) [[next -->]](../core-java-numbers-3) From 118fc23560196def39039e7db65d10084ab5234a Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:26:44 +0800 Subject: [PATCH 43/88] Update README.md --- jsoup/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/jsoup/README.md b/jsoup/README.md index 3a8a7f0ebb..f1aeba5b06 100644 --- a/jsoup/README.md +++ b/jsoup/README.md @@ -6,6 +6,7 @@ This module contains articles about jsoup. - [Parsing HTML in Java with Jsoup](https://www.baeldung.com/java-with-jsoup) - [How to Add Proxy Support to Jsoup?](https://www.baeldung.com/java-jsoup-proxy) - [Preserving Line Breaks When Using Jsoup](https://www.baeldung.com/jsoup-line-breaks) +- [Parsing HTML Table in Java With Jsoup](https://www.baeldung.com/java-jsoup-parse-html-table) ### Build the Project From 68df725a28d36d1518ff6690783860116a4018fd Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:28:04 +0800 Subject: [PATCH 44/88] Update README.md --- persistence-modules/spring-data-jpa-repo-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/spring-data-jpa-repo-3/README.md b/persistence-modules/spring-data-jpa-repo-3/README.md index ff219a1d78..dbd7b67e2c 100644 --- a/persistence-modules/spring-data-jpa-repo-3/README.md +++ b/persistence-modules/spring-data-jpa-repo-3/README.md @@ -8,4 +8,5 @@ This module contains articles about Spring Data JPA. - [Correct Use of flush() in JPA](https://www.baeldung.com/spring-jpa-flush) - [Difference Between findBy and findOneBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-findby-vs-findoneby) - [How to Get Last Record in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-last-record) +- [Refresh and Fetch an Entity After Save in JPA](https://www.baeldung.com/spring-data-jpa-refresh-fetch-entity-after-save) - More articles: [[<-- prev]](../spring-data-jpa-repo-2) From a3abc7714020b1cf50250ebbf787e2821666cc78 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:29:09 +0800 Subject: [PATCH 45/88] Update README.md --- apache-kafka-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apache-kafka-3/README.md b/apache-kafka-3/README.md index 0b96e55385..a2a99425f9 100644 --- a/apache-kafka-3/README.md +++ b/apache-kafka-3/README.md @@ -6,4 +6,5 @@ This module contains articles about Apache Kafka. You can build the project from the command line using: *mvn clean install*, or in an IDE. ### Relevant Articles: +- [Commit Offsets in Kafka](https://www.baeldung.com/kafka-commit-offsets) From 37ab5e240a1262f4fc3872815ba068ac9a77d7f1 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:32:09 +0800 Subject: [PATCH 46/88] Update README.md --- algorithms-modules/algorithms-miscellaneous-7/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms-modules/algorithms-miscellaneous-7/README.md b/algorithms-modules/algorithms-miscellaneous-7/README.md index d58e645b8b..a08948eda5 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/README.md +++ b/algorithms-modules/algorithms-miscellaneous-7/README.md @@ -13,4 +13,5 @@ - [Generate Juggler Sequence in Java](https://www.baeldung.com/java-generate-juggler-sequence) - [Finding the Parent of a Node in a Binary Search Tree with Java](https://www.baeldung.com/java-find-parent-node-binary-search-tree) - [Check if a Number Is a Happy Number in Java](https://www.baeldung.com/java-happy-sad-number-test) +- [Find the Largest Number Possible After Removing k Digits of a Number](https://www.baeldung.com/java-find-largest-number-remove-k-digits) - More articles: [[<-- prev]](/algorithms-miscellaneous-6) From 4a87ccbb01563ffde79fcc90260d57844869e3de Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:34:23 +0800 Subject: [PATCH 47/88] Update README.md --- core-java-modules/core-java-lang-math-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-lang-math-4/README.md b/core-java-modules/core-java-lang-math-4/README.md index 0c28f94821..377c51848d 100644 --- a/core-java-modules/core-java-lang-math-4/README.md +++ b/core-java-modules/core-java-lang-math-4/README.md @@ -1,3 +1,4 @@ ========= ### Relevant articles: +- [Calculate Percentiles in Java](https://www.baeldung.com/java-compute-percentiles) From b31ede967fbf212588f3b38b8377852527b7a31d Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:37:05 +0800 Subject: [PATCH 48/88] Update README.md --- core-java-modules/core-java-collections/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections/README.md b/core-java-modules/core-java-collections/README.md index 574f61ac6a..ec274fa051 100644 --- a/core-java-modules/core-java-collections/README.md +++ b/core-java-modules/core-java-collections/README.md @@ -13,4 +13,5 @@ This module contains articles about Java collections - [Guide to the Java Queue Interface](https://www.baeldung.com/java-queue) - [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections) - [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list) +- [Adding Elements to a Collection During Iteration](https://www.baeldung.com/java-add-elements-collection) - More articles: [[next -->]](/core-java-modules/core-java-collections-2) From add089ed5e6059bab4be1b7314d215ddb51a488d Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:39:20 +0800 Subject: [PATCH 49/88] Update README.md --- core-java-modules/core-java-lang-operators-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-lang-operators-2/README.md b/core-java-modules/core-java-lang-operators-2/README.md index 52b05e95a4..0dc6f7d303 100644 --- a/core-java-modules/core-java-lang-operators-2/README.md +++ b/core-java-modules/core-java-lang-operators-2/README.md @@ -12,3 +12,4 @@ This module contains articles about Java operators - [What Does “––>” Mean in Java?](https://www.baeldung.com/java-minus-minus-greaterthan) - [All the Ways Java Uses the Colon Character](https://www.baeldung.com/java-colon) - [Convert Infix to Postfix Expressions in Java](https://www.baeldung.com/java-convert-infix-to-postfix-expressions) +- [Representation of Integers at a Bit Level in Java](https://www.baeldung.com/java-integer-bit-representation) From bf24acf2936ad64fa63b46f226cbb7bb65059e32 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:42:32 +0800 Subject: [PATCH 50/88] Update README.md --- persistence-modules/querydsl/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/querydsl/README.md b/persistence-modules/querydsl/README.md index 03e113795d..1e1cf0f464 100644 --- a/persistence-modules/querydsl/README.md +++ b/persistence-modules/querydsl/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Intro to Querydsl](https://www.baeldung.com/intro-to-querydsl) - [A Guide to Querydsl with JPA](https://www.baeldung.com/querydsl-with-jpa-tutorial) +- [Querydsl vs. JPA Criteria](https://www.baeldung.com/jpa-criteria-querydsl-differences) From 2834450ef5c5405cfad7ee6e006b7037054ae539 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:45:03 +0800 Subject: [PATCH 51/88] Update README.md --- spring-kafka-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-kafka-3/README.md b/spring-kafka-3/README.md index e150413789..624c6ff790 100644 --- a/spring-kafka-3/README.md +++ b/spring-kafka-3/README.md @@ -4,3 +4,4 @@ - [View Kafka Headers in Java](https://www.baeldung.com/java-kafka-view-headers) - [Understanding Kafka InstanceAlreadyExistsException in Java](https://www.baeldung.com/kafka-instancealreadyexistsexception) - [Difference Between GroupId and ConsumerId in Apache Kafka](https://www.baeldung.com/apache-kafka-groupid-vs-consumerid) +- [Dynamically Managing Kafka Listeners in Spring Boot](https://www.baeldung.com/kafka-spring-boot-dynamically-manage-listeners) From 37004adaa0fd69ec1e1aa053a9582d300862e3d1 Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:46:26 +0800 Subject: [PATCH 52/88] Update README.md --- core-java-modules/core-java-date-operations-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-date-operations-4/README.md b/core-java-modules/core-java-date-operations-4/README.md index 0e9bc710c8..97d738f2ba 100644 --- a/core-java-modules/core-java-date-operations-4/README.md +++ b/core-java-modules/core-java-date-operations-4/README.md @@ -5,3 +5,4 @@ This module contains articles about date operations in Java. - [Calculate Number of Weekdays Between Two Dates in Java](https://www.baeldung.com/java-count-weekdays-between-two-dates) - [Convert Long to Date in Java](https://www.baeldung.com/java-long-date-conversion) - [Convert Date to Unix Timestamp in Java](https://www.baeldung.com/java-convert-date-unix-timestamp) +- [Checking if a Date Object Equals Yesterday](https://www.baeldung.com/java-date-check-yesterday) From 5159b1bb62f2a84356b560f15c1fb635ec1ce59f Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:48:34 +0800 Subject: [PATCH 53/88] Update README.md --- spring-boot-modules/spring-caching-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-modules/spring-caching-2/README.md b/spring-boot-modules/spring-caching-2/README.md index 864a17d98b..fffdacdfb2 100644 --- a/spring-boot-modules/spring-caching-2/README.md +++ b/spring-boot-modules/spring-caching-2/README.md @@ -2,4 +2,5 @@ - [Spring Boot Cache with Redis](https://www.baeldung.com/spring-boot-redis-cache) - [Setting Time-To-Live Value for Caching](https://www.baeldung.com/spring-setting-ttl-value-cache) - [Get All Cached Keys with Caffeine Cache in Spring Boot](https://www.baeldung.com/spring-boot-caffeine-spring-get-all-keys) +- [Implement Two-Level Cache With Spring](https://www.baeldung.com/spring-two-level-cache) From c49c8518005c0d9c2a0fcb2f8c5359ce317ac74d Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:50:05 +0800 Subject: [PATCH 54/88] Update README.md --- core-java-modules/core-java-8-datetime-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-8-datetime-2/README.md b/core-java-modules/core-java-8-datetime-2/README.md index e689e7257f..04461663e3 100644 --- a/core-java-modules/core-java-8-datetime-2/README.md +++ b/core-java-modules/core-java-8-datetime-2/README.md @@ -13,4 +13,5 @@ - [Format LocalDate to ISO 8601 With T and Z](https://www.baeldung.com/java-format-localdate-iso-8601-t-z) - [Check if Two Date Ranges Overlap](https://www.baeldung.com/java-check-two-date-ranges-overlap) - [Difference between ZoneOffset.UTC and ZoneId.of(“UTC”)](https://www.baeldung.com/java-zoneoffset-utc-zoneid-of) +- [Check if a Given Time Lies Between Two Times Regardless of Date](https://www.baeldung.com/java-check-between-two-times) - [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1) From 1b599ba18d3aefbed52a4124b1f6d10dfec4d67e Mon Sep 17 00:00:00 2001 From: rcalago <149600319+rcalago@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:51:24 +0800 Subject: [PATCH 55/88] Update README.md --- core-java-modules/core-java-concurrency-advanced-5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-concurrency-advanced-5/README.md b/core-java-modules/core-java-concurrency-advanced-5/README.md index 5a41310707..45937aa47f 100644 --- a/core-java-modules/core-java-concurrency-advanced-5/README.md +++ b/core-java-modules/core-java-concurrency-advanced-5/README.md @@ -4,3 +4,4 @@ - [Working with Exceptions in Java CompletableFuture](https://www.baeldung.com/java-exceptions-completablefuture) - [CountDownLatch vs. Semaphore](https://www.baeldung.com/java-countdownlatch-vs-semaphore) - [Callbacks in ListenableFuture and CompletableFuture](https://www.baeldung.com/java-callbacks-listenablefuture-completablefuture) +- [Guide to ExecutorService vs. CompletableFuture](https://www.baeldung.com/java-executorservice-vs-completablefuture) From 8f2b321720ef1a9147a258e156046064c5dd06ca Mon Sep 17 00:00:00 2001 From: ovidiu-mihai98 <138307181+ovidiumihaitacu@users.noreply.github.com> Date: Thu, 21 Mar 2024 18:36:10 +0200 Subject: [PATCH 56/88] Split Changelogs --- .../liquibase/changelog-customChangeset.xml | 22 +++++++++++++++++++ .../main/resources/liquibase/changelog.xml | 6 ----- 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml diff --git a/persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml b/persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml new file mode 100644 index 0000000000..e33bc1610a --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/liquibase/changelog-customChangeset.xml @@ -0,0 +1,22 @@ + + + + + + CREATE SCHEMA IF NOT EXISTS user_management; + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml index cec8ae138f..6ae5187a92 100644 --- a/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml +++ b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml @@ -4,13 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"> - - - - - - From 8c5104e78e7654754b65594ccd4a56598f836aa5 Mon Sep 17 00:00:00 2001 From: Riza Farheen <82656175+RizaFarheen@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:38:41 +0400 Subject: [PATCH 57/88] Delete microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java --- .../io/orkes/example/saga/SagaApplicationTests.java | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java diff --git a/microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java b/microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java deleted file mode 100644 index dfdebf099f..0000000000 --- a/microservices-modules/saga-pattern/src/test/java/io/orkes/example/saga/SagaApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.orkes.example.saga; - -//import org.junit.jupiter.api.Test; -//import org.springframework.boot.test.context.SpringBootTest; -// -//@SpringBootTest -//class SagaApplicationTests { -// -// @Test -// void contextLoads() { -// } -// -//} From 8095c35738b6a477ee153a7501333213c4283736 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Fri, 22 Mar 2024 16:19:54 +0100 Subject: [PATCH 58/88] [JAVA-32540] Change the Kafka test to Manual type (#16193) --- .../{KafkaDltIntegrationTest.java => KafkaDltManualTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/{KafkaDltIntegrationTest.java => KafkaDltManualTest.java} (99%) diff --git a/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltManualTest.java similarity index 99% rename from spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java rename to spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltManualTest.java index 72b77c360f..fb75e56063 100644 --- a/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltIntegrationTest.java +++ b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/dlt/KafkaDltManualTest.java @@ -34,7 +34,7 @@ import org.springframework.test.context.ActiveProfiles; topics = {"payments-fail-on-error-dlt", "payments-retry-on-error-dlt", "payments-no-dlt"} ) @ActiveProfiles("dlt") -public class KafkaDltIntegrationTest { +public class KafkaDltManualTest { private static final String FAIL_ON_ERROR_TOPIC = "payments-fail-on-error-dlt"; private static final String RETRY_ON_ERROR_TOPIC = "payments-retry-on-error-dlt"; private static final String NO_DLT_TOPIC = "payments-no-dlt"; From 04b7d05a762b03f36a462f4a5fdfdbb30da26847 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Fri, 22 Mar 2024 16:36:21 +0100 Subject: [PATCH 59/88] [JAVA-32305] Failing test for External UrlCheckerUnitTest in core-java-networking-2 (#16174) --- ...lCheckerUnitTest.java => UrlCheckerIntegrationTest.java} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/{UrlCheckerUnitTest.java => UrlCheckerIntegrationTest.java} (92%) diff --git a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerUnitTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java similarity index 92% rename from core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerUnitTest.java rename to core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java index 5e295e65a0..e3100deebc 100644 --- a/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerUnitTest.java +++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/url/UrlCheckerIntegrationTest.java @@ -6,7 +6,7 @@ import java.io.IOException; import org.junit.Test; -public class UrlCheckerUnitTest { +public class UrlCheckerIntegrationTest { @Test public void givenValidUrl_WhenUsingHEAD_ThenReturn200() throws IOException { @@ -18,7 +18,7 @@ public class UrlCheckerUnitTest { @Test public void givenInvalidIUrl_WhenUsingHEAD_ThenReturn404() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com/unkownurl"); + int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com/xyz"); assertEquals(404, responseCode); } @@ -32,7 +32,7 @@ public class UrlCheckerUnitTest { @Test public void givenInvalidIUrl_WhenUsingGET_ThenReturn404() throws IOException { UrlChecker tester = new UrlChecker(); - int responseCode = tester.getResponseCodeForURL("http://www.example.com/unkownurl"); + int responseCode = tester.getResponseCodeForURL("http://www.example.com/xyz"); assertEquals(404, responseCode); } From da41c860a11ef32559b5fdf70c63162c4ea722d7 Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Fri, 22 Mar 2024 21:51:03 +0530 Subject: [PATCH 60/88] [JAVA-29010] Upgrade spring-reactive-security to Spring Boot 3 (#16153) --- spring-reactive-modules/pom.xml | 2 +- .../spring-reactive-security/pom.xml | 19 ++++++++++++++----- .../authresolver/CustomWebSecurityConfig.java | 13 +++++++------ .../global/CorsGlobalConfigApplication.java | 2 +- .../webfilter/CorsWebFilterApplication.java | 2 +- .../webflux/EmployeeWebSecurityConfig.java | 11 +++++------ .../AuthResolverIntegrationTest.java | 6 ++++-- 7 files changed, 33 insertions(+), 22 deletions(-) diff --git a/spring-reactive-modules/pom.xml b/spring-reactive-modules/pom.xml index 6ab85c88b4..a8a9d6de8a 100644 --- a/spring-reactive-modules/pom.xml +++ b/spring-reactive-modules/pom.xml @@ -24,7 +24,7 @@ spring-reactive-client-2 spring-reactive-filters spring-reactive-oauth - spring-reactive-security + spring-reactive-data-couchbase spring-reactive spring-reactive-exceptions diff --git a/spring-reactive-modules/spring-reactive-security/pom.xml b/spring-reactive-modules/spring-reactive-security/pom.xml index d501a03c46..ea886f5855 100644 --- a/spring-reactive-modules/spring-reactive-security/pom.xml +++ b/spring-reactive-modules/spring-reactive-security/pom.xml @@ -10,9 +10,10 @@ spring boot security sample project about new features - com.baeldung.spring.reactive - spring-reactive-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -34,8 +35,8 @@ ${reactor-spring.version} - javax.json.bind - javax.json.bind-api + jakarta.json.bind + jakarta.json.bind-api org.projectlombok @@ -51,6 +52,7 @@ org.apache.johnzon johnzon-jsonb + ${johnzon-jsonb.version} @@ -63,6 +65,11 @@ spring-boot-devtools runtime + + jakarta.json + jakarta.json-api + ${jakarta.json-api.version} + org.springframework.boot spring-boot-starter-test @@ -117,6 +124,8 @@ 1.0 3.1.6.RELEASE 3.4.29 + 2.0.1 + 2.0.0 \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java index dc5eab3dd5..77f83be28d 100644 --- a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java +++ b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/authresolver/CustomWebSecurityConfig.java @@ -2,10 +2,13 @@ package com.baeldung.reactive.authresolver; import java.util.Collections; import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.ReactiveAuthenticationManager; import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.SecurityWebFiltersOrder; import org.springframework.security.config.web.server.ServerHttpSecurity; @@ -24,12 +27,10 @@ public class CustomWebSecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http - .authorizeExchange() - .pathMatchers("/**") - .authenticated() - .and() - .httpBasic() - .disable() + .csrf(csrfSpec -> csrfSpec.disable()) + .authorizeExchange(auth -> auth.pathMatchers(HttpMethod.GET,"/**") + .authenticated()) + .httpBasic(httpBasicSpec -> httpBasicSpec.disable()) .addFilterAfter(authenticationWebFilter(), SecurityWebFiltersOrder.REACTOR_CONTEXT) .build(); } diff --git a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/global/CorsGlobalConfigApplication.java b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/global/CorsGlobalConfigApplication.java index a70f937980..8be6484e68 100644 --- a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/global/CorsGlobalConfigApplication.java +++ b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/global/CorsGlobalConfigApplication.java @@ -27,7 +27,7 @@ public class CorsGlobalConfigApplication { @Bean public SecurityWebFilterChain corsGlobalSpringSecurityFilterChain(ServerHttpSecurity http) { - http.csrf().disable(); + http.csrf(csrfSpec -> csrfSpec.disable()); return http.build(); } } diff --git a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/webfilter/CorsWebFilterApplication.java b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/webfilter/CorsWebFilterApplication.java index 7792975768..343151498a 100644 --- a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/webfilter/CorsWebFilterApplication.java +++ b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/reactive/cors/webfilter/CorsWebFilterApplication.java @@ -27,7 +27,7 @@ public class CorsWebFilterApplication { @Bean public SecurityWebFilterChain corsWebfilterSpringSecurityFilterChain(ServerHttpSecurity http) { - http.csrf().disable(); + http.csrf(csrfSpec -> csrfSpec.disable()); return http.build(); } diff --git a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebSecurityConfig.java b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebSecurityConfig.java index 75475a0f08..929e466169 100644 --- a/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebSecurityConfig.java +++ b/spring-reactive-modules/spring-reactive-security/src/main/java/com/baeldung/webflux/EmployeeWebSecurityConfig.java @@ -3,6 +3,7 @@ package com.baeldung.webflux; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; @@ -27,15 +28,13 @@ public class EmployeeWebSecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http.csrf() - .disable() - .authorizeExchange() + http.csrf(csrfSpec -> csrfSpec.disable()) + .authorizeExchange(auth -> auth .pathMatchers(HttpMethod.POST, "/employees/update") .hasRole("ADMIN") .pathMatchers("/**") - .permitAll() - .and() - .httpBasic(); + .permitAll()) + .httpBasic(Customizer.withDefaults()); return http.build(); } diff --git a/spring-reactive-modules/spring-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java b/spring-reactive-modules/spring-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java index 9e0855d086..ca3ea19e09 100644 --- a/spring-reactive-modules/spring-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java +++ b/spring-reactive-modules/spring-reactive-security/src/test/java/com/baeldung/reactive/authresolver/AuthResolverIntegrationTest.java @@ -1,19 +1,21 @@ package com.baeldung.reactive.authresolver; import java.util.Base64; - import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AuthResolverApplication.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = {AuthResolverApplication.class, AuthResolverController.class, CustomWebSecurityConfig.class}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@AutoConfigureWebTestClient(timeout = "36000000") public class AuthResolverIntegrationTest { @Autowired private WebTestClient testClient; From e65c1f851fa27ea9d2b61c8f2a5160139e5e6865 Mon Sep 17 00:00:00 2001 From: sam-gardner <53271849+sam-gardner@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:37:51 +0000 Subject: [PATCH 61/88] [JAVA-28945] Upgrade cloud-foundry-uaa to Spring Boot 3 (#16181) --- ...AAOAuth2ResourceServerSecurityConfiguration.java | 13 ++++++------- security-modules/cloud-foundry-uaa/pom.xml | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java b/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java index 9bdee7f732..0ce558f9e0 100644 --- a/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java +++ b/security-modules/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java @@ -1,6 +1,7 @@ package com.baeldung.cfuaa.oauth2.resourceserver; import org.springframework.context.annotation.Bean; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @@ -10,16 +11,14 @@ public class CFUAAOAuth2ResourceServerSecurityConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers("/read/**") + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/read/**") .hasAuthority("SCOPE_resource.read") - .antMatchers("/write/**") + .requestMatchers("/write/**") .hasAuthority("SCOPE_resource.write") .anyRequest() - .authenticated() - .and() - .oauth2ResourceServer() - .jwt(); + .authenticated()) + .oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults())); return http.build(); } diff --git a/security-modules/cloud-foundry-uaa/pom.xml b/security-modules/cloud-foundry-uaa/pom.xml index ff26d56dc3..4ba70fbd43 100644 --- a/security-modules/cloud-foundry-uaa/pom.xml +++ b/security-modules/cloud-foundry-uaa/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 From da0dec8e13620a2c1aeb194820ba7835600fc53d Mon Sep 17 00:00:00 2001 From: sam-gardner <53271849+sam-gardner@users.noreply.github.com> Date: Fri, 22 Mar 2024 17:56:27 +0000 Subject: [PATCH 62/88] JAVA-32061 Upgrade spring-rest-simple to Spring Boot 3 (#16160) --- spring-web-modules/spring-rest-simple/pom.xml | 40 +++++++++---------- .../apachefileupload/UploadController.java | 39 +++++++++--------- .../java/com/baeldung/web/util/LinkUtil.java | 2 +- .../web/test/RequestMappingLiveTest.java | 2 +- 4 files changed, 40 insertions(+), 43 deletions(-) diff --git a/spring-web-modules/spring-rest-simple/pom.xml b/spring-web-modules/spring-rest-simple/pom.xml index a75c7c0e90..7cb9158f8f 100644 --- a/spring-web-modules/spring-rest-simple/pom.xml +++ b/spring-web-modules/spring-rest-simple/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -59,26 +59,16 @@ ${spring-oxm.version} - commons-fileupload - commons-fileupload + org.apache.commons + commons-fileupload2-jakarta ${commons-fileupload.version} - - javax.servlet - javax.servlet-api - provided - - - javax.servlet - jstl - runtime + org.apache.commons + commons-fileupload2-jakarta-servlet6 + ${commons-fileupload2-jakarta-servlet6.version} - - com.fasterxml.jackson.core - jackson-databind - com.fasterxml.jackson.dataformat jackson-dataformat-xml @@ -88,6 +78,11 @@ xstream ${xstream.version} + + jakarta.xml.bind + jakarta.xml.bind-api + ${jakarta.xml.bind-api.version} + com.google.guava @@ -110,9 +105,10 @@ spring-test - com.jayway.restassured + io.rest-assured rest-assured - ${jayway-rest-assured.version} + ${rest-assured.version} + test com.google.protobuf @@ -273,7 +269,6 @@ 1.4 3.1.0 1.4.9 - 2.9.0 6.1.4 1.6.0 @@ -281,6 +276,11 @@ 4.12.0 2.2.0 + 2.0.0-M1 + 5.4.0 + 2.3.2 + 2.0.0-M2 + 5.3.1 \ No newline at end of file diff --git a/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java index b9b6739898..6c9b1e9c65 100644 --- a/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java +++ b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java @@ -1,39 +1,36 @@ package com.baeldung.apachefileupload; -import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpServletRequest; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemIterator; -import org.apache.commons.fileupload.FileItemStream; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.fileupload.util.Streams; +import org.apache.commons.fileupload2.core.FileItem; +import org.apache.commons.fileupload2.core.FileItemInput; +import org.apache.commons.fileupload2.core.FileItemInputIterator; +import org.apache.commons.fileupload2.core.DiskFileItemFactory; +import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload; + import org.apache.commons.io.IOUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import jakarta.servlet.http.HttpServletRequest; + @RestController public class UploadController { @RequestMapping(value = "/upload", method = RequestMethod.POST) public String handleUpload(HttpServletRequest request) { System.out.println(System.getProperty("java.io.tmpdir")); - boolean isMultipart = ServletFileUpload.isMultipartContent(request); + boolean isMultipart = JakartaServletFileUpload.isMultipartContent(request); // Create a factory for disk-based file items - DiskFileItemFactory factory = new DiskFileItemFactory(); - factory.setRepository(new File(System.getProperty("java.io.tmpdir"))); - factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD); - factory.setFileCleaningTracker(null); + DiskFileItemFactory factory = DiskFileItemFactory.builder().get(); // Configure a repository (to ensure a secure temp location is used) - ServletFileUpload upload = new ServletFileUpload(factory); + JakartaServletFileUpload upload = new JakartaServletFileUpload(factory); try { // Parse the request List items = upload.parseRequest(request); @@ -51,21 +48,21 @@ public class UploadController { } } // Parse the request with Streaming API - upload = new ServletFileUpload(); - FileItemIterator iterStream = upload.getItemIterator(request); + upload = new JakartaServletFileUpload(); + FileItemInputIterator iterStream = upload.getItemIterator(request); while (iterStream.hasNext()) { - FileItemStream item = iterStream.next(); + FileItemInput item = iterStream.next(); String name = item.getFieldName(); - InputStream stream = item.openStream(); + InputStream stream = item.getInputStream(); if (!item.isFormField()) { //Process the InputStream } else { //process form fields - String formFieldValue = Streams.asString(stream); + String formFieldValue = IOUtils.toString(stream, StandardCharsets.UTF_8); } } return "success!"; - } catch (IOException | FileUploadException ex) { + } catch (IOException ex) { return "failed: " + ex.getMessage(); } } diff --git a/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java index 3ebba8ae1c..82e3d2c913 100644 --- a/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java +++ b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java @@ -1,6 +1,6 @@ package com.baeldung.web.util; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; /** * Provides some constants and utility methods to build a Link Header to be stored in the {@link HttpServletResponse} object diff --git a/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java index f26f241beb..1ceb653849 100644 --- a/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java +++ b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java @@ -5,7 +5,7 @@ import static org.hamcrest.Matchers.equalTo; import org.junit.Test; -import com.jayway.restassured.RestAssured; +import io.restassured.RestAssured; public class RequestMappingLiveTest { private static String BASE_URI = "http://localhost:8082/spring-rest/ex/"; From 663d1831daa310ddb355cd2aec41c7e56e70cfda Mon Sep 17 00:00:00 2001 From: MohamedHelmyKassab <137485958+MohamedHelmyKassab@users.noreply.github.com> Date: Fri, 22 Mar 2024 20:15:31 +0200 Subject: [PATCH 63/88] This commit is related to BAEL-6404 (#16201) This commit aims to add a test class "UTF8ToISOUnitTest.java" To convert UTF-8 to ISO-8859-1 in Java. --- .../baeldung/UTF8ToISO/UTF8ToISOUnitTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java new file mode 100644 index 0000000000..f47ea5fdaf --- /dev/null +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/UTF8ToISO/UTF8ToISOUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.UTF8ToISO; + +import org.junit.jupiter.api.Test; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; + +import static org.junit.Assert.assertArrayEquals; + +public class UTF8ToISOUnitTest { + String string = "âabcd"; + byte[] expectedBytes = new byte[]{(byte) 0xE2, 0x61, 0x62, 0x63, 0x64}; + + @Test + public void givenUtf8String_whenUsingGetByte_thenIsoBytesShouldBeEqual() { + byte[] iso88591bytes = string.getBytes(StandardCharsets.ISO_8859_1); + assertArrayEquals(expectedBytes, iso88591bytes); + } + + @Test + public void givenString_whenUsingByteBufferCharBufferConvertToIso_thenBytesShouldBeEqual() { + ByteBuffer inputBuffer = ByteBuffer.wrap(string.getBytes(StandardCharsets.UTF_8)); + CharBuffer data = StandardCharsets.UTF_8.decode(inputBuffer); + ByteBuffer outputBuffer = StandardCharsets.ISO_8859_1.encode(data); + byte[] outputData = new byte[outputBuffer.remaining()]; + outputBuffer.get(outputData); + assertArrayEquals(expectedBytes, outputData); + } +} From 74cd524de2a424e6d412ac385906f0d3c4c380c0 Mon Sep 17 00:00:00 2001 From: sam-gardner <53271849+sam-gardner@users.noreply.github.com> Date: Fri, 22 Mar 2024 20:25:28 +0000 Subject: [PATCH 64/88] JAVA-32103 Move spring-boot-kafka-ssl article to spring-kafka-2 (#16178) --- spring-kafka-2/README.md | 1 + .../spring}/kafka/ssl/KafkaConsumer.java | 9 +++++---- .../spring}/kafka/ssl/KafkaProducer.java | 7 ++++--- .../kafka/ssl/KafkaSslApplication.java | 3 +-- .../src/main/resources/application-ssl.yml | 0 .../ssl/KafkaSslApplicationLiveTest.java | 19 +++++++++--------- .../client-certs/kafka.client.keystore.jks | Bin .../client-certs/kafka.client.truststore.jks | Bin .../docker/certs/kafka.server.keystore.jks | Bin .../docker/certs/kafka.server.truststore.jks | Bin .../docker/certs/kafka_keystore_credentials | 0 .../docker/certs/kafka_sslkey_credentials | 0 .../docker/certs/kafka_truststore_credentials | 0 .../test/resources/docker/docker-compose.yml | 0 spring-kafka/README.md | 1 - 15 files changed, 21 insertions(+), 19 deletions(-) rename {spring-kafka/src/main/java/com/baeldung => spring-kafka-2/src/main/java/com/baeldung/spring}/kafka/ssl/KafkaConsumer.java (94%) rename {spring-kafka/src/main/java/com/baeldung => spring-kafka-2/src/main/java/com/baeldung/spring}/kafka/ssl/KafkaProducer.java (94%) rename {spring-kafka/src/main/java/com/baeldung => spring-kafka-2/src/main/java/com/baeldung/spring}/kafka/ssl/KafkaSslApplication.java (74%) rename {spring-kafka => spring-kafka-2}/src/main/resources/application-ssl.yml (100%) rename {spring-kafka/src/test/java/com/baeldung => spring-kafka-2/src/test/java/com/baeldung/spring}/kafka/ssl/KafkaSslApplicationLiveTest.java (94%) rename {spring-kafka => spring-kafka-2}/src/test/resources/client-certs/kafka.client.keystore.jks (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/client-certs/kafka.client.truststore.jks (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/docker/certs/kafka.server.keystore.jks (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/docker/certs/kafka.server.truststore.jks (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/docker/certs/kafka_keystore_credentials (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/docker/certs/kafka_sslkey_credentials (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/docker/certs/kafka_truststore_credentials (100%) rename {spring-kafka => spring-kafka-2}/src/test/resources/docker/docker-compose.yml (100%) diff --git a/spring-kafka-2/README.md b/spring-kafka-2/README.md index 4dff7ef5db..7dfb05d160 100644 --- a/spring-kafka-2/README.md +++ b/spring-kafka-2/README.md @@ -10,3 +10,4 @@ This module contains articles about Spring with Kafka - [Splitting Streams in Kafka](https://www.baeldung.com/kafka-splitting-streams) - [Manage Kafka Consumer Groups](https://www.baeldung.com/kafka-manage-consumer-groups) - [Dead Letter Queue for Kafka With Spring](https://www.baeldung.com/kafka-spring-dead-letter-queue) +- [Configuring Kafka SSL Using Spring Boot](https://www.baeldung.com/spring-boot-kafka-ssl) diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaConsumer.java b/spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaConsumer.java similarity index 94% rename from spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaConsumer.java rename to spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaConsumer.java index 77df74b6c9..68353312a9 100644 --- a/spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaConsumer.java +++ b/spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaConsumer.java @@ -1,12 +1,13 @@ -package com.baeldung.kafka.ssl; +package com.baeldung.spring.kafka.ssl; + +import java.util.ArrayList; +import java.util.List; -import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; +import lombok.extern.slf4j.Slf4j; @Component @Slf4j diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaProducer.java b/spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaProducer.java similarity index 94% rename from spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaProducer.java rename to spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaProducer.java index 38ce366355..daf5888db0 100644 --- a/spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaProducer.java +++ b/spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaProducer.java @@ -1,9 +1,10 @@ -package com.baeldung.kafka.ssl; +package com.baeldung.spring.kafka.ssl; + +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Component; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.stereotype.Component; @Slf4j @AllArgsConstructor diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaSslApplication.java b/spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaSslApplication.java similarity index 74% rename from spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaSslApplication.java rename to spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaSslApplication.java index b7747ebfef..4e3e4701b1 100644 --- a/spring-kafka/src/main/java/com/baeldung/kafka/ssl/KafkaSslApplication.java +++ b/spring-kafka-2/src/main/java/com/baeldung/spring/kafka/ssl/KafkaSslApplication.java @@ -1,7 +1,6 @@ -package com.baeldung.kafka.ssl; +package com.baeldung.spring.kafka.ssl; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication diff --git a/spring-kafka/src/main/resources/application-ssl.yml b/spring-kafka-2/src/main/resources/application-ssl.yml similarity index 100% rename from spring-kafka/src/main/resources/application-ssl.yml rename to spring-kafka-2/src/main/resources/application-ssl.yml diff --git a/spring-kafka/src/test/java/com/baeldung/kafka/ssl/KafkaSslApplicationLiveTest.java b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/ssl/KafkaSslApplicationLiveTest.java similarity index 94% rename from spring-kafka/src/test/java/com/baeldung/kafka/ssl/KafkaSslApplicationLiveTest.java rename to spring-kafka-2/src/test/java/com/baeldung/spring/kafka/ssl/KafkaSslApplicationLiveTest.java index e05298face..d0fdc0d8cc 100644 --- a/spring-kafka/src/test/java/com/baeldung/kafka/ssl/KafkaSslApplicationLiveTest.java +++ b/spring-kafka-2/src/test/java/com/baeldung/spring/kafka/ssl/KafkaSslApplicationLiveTest.java @@ -1,6 +1,13 @@ -package com.baeldung.kafka.ssl; +package com.baeldung.spring.kafka.ssl; + +import static com.baeldung.spring.kafka.ssl.KafkaConsumer.TOPIC; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +import java.io.File; +import java.time.Duration; +import java.util.UUID; -import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -10,13 +17,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.io.File; -import java.time.Duration; -import java.util.UUID; - -import static com.baeldung.kafka.ssl.KafkaConsumer.TOPIC; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; +import lombok.extern.slf4j.Slf4j; @Slf4j @ActiveProfiles("ssl") diff --git a/spring-kafka/src/test/resources/client-certs/kafka.client.keystore.jks b/spring-kafka-2/src/test/resources/client-certs/kafka.client.keystore.jks similarity index 100% rename from spring-kafka/src/test/resources/client-certs/kafka.client.keystore.jks rename to spring-kafka-2/src/test/resources/client-certs/kafka.client.keystore.jks diff --git a/spring-kafka/src/test/resources/client-certs/kafka.client.truststore.jks b/spring-kafka-2/src/test/resources/client-certs/kafka.client.truststore.jks similarity index 100% rename from spring-kafka/src/test/resources/client-certs/kafka.client.truststore.jks rename to spring-kafka-2/src/test/resources/client-certs/kafka.client.truststore.jks diff --git a/spring-kafka/src/test/resources/docker/certs/kafka.server.keystore.jks b/spring-kafka-2/src/test/resources/docker/certs/kafka.server.keystore.jks similarity index 100% rename from spring-kafka/src/test/resources/docker/certs/kafka.server.keystore.jks rename to spring-kafka-2/src/test/resources/docker/certs/kafka.server.keystore.jks diff --git a/spring-kafka/src/test/resources/docker/certs/kafka.server.truststore.jks b/spring-kafka-2/src/test/resources/docker/certs/kafka.server.truststore.jks similarity index 100% rename from spring-kafka/src/test/resources/docker/certs/kafka.server.truststore.jks rename to spring-kafka-2/src/test/resources/docker/certs/kafka.server.truststore.jks diff --git a/spring-kafka/src/test/resources/docker/certs/kafka_keystore_credentials b/spring-kafka-2/src/test/resources/docker/certs/kafka_keystore_credentials similarity index 100% rename from spring-kafka/src/test/resources/docker/certs/kafka_keystore_credentials rename to spring-kafka-2/src/test/resources/docker/certs/kafka_keystore_credentials diff --git a/spring-kafka/src/test/resources/docker/certs/kafka_sslkey_credentials b/spring-kafka-2/src/test/resources/docker/certs/kafka_sslkey_credentials similarity index 100% rename from spring-kafka/src/test/resources/docker/certs/kafka_sslkey_credentials rename to spring-kafka-2/src/test/resources/docker/certs/kafka_sslkey_credentials diff --git a/spring-kafka/src/test/resources/docker/certs/kafka_truststore_credentials b/spring-kafka-2/src/test/resources/docker/certs/kafka_truststore_credentials similarity index 100% rename from spring-kafka/src/test/resources/docker/certs/kafka_truststore_credentials rename to spring-kafka-2/src/test/resources/docker/certs/kafka_truststore_credentials diff --git a/spring-kafka/src/test/resources/docker/docker-compose.yml b/spring-kafka-2/src/test/resources/docker/docker-compose.yml similarity index 100% rename from spring-kafka/src/test/resources/docker/docker-compose.yml rename to spring-kafka-2/src/test/resources/docker/docker-compose.yml diff --git a/spring-kafka/README.md b/spring-kafka/README.md index 6e495b1210..ed6c3bf8d7 100644 --- a/spring-kafka/README.md +++ b/spring-kafka/README.md @@ -8,7 +8,6 @@ This module contains articles about Spring with Kafka - [Testing Kafka and Spring Boot](https://www.baeldung.com/spring-boot-kafka-testing) - [Monitor the Consumer Lag in Apache Kafka](https://www.baeldung.com/java-kafka-consumer-lag) - [Send Large Messages With Kafka](https://www.baeldung.com/java-kafka-send-large-message) -- [Configuring Kafka SSL Using Spring Boot](https://www.baeldung.com/spring-boot-kafka-ssl) - [Kafka Streams With Spring Boot](https://www.baeldung.com/spring-boot-kafka-streams) - [Get the Number of Messages in an Apache Kafka Topic](https://www.baeldung.com/java-kafka-count-topic-messages) - [Sending Data to a Specific Partition in Kafka](https://www.baeldung.com/kafka-send-data-partition) From 9cc307e108fe4946da81bcfb1e114ed0347b73c5 Mon Sep 17 00:00:00 2001 From: DiegoMarti2 <150871541+DiegoMarti2@users.noreply.github.com> Date: Fri, 22 Mar 2024 23:08:14 +0200 Subject: [PATCH 65/88] baeldung-articles : BAEL-6752 (#16195) * baeldung-articles : BAEL-6752 When to Use Setter Methods or Constructors for Setting a Variable's Value in Java. * baeldung-articles : BAEL-6752 When to Use Setter Methods or Constructors for Setting a Variable's Value in Java. * Updating ConstructorsVersusSetterMethodsUnitTest.java Rename functions --- .../Product.java | 26 ++++++++++++++++ .../constructorversussettermethod/User.java | 31 +++++++++++++++++++ ...nstructorsVersusSetterMethodsUnitTest.java | 30 ++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java create mode 100644 core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java create mode 100644 core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java diff --git a/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java new file mode 100644 index 0000000000..f8c04a3f81 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/Product.java @@ -0,0 +1,26 @@ +package com.baeldung.constructorversussettermethod; + +public class Product { + private String name; + private double price; + private String category; + + public Product(String name, double price, String category) { + this.name = name; + this.price = price; + this.category = category; + } + + public String getName() { + return name; + } + + public double getPrice() { + return price; + } + + public String getCategory() { + return category; + } +} + diff --git a/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java new file mode 100644 index 0000000000..57ec590470 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors-2/src/main/java/com/baeldung/objectcreation/constructorversussettermethod/User.java @@ -0,0 +1,31 @@ +package com.baeldung.constructorversussettermethod; + +public class User { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + if (username.matches("[a-zA-Z0-9_]+")) { + this.username = username; + } else { + throw new IllegalArgumentException("Invalid username format"); + } + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + if (password.length() >= 8) { + this.password = password; + } else { + throw new IllegalArgumentException("Password must be at least 8 characters long"); + } + } +} + diff --git a/core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java b/core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java new file mode 100644 index 0000000000..09294e2232 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-constructors-2/src/test/java/com/baeldung/objectcreation/constructorversussettermethod/ConstructorsVersusSetterMethodsUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.constructorversussettermethod; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ConstructorsVersusSetterMethodsUnitTest { + @Test + public void givenNewUser_whenSettingUsername_thenUsernameIsSet() { + User user = new User(); + user.setUsername("john_doe"); + assertEquals("john_doe", user.getUsername()); + } + + @Test + public void givenNewUser_whenSettingPassword_thenPasswordIsSet() { + User user = new User(); + user.setPassword("strongPassword123"); + assertEquals("strongPassword123", user.getPassword()); + } + + @Test + public void givenProductDetails_whenCreatingProductWithConstructor_thenProductHasCorrectAttributes() { + Product product = new Product("Smartphone", 599.99, "Electronics"); + assertEquals("Smartphone", product.getName()); + assertEquals(599.99, product.getPrice(), 0.001); + assertEquals("Electronics", product.getCategory()); + } +} + From 8bd2ca68939548fbb31d918ae105d6887261e2c8 Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Sat, 23 Mar 2024 17:19:34 +0530 Subject: [PATCH 66/88] JAVA-31602 :- Upgrade spring-boot-mvc-2, spring-boot-mvc-5 to boot 3.2.2 (#16188) * JAVA-31602 :- Upgrade spring-boot-mvc-2, spring-boot-mvc-5 to boot 3.2.2 * JAVA-31602 :- Upgrade spring-boot-mvc-2, spring-boot-mvc-5 to boot 3.2.2 * Revert parent pom to restrict build * JAVA-31602 :- Upgrade spring-boot-mvc-2, spring-boot-mvc-5 to boot 3.2.2 * Fix version error * JAVA-31602 :- Upgrade spring-boot-mvc-2, spring-boot-mvc-5 to boot 3.2.2 * Fix version error * JAVA-31602 :- Upgrade spring-boot-mvc-2, spring-boot-mvc-5 to boot 3.2.2 * Fix version error * Fix version error * Enable in Parent POM * Fix haslength approach --------- Co-authored-by: Amit Pandey --- spring-boot-modules/pom.xml | 2 +- spring-boot-modules/spring-boot-mvc-2/pom.xml | 5 +++++ .../java/com/baeldung/mime/FooController.java | 3 --- .../springbootmvc/ctrl/ProductController.java | 15 +++++---------- .../springbootmvc/svc/ProductService.java | 2 +- .../com/baeldung/students/StudentService.java | 2 +- spring-boot-modules/spring-boot-mvc-5/pom.xml | 13 ++++--------- .../requestwrapper/EscapeHtmlRequestWrapper.java | 11 +++++++++++ .../EscapeHtmlAspectIntegrationTest.java | 2 ++ .../EscapeHtmlFilterIntegrationTest.java | 5 ++++- 10 files changed, 34 insertions(+), 26 deletions(-) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 3be66dc168..873232123b 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -58,7 +58,7 @@ spring-boot-mvc-2 spring-boot-mvc-3 spring-boot-mvc-4 - + spring-boot-mvc-5 spring-boot-mvc-birt spring-boot-mvc-jersey spring-boot-nashorn diff --git a/spring-boot-modules/spring-boot-mvc-2/pom.xml b/spring-boot-modules/spring-boot-mvc-2/pom.xml index bdf9b66a86..b6ac5bdcd7 100644 --- a/spring-boot-modules/spring-boot-mvc-2/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-2/pom.xml @@ -53,6 +53,7 @@ io.rest-assured rest-assured test + ${rest-assured-version} @@ -80,7 +81,11 @@ 3.0.0 com.baeldung.springbootmvc.SpringBootMvcFnApplication + 17 1.4.11.1 + 5.4.0 + 3.2.2 + 5.10.2 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java index b5c0bdad12..c576c3cb1b 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/mime/FooController.java @@ -2,12 +2,9 @@ package com.baeldung.mime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java index 6a77e72cea..351dd2344f 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/ctrl/ProductController.java @@ -4,8 +4,9 @@ import static org.springframework.web.servlet.function.RouterFunctions.route; import static org.springframework.web.servlet.function.ServerResponse.ok; import static org.springframework.web.servlet.function.ServerResponse.status; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.baeldung.springbootmvc.SpringBootMvcFnApplication.Error; +import com.baeldung.springbootmvc.model.Product; +import com.baeldung.springbootmvc.svc.ProductService; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.servlet.function.EntityResponse; @@ -14,10 +15,6 @@ import org.springframework.web.servlet.function.RouterFunction; import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.servlet.function.ServerResponse; -import com.baeldung.springbootmvc.SpringBootMvcFnApplication.Error; -import com.baeldung.springbootmvc.model.Product; -import com.baeldung.springbootmvc.svc.ProductService; - @Component public class ProductController { @@ -27,10 +24,8 @@ public class ProductController { } public RouterFunction productSearch(ProductService ps) { - return route().nest(RequestPredicates.path("/product"), builder -> { - builder.GET("/name/{name}", req -> ok().body(ps.findByName(req.pathVariable("name")))) - .GET("/id/{id}", req -> ok().body(ps.findById(Integer.parseInt(req.pathVariable("id"))))); - }) + return route().nest(RequestPredicates.path("/product"), builder -> builder.GET("/name/{name}", req -> ok().body(ps.findByName(req.pathVariable("name")))) + .GET("/id/{id}", req -> ok().body(ps.findById(Integer.parseInt(req.pathVariable("id")))))) .onError(ProductService.ItemNotFoundException.class, (e, req) -> EntityResponse.fromObject(new Error(e.getMessage())) .status(HttpStatus.NOT_FOUND) .build()) diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java index e2d281d54f..5be5f67a37 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/springbootmvc/svc/ProductService.java @@ -38,7 +38,7 @@ public class ProductService { } public Product save(Product product) { - if (StringUtils.isEmpty(product.getName()) || product.getPrice() == 0.0) { + if (!StringUtils.hasLength(product.getName()) || product.getPrice() == 0.0) { throw new IllegalArgumentException(); } int newId = products.stream() diff --git a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java index 80f6dfd514..f42c61077c 100644 --- a/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java +++ b/spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/students/StudentService.java @@ -19,7 +19,7 @@ public class StudentService { new Student(2, "Sebastian","Bach"), new Student(3, "Pablo","Picasso"), }).stream() - .collect(Collectors.toConcurrentMap(s -> s.getId(), Function.identity())); + .collect(Collectors.toConcurrentMap(Student::getId, Function.identity())); // DB id sequence mock private AtomicLong sequence = new AtomicLong(3); diff --git a/spring-boot-modules/spring-boot-mvc-5/pom.xml b/spring-boot-modules/spring-boot-mvc-5/pom.xml index 10a58a6a59..3a45d58831 100644 --- a/spring-boot-modules/spring-boot-mvc-5/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-5/pom.xml @@ -65,22 +65,17 @@ JAR - - org.apache.maven.plugins - maven-compiler-plugin - - 9 - 9 - - + 3.2.2 + 5.10.2 3.0.0 com.baeldung.springboot.swagger.ArticleApplication - 2021.0.5 + 2023.0.0 1.10 + 17 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java index 66fce3c3e2..1d65b73e8e 100644 --- a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java +++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java @@ -5,6 +5,9 @@ import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.*; +import java.util.Collections; +import java.util.Enumeration; +import org.springframework.http.HttpHeaders; public class EscapeHtmlRequestWrapper extends HttpServletRequestWrapper { private String body = null; @@ -64,4 +67,12 @@ public class EscapeHtmlRequestWrapper extends HttpServletRequestWrapper { public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(this.getInputStream())); } + + @Override + public Enumeration getHeaders(String name) { + if(HttpHeaders.CONTENT_LENGTH.equals(name)) { + return Collections.enumeration(Collections.singletonList(String.valueOf(body.length()))); + } + return super.getHeaders(name); + } } diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java index ef18591ccb..fe212bf6b1 100644 --- a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -45,6 +46,7 @@ public class EscapeHtmlAspectIntegrationTest { mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save")) .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_LENGTH, 100) .content(objectMapper.writeValueAsString(requestBody))) .andExpect(MockMvcResultMatchers.status() .isCreated()) diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java index c813827422..ff37cb6217 100644 --- a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java @@ -1,5 +1,6 @@ package com.baeldung.modifyrequest; +import com.baeldung.modifyrequest.config.WebMvcConfiguration; import com.baeldung.modifyrequest.controller.UserController; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; @@ -9,6 +10,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -21,7 +23,7 @@ import java.util.Map; @ExtendWith(SpringExtension.class) @AutoConfigureMockMvc -@WebMvcTest(UserController.class) +@WebMvcTest(value ={UserController.class, WebMvcConfiguration.class}) @ActiveProfiles("filterExample") public class EscapeHtmlFilterIntegrationTest { Logger logger = LoggerFactory.getLogger(EscapeHtmlFilterIntegrationTest.class); @@ -44,6 +46,7 @@ public class EscapeHtmlFilterIntegrationTest { mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save")) .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.CONTENT_LENGTH, "100") .content(objectMapper.writeValueAsString(requestBody))).andExpect(MockMvcResultMatchers.status() .isCreated()).andExpect(MockMvcResultMatchers.content() .json(objectMapper.writeValueAsString(expectedResponseBody))); From 429b4700e8b09d965efc94d3dd3bcfe7fff99bed Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Sat, 23 Mar 2024 17:43:07 +0530 Subject: [PATCH 67/88] JAVA-32517 Upgrade parent-spring-6 to latest version of Spring (#16179) --- parent-spring-6/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parent-spring-6/pom.xml b/parent-spring-6/pom.xml index 4665030baf..1d0d54d398 100644 --- a/parent-spring-6/pom.xml +++ b/parent-spring-6/pom.xml @@ -35,7 +35,7 @@ - 6.1.2 + 6.1.5 2023.0.0 3.2.1 From f63ea849184539815b1d7b69503579e54c557819 Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Sat, 23 Mar 2024 17:52:50 +0530 Subject: [PATCH 68/88] JAVA-31640 :- Upgrade Spring Boot Data (#16207) Co-authored-by: Amit Pandey --- spring-boot-modules/spring-boot-data/pom.xml | 2 ++ .../src/main/resources/application.properties | 1 + .../jsondateformat/ContactAppIntegrationTest.java | 8 ++++---- ...ntactAppWithObjectMapperCustomizerIntegrationTest.java | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/spring-boot-modules/spring-boot-data/pom.xml b/spring-boot-modules/spring-boot-data/pom.xml index 5c76035a3a..b0dffa3f6d 100644 --- a/spring-boot-modules/spring-boot-data/pom.xml +++ b/spring-boot-modules/spring-boot-data/pom.xml @@ -157,6 +157,8 @@ + 3.2.2 + 5.10.2 2.2.4 19 com.baeldung.SpringBootDataApplication diff --git a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties index cee5701cb5..7ad6ca058f 100644 --- a/spring-boot-modules/spring-boot-data/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-data/src/main/resources/application.properties @@ -6,5 +6,6 @@ spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password= +spring.main.allow-bean-definition-overriding=true diff --git a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java index cb2aee8cdf..435b12b000 100644 --- a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java @@ -44,7 +44,7 @@ public class ContactAppIntegrationTest { public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -59,7 +59,7 @@ public class ContactAppIntegrationTest { public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/javaUtilDate", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -74,7 +74,7 @@ public class ContactAppIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plainWithJavaUtilDate", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -89,7 +89,7 @@ public class ContactAppIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plain", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); diff --git a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java index c5c57c2973..dfe1ba3baf 100644 --- a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -38,7 +38,7 @@ public class ContactAppWithObjectMapperCustomizerIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plainWithJavaUtilDate", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); @@ -53,7 +53,7 @@ public class ContactAppWithObjectMapperCustomizerIntegrationTest { public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plain", String.class); - assertEquals(200, response.getStatusCodeValue()); + assertEquals(200, response.getStatusCode().value()); List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); From 5f9eed3b36f51c9b77fac21e42b765842122eb47 Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Sat, 23 Mar 2024 18:31:13 +0530 Subject: [PATCH 69/88] JAVA-32167 Fix references to parent- Week 11 (#16128) --- .../quarkus-vs-springboot/spring-project/pom.xml | 14 +++++++++++--- .../spring-boot-documentation/pom.xml | 14 -------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml index fc24b43497..f087fbba6b 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml @@ -7,9 +7,9 @@ 0.1-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 3.1.3 + com.baeldung + quarkus-vs-springboot + 1.0-SNAPSHOT @@ -21,6 +21,13 @@ pom import + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + @@ -93,6 +100,7 @@ 17 1.17.2 1.0.2 + 3.1.3 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-documentation/pom.xml b/spring-boot-modules/spring-boot-documentation/pom.xml index a941ca36e6..cb50ebe40f 100644 --- a/spring-boot-modules/spring-boot-documentation/pom.xml +++ b/spring-boot-modules/spring-boot-documentation/pom.xml @@ -18,20 +18,6 @@ - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - org.springframework.boot spring-boot-starter From f277f6195e37b403e8ed18ea23f6f1fd0e66c54d Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Sun, 24 Mar 2024 15:36:18 +0200 Subject: [PATCH 70/88] [JAVA-28950] upgrade spring-credhub to spring-boot 3 (#16198) --- spring-credhub/pom.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spring-credhub/pom.xml b/spring-credhub/pom.xml index f257d549bf..0065269bc2 100644 --- a/spring-credhub/pom.xml +++ b/spring-credhub/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -37,8 +37,7 @@ - 2.2.0 - UTF-8 + 3.1.0 \ No newline at end of file From 8dcc7d156928d99a85033c70ded2be084070cb5b Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Sun, 24 Mar 2024 19:18:22 +0530 Subject: [PATCH 71/88] JAVA-31500 :- Upgrade spring-data-redis to Spring Boot 3 (#16057) --- persistence-modules/spring-data-redis/pom.xml | 16 +++++++++++----- .../data/reactive/redis/config/RedisConfig.java | 4 ++-- .../spring/data/redis/config/RedisConfig.java | 4 ++-- .../spring/data/redis/model/Student.java | 2 ++ .../data/redis/queue/RedisMessageSubscriber.java | 2 +- .../template/RedisKeyCommandsManualTest.java | 4 ++-- .../template/RedisTemplateListOpsManualTest.java | 4 ++-- .../RedisTemplateValueOpsManualTest.java | 4 ++-- .../redis/repo/StudentRepositoryManualTest.java | 12 ++++++------ 9 files changed, 30 insertions(+), 22 deletions(-) diff --git a/persistence-modules/spring-data-redis/pom.xml b/persistence-modules/spring-data-redis/pom.xml index 382cdf83f5..9e3903a587 100644 --- a/persistence-modules/spring-data-redis/pom.xml +++ b/persistence-modules/spring-data-redis/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -72,12 +72,17 @@ org.apache.maven.plugins maven-surefire-plugin - true - false 0 -Xmx1024m + + org.apache.maven.plugins + maven-compiler-plugin + + true + + @@ -85,7 +90,8 @@ 3.2.4 0.10.0 0.6 - 5.0.2 + 4.3.2 + com.baeldung.spring.data.redis.SpringRedisApplication \ No newline at end of file diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java index de8e447ef8..7fa82e8f19 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java @@ -14,7 +14,7 @@ import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Configuration public class RedisConfig { @@ -45,7 +45,7 @@ public class RedisConfig { @PreDestroy public void cleanRedis() { - factory.getConnection() + factory.getConnection().serverCommands() .flushDb(); } } diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java index 7fd13d2777..0d7bbe963d 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java @@ -29,9 +29,9 @@ public class RedisConfig { @Bean public RedisTemplate redisTemplate() { - final RedisTemplate template = new RedisTemplate(); + final RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory()); - template.setValueSerializer(new GenericToStringSerializer(Object.class)); + template.setValueSerializer(new GenericToStringSerializer<>(Object.class)); return template; } diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java index b97ed23387..9da785c158 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java @@ -2,9 +2,11 @@ package com.baeldung.spring.data.redis.model; import java.io.Serializable; +import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisHash; @RedisHash("Student") +@RequiredArgsConstructor public class Student implements Serializable { public enum Gender { diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java index 849e1fb59f..90f2a9d8af 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java @@ -10,7 +10,7 @@ import java.util.List; @Service public class RedisMessageSubscriber implements MessageListener { - public static List messageList = new ArrayList(); + public static List messageList = new ArrayList<>(); public void onMessage(final Message message, final byte[] pattern) { messageList.add(message.toString()); diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java index 2aabe099ea..37b1d9bd54 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java @@ -37,13 +37,13 @@ public class RedisKeyCommandsManualTest { private ReactiveStringCommands stringCommands; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java index 7353b9630c..9569a360fe 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java @@ -34,13 +34,13 @@ public class RedisTemplateListOpsManualTest { private ReactiveListOperations reactiveListOps; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 128M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java index af8e41f9e8..df33d362f9 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java @@ -37,13 +37,13 @@ public class RedisTemplateValueOpsManualTest { private ReactiveValueOperations reactiveValueOps; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java index a2b62167a1..8950b582e8 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java @@ -33,18 +33,18 @@ public class StudentRepositoryManualTest { private static redis.embedded.RedisServer redisServer; @BeforeClass - public static void startRedisServer() throws IOException { + public static void startRedisServer() { redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 128M").build(); redisServer.start(); } @AfterClass - public static void stopRedisServer() throws IOException { + public static void stopRedisServer() { redisServer.stop(); } @Test - public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception { + public void whenSavingStudent_thenAvailableOnRetrieval() { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); studentRepository.save(student); final Student retrievedStudent = studentRepository.findById(student.getId()).get(); @@ -52,7 +52,7 @@ public class StudentRepositoryManualTest { } @Test - public void whenUpdatingStudent_thenAvailableOnRetrieval() throws Exception { + public void whenUpdatingStudent_thenAvailableOnRetrieval() { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); studentRepository.save(student); student.setName("Richard Watson"); @@ -62,7 +62,7 @@ public class StudentRepositoryManualTest { } @Test - public void whenSavingStudents_thenAllShouldAvailableOnRetrieval() throws Exception { + public void whenSavingStudents_thenAllShouldAvailableOnRetrieval() { final Student engStudent = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); final Student medStudent = new Student("Med2015001", "Gareth Houston", Student.Gender.MALE, 2); studentRepository.save(engStudent); @@ -73,7 +73,7 @@ public class StudentRepositoryManualTest { } @Test - public void whenDeletingStudent_thenNotAvailableOnRetrieval() throws Exception { + public void whenDeletingStudent_thenNotAvailableOnRetrieval() { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); studentRepository.save(student); studentRepository.deleteById(student.getId()); From ff12386947722dc15575b05c604ab8e75dcba422 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Sun, 24 Mar 2024 23:19:00 +0700 Subject: [PATCH 72/88] [JAVA-32056] Upgrade spring-mvc-java-3 to Boot 3 (#16161) --- spring-web-modules/spring-mvc-java-3/pom.xml | 14 ++++++++++---- .../filters/CacheRequestContentFilter.java | 6 +++--- .../com/baeldung/filters/HttpRequestUnitTest.java | 10 +++++----- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/spring-web-modules/spring-mvc-java-3/pom.xml b/spring-web-modules/spring-mvc-java-3/pom.xml index 4d669c7e7b..5999f6b118 100644 --- a/spring-web-modules/spring-mvc-java-3/pom.xml +++ b/spring-web-modules/spring-mvc-java-3/pom.xml @@ -11,15 +11,16 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api + ${jakarta.version} org.springframework @@ -37,4 +38,9 @@ + + 6.1.0-M2 + com.baeldung.Main + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-java-3/src/main/java/com/baeldung/filters/CacheRequestContentFilter.java b/spring-web-modules/spring-mvc-java-3/src/main/java/com/baeldung/filters/CacheRequestContentFilter.java index 907ec24700..b6f313c829 100644 --- a/spring-web-modules/spring-mvc-java-3/src/main/java/com/baeldung/filters/CacheRequestContentFilter.java +++ b/spring-web-modules/spring-mvc-java-3/src/main/java/com/baeldung/filters/CacheRequestContentFilter.java @@ -2,9 +2,9 @@ package com.baeldung.filters; import org.springframework.web.util.ContentCachingRequestWrapper; -import javax.servlet.*; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter(urlPatterns = "/*") diff --git a/spring-web-modules/spring-mvc-java-3/src/test/java/com/baeldung/filters/HttpRequestUnitTest.java b/spring-web-modules/spring-mvc-java-3/src/test/java/com/baeldung/filters/HttpRequestUnitTest.java index cd369d9118..b4a2751ea6 100644 --- a/spring-web-modules/spring-mvc-java-3/src/test/java/com/baeldung/filters/HttpRequestUnitTest.java +++ b/spring-web-modules/spring-mvc-java-3/src/test/java/com/baeldung/filters/HttpRequestUnitTest.java @@ -1,16 +1,16 @@ package com.baeldung.filters; +import jakarta.servlet.Filter; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.web.util.ContentCachingRequestWrapper; -import javax.servlet.Filter; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; From 17cb4108d4a62e15a609ef3ea7bbc980865165dc Mon Sep 17 00:00:00 2001 From: Mo Helmy <135069400+BenHelmyBen@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:08:17 +0200 Subject: [PATCH 73/88] This PR is related to BAEL-7427 (#16028) * This commit is related to BAEL-7427 This commit aims to add a Main class. * This commit is related to BAEL-7427 This commit aims to add a myFile.gz file to the resources folder. * This commit is related to BAEL-7427 This commit aims to add a test class "ReadingGZIPUsingGZIPInputStreamUnitTest". * This commit is related to BAEL-7427 This commit aims to add a myFile.gz file to the resources folder. * Update Main.java * Update ReadingGZIPUsingGZIPInputStreamUnitTest.java * Update Main.java * Update ReadingGZIPUsingGZIPInputStreamUnitTest.java * Update ReadingGZIPUsingGZIPInputStreamUnitTest.java * Update Main.java * Update Main.java * Update ReadingGZIPUsingGZIPInputStreamUnitTest.java * Update Main.java * Update ReadingGZIPUsingGZIPInputStreamUnitTest.java * Update Main.java * Update ReadingGZIPUsingGZIPInputStreamUnitTest.java * Update Main.java --- .../baeldung/usinggzipInputstream/Main.java | 73 ++++++++++++++++++ .../src/main/resources/myFile.gz | Bin 0 -> 43 bytes ...adingGZIPUsingGZIPInputStreamUnitTest.java | 50 ++++++++++++ .../src/test/resources/myFile.gz | Bin 0 -> 43 bytes 4 files changed, 123 insertions(+) create mode 100644 core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java create mode 100644 core-java-modules/core-java-io-5/src/main/resources/myFile.gz create mode 100644 core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java create mode 100644 core-java-modules/core-java-io-5/src/test/resources/myFile.gz diff --git a/core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java b/core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java new file mode 100644 index 0000000000..7065352be7 --- /dev/null +++ b/core-java-modules/core-java-io-5/src/main/java/com/baeldung/usinggzipInputstream/Main.java @@ -0,0 +1,73 @@ +package com.baeldung.usinggzipInputstream; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.zip.GZIPInputStream; + +import static java.util.stream.Collectors.toList; + +public class Main { + static String filePath = Objects.requireNonNull(Main.class.getClassLoader().getResource("myFile.gz")).getFile(); + + public static void main(String[] args) throws IOException { + // Test readGZipFile method + List fileContents = readGZipFile(filePath); + System.out.println("Contents of GZIP file:"); + fileContents.forEach(System.out::println); + + // Test findInZipFile method + String searchTerm = "Line 1 content"; + List foundLines = findInZipFile(filePath, searchTerm); + System.out.println("Lines containing '" + searchTerm + "' in GZIP file:"); + foundLines.forEach(System.out::println); + + + // Test useContentsOfZipFile method + System.out.println("Using contents of GZIP file with consumer:"); + useContentsOfZipFile(filePath, linesStream -> { + linesStream.filter(line -> line.length() > 10).forEach(System.out::println); + }); + } + + + public static List readGZipFile(String filePath) throws IOException { + List lines = new ArrayList<>(); + try (InputStream inputStream = new FileInputStream(filePath); + GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + String line; + while ((line = bufferedReader.readLine()) != null) { + lines.add(line); + } + } + + return lines; + } + + public static List findInZipFile(String filePath, String toFind) throws IOException { + try (InputStream inputStream = new FileInputStream(filePath); + GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + return bufferedReader.lines().filter(line -> line.contains(toFind)).collect(toList()); + } + } + + public static void useContentsOfZipFile(String filePath, Consumer> consumer) throws IOException { + try (InputStream inputStream = new FileInputStream(filePath); + GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + consumer.accept(bufferedReader.lines()); + } + } + +} diff --git a/core-java-modules/core-java-io-5/src/main/resources/myFile.gz b/core-java-modules/core-java-io-5/src/main/resources/myFile.gz new file mode 100644 index 0000000000000000000000000000000000000000..47c3ad1e1bf21509aad3565310817853ec643c24 GIT binary patch literal 43 vcmb2|=3oGW|DR8u@eVZz@i=#0+w-jU!%vKby#YIq8R#(_ynNJC2dD-BT*DB2 literal 0 HcmV?d00001 diff --git a/core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java new file mode 100644 index 0000000000..51814f4581 --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/usinggzipInputstream/ReadingGZIPUsingGZIPInputStreamUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.usinggzipInputstream; + +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +public class ReadingGZIPUsingGZIPInputStreamUnitTest { + String testFilePath = Objects.requireNonNull(ReadingGZIPUsingGZIPInputStreamUnitTest.class.getClassLoader().getResource("myFile.gz")).getFile(); + List expectedFilteredLines = Arrays.asList("Line 1 content", "Line 2 content", "Line 3 content"); + + @Test + void givenGZFile_whenUsingGZIPInputStream_thenReadLines() throws IOException { + try (Stream lines = Main.readGZipFile(testFilePath).stream()) { + List result = lines + .filter(expectedFilteredLines::contains) + .collect(Collectors.toList()); + + assertEquals(expectedFilteredLines, result); + } + } + + @Test + void givenGZFile_whenUsingtestFindInZipFile_thenReadLines() throws IOException { + String toFind = "Line 1 content"; + + List result = Main.findInZipFile(testFilePath, toFind); + + assertEquals("Line 1 content", result.get(0)); + + } + + @Test + void givenGZFile_whenUsingContentsOfZipFile_thenReadLines() throws IOException { + AtomicInteger count = new AtomicInteger(0); + + Main.useContentsOfZipFile(testFilePath, linesStream -> { + linesStream.filter(line -> line.length() > 10).forEach(line -> count.incrementAndGet()); + }); + + assertEquals(3, count.get()); + } +} diff --git a/core-java-modules/core-java-io-5/src/test/resources/myFile.gz b/core-java-modules/core-java-io-5/src/test/resources/myFile.gz new file mode 100644 index 0000000000000000000000000000000000000000..47c3ad1e1bf21509aad3565310817853ec643c24 GIT binary patch literal 43 vcmb2|=3oGW|DR8u@eVZz@i=#0+w-jU!%vKby#YIq8R#(_ynNJC2dD-BT*DB2 literal 0 HcmV?d00001 From 42b9fb45983b9180de1ad765feaaee7d9b1c1b31 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Sun, 24 Mar 2024 23:53:37 +0100 Subject: [PATCH 74/88] [JAVA-32171] Fix missing pom.xml (#16196) --- aws-modules/aws-reactive/pom.xml | 1 + maven-modules/pom.xml | 3 +++ maven-modules/version-overriding-plugins/pom.xml | 1 + .../version-overriding-child-a/pom.xml | 1 + microservices-modules/micronaut/pom.xml | 2 ++ patterns-modules/enterprise-patterns/pom.xml | 1 + patterns-modules/intercepting-filter/pom.xml | 2 ++ patterns-modules/monkey-patching/pom.xml | 7 ++++++- persistence-modules/spring-boot-persistence-2/pom.xml | 1 + persistence-modules/spring-boot-persistence-3/pom.xml | 1 + server-modules/undertow/pom.xml | 1 + server-modules/wildfly/pom.xml | 1 + spf4j/spf4j-aspects-app/pom.xml | 1 + spf4j/spf4j-core-app/pom.xml | 1 + tensorflow-java/pom.xml | 2 ++ web-modules/blade/pom.xml | 1 + web-modules/dropwizard/pom.xml | 2 ++ 17 files changed, 28 insertions(+), 1 deletion(-) diff --git a/aws-modules/aws-reactive/pom.xml b/aws-modules/aws-reactive/pom.xml index 7a425c44b4..0ff255d960 100644 --- a/aws-modules/aws-reactive/pom.xml +++ b/aws-modules/aws-reactive/pom.xml @@ -87,6 +87,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.version} diff --git a/maven-modules/pom.xml b/maven-modules/pom.xml index 2be1309c25..956ae917ac 100644 --- a/maven-modules/pom.xml +++ b/maven-modules/pom.xml @@ -84,4 +84,7 @@ + + 3.1.0 + \ No newline at end of file diff --git a/maven-modules/version-overriding-plugins/pom.xml b/maven-modules/version-overriding-plugins/pom.xml index d38541d797..1f3106df3b 100644 --- a/maven-modules/version-overriding-plugins/pom.xml +++ b/maven-modules/version-overriding-plugins/pom.xml @@ -30,6 +30,7 @@ maven-resources-plugin + ${maven-resources-plugin.version} diff --git a/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml b/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml index 48b5782f72..e54768b5c3 100644 --- a/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml +++ b/maven-modules/version-overriding-plugins/version-overriding-child-a/pom.xml @@ -16,6 +16,7 @@ maven-resources-plugin + ${maven-resources-plugin.version} diff --git a/microservices-modules/micronaut/pom.xml b/microservices-modules/micronaut/pom.xml index fa73a15ac4..641b23d5e6 100644 --- a/microservices-modules/micronaut/pom.xml +++ b/microservices-modules/micronaut/pom.xml @@ -101,6 +101,7 @@ io.micronaut.build micronaut-maven-plugin + ${micronaut-build.version} org.apache.maven.plugins @@ -154,6 +155,7 @@ jar 3.12.1 netty + 3.5.4 3.2.0 diff --git a/patterns-modules/enterprise-patterns/pom.xml b/patterns-modules/enterprise-patterns/pom.xml index a3c9da448d..45da43ba6f 100644 --- a/patterns-modules/enterprise-patterns/pom.xml +++ b/patterns-modules/enterprise-patterns/pom.xml @@ -52,6 +52,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-boot.version} diff --git a/patterns-modules/intercepting-filter/pom.xml b/patterns-modules/intercepting-filter/pom.xml index 60246e7838..949695afed 100644 --- a/patterns-modules/intercepting-filter/pom.xml +++ b/patterns-modules/intercepting-filter/pom.xml @@ -39,6 +39,7 @@ org.eclipse.jetty jetty-maven-plugin + ${jetty-plugin.version} / @@ -50,6 +51,7 @@ 3.3.2 + 11.0.20 \ No newline at end of file diff --git a/patterns-modules/monkey-patching/pom.xml b/patterns-modules/monkey-patching/pom.xml index e7fae87646..1d0146d990 100644 --- a/patterns-modules/monkey-patching/pom.xml +++ b/patterns-modules/monkey-patching/pom.xml @@ -29,7 +29,7 @@ org.springframework.boot spring-boot-starter-aop - 2.7.0 + ${spring-boot.version} @@ -38,7 +38,12 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-boot.version} + + + 2.7.0 + diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml index 9b22e6902c..0937e76fa1 100644 --- a/persistence-modules/spring-boot-persistence-2/pom.xml +++ b/persistence-modules/spring-boot-persistence-2/pom.xml @@ -124,6 +124,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.boot.dependencies} diff --git a/persistence-modules/spring-boot-persistence-3/pom.xml b/persistence-modules/spring-boot-persistence-3/pom.xml index fd4d354c78..2684d4dcd2 100644 --- a/persistence-modules/spring-boot-persistence-3/pom.xml +++ b/persistence-modules/spring-boot-persistence-3/pom.xml @@ -55,6 +55,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.boot.dependencies} diff --git a/server-modules/undertow/pom.xml b/server-modules/undertow/pom.xml index a73771485c..8baf69c88a 100644 --- a/server-modules/undertow/pom.xml +++ b/server-modules/undertow/pom.xml @@ -32,6 +32,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven-jar-plugin.version} diff --git a/server-modules/wildfly/pom.xml b/server-modules/wildfly/pom.xml index fece3c9866..bc02f42b98 100644 --- a/server-modules/wildfly/pom.xml +++ b/server-modules/wildfly/pom.xml @@ -51,6 +51,7 @@ maven-failsafe-plugin + ${maven-failsafe-plugin.version} diff --git a/spf4j/spf4j-aspects-app/pom.xml b/spf4j/spf4j-aspects-app/pom.xml index 9769ff77f3..df3b0ee551 100644 --- a/spf4j/spf4j-aspects-app/pom.xml +++ b/spf4j/spf4j-aspects-app/pom.xml @@ -77,6 +77,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven-jar-plugin.version} diff --git a/spf4j/spf4j-core-app/pom.xml b/spf4j/spf4j-core-app/pom.xml index ee82ea869a..665b37583c 100644 --- a/spf4j/spf4j-core-app/pom.xml +++ b/spf4j/spf4j-core-app/pom.xml @@ -83,6 +83,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven-jar-plugin.version} diff --git a/tensorflow-java/pom.xml b/tensorflow-java/pom.xml index 4dd86d45e3..888588efe5 100644 --- a/tensorflow-java/pom.xml +++ b/tensorflow-java/pom.xml @@ -28,12 +28,14 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-maven-plugin.version} 1.12.0 + 3.2.2 \ No newline at end of file diff --git a/web-modules/blade/pom.xml b/web-modules/blade/pom.xml index fb0ca13dbe..2748c05663 100644 --- a/web-modules/blade/pom.xml +++ b/web-modules/blade/pom.xml @@ -62,6 +62,7 @@ org.apache.maven.plugins maven-failsafe-plugin + ${maven-failsafe-plugin.version} true diff --git a/web-modules/dropwizard/pom.xml b/web-modules/dropwizard/pom.xml index 03562acded..a1cc17f5bf 100644 --- a/web-modules/dropwizard/pom.xml +++ b/web-modules/dropwizard/pom.xml @@ -27,6 +27,7 @@ org.apache.maven.plugins maven-shade-plugin + ${maven-shade-plugin.version} true @@ -64,6 +65,7 @@ 2.0.0 + 3.5.0 \ No newline at end of file From e0a6bc2da39ed3b166ecf2fd09ec09ced6135e39 Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Mon, 25 Mar 2024 04:38:15 +0530 Subject: [PATCH 75/88] [JAVA-29007] - Upgrade Spring Reactive exceptions (#16208) --- spring-reactive-modules/spring-reactive-exceptions/pom.xml | 6 ++++++ .../spring/reactive/customexception/model/ErrorDetails.java | 6 +++--- .../customexception/controller/UserControllerUnitTest.java | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/spring-reactive-modules/spring-reactive-exceptions/pom.xml b/spring-reactive-modules/spring-reactive-exceptions/pom.xml index 1f24f9cd1c..8cde579ddb 100644 --- a/spring-reactive-modules/spring-reactive-exceptions/pom.xml +++ b/spring-reactive-modules/spring-reactive-exceptions/pom.xml @@ -61,4 +61,10 @@ + + 3.2.2 + 5.10.2 + 17 + + diff --git a/spring-reactive-modules/spring-reactive-exceptions/src/main/java/com/baeldung/spring/reactive/customexception/model/ErrorDetails.java b/spring-reactive-modules/spring-reactive-exceptions/src/main/java/com/baeldung/spring/reactive/customexception/model/ErrorDetails.java index a4ca566c71..357998dda1 100644 --- a/spring-reactive-modules/spring-reactive-exceptions/src/main/java/com/baeldung/spring/reactive/customexception/model/ErrorDetails.java +++ b/spring-reactive-modules/spring-reactive-exceptions/src/main/java/com/baeldung/spring/reactive/customexception/model/ErrorDetails.java @@ -11,11 +11,11 @@ public enum ErrorDetails { API_USER_NOT_FOUND(123, "User not found", "http://example.com/123"); @Getter - private Integer errorCode; + private final Integer errorCode; @Getter - private String errorMessage; + private final String errorMessage; @Getter - private String referenceUrl; + private final String referenceUrl; ErrorDetails(Integer errorCode, String errorMessage, String referenceUrl) { this.errorCode = errorCode; diff --git a/spring-reactive-modules/spring-reactive-exceptions/src/test/java/com/baeldung/spring/reactive/customexception/controller/UserControllerUnitTest.java b/spring-reactive-modules/spring-reactive-exceptions/src/test/java/com/baeldung/spring/reactive/customexception/controller/UserControllerUnitTest.java index 150d0b08a6..c4306e6e62 100644 --- a/spring-reactive-modules/spring-reactive-exceptions/src/test/java/com/baeldung/spring/reactive/customexception/controller/UserControllerUnitTest.java +++ b/spring-reactive-modules/spring-reactive-exceptions/src/test/java/com/baeldung/spring/reactive/customexception/controller/UserControllerUnitTest.java @@ -1,6 +1,6 @@ package com.baeldung.spring.reactive.customexception.controller; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @@ -55,7 +55,7 @@ class UserControllerUnitTest { // Then assertNotNull(problemDetail); assertNotNull(problemDetail.getProperties().get("errors")); - List errors = (List) problemDetail.getProperties().get("errors"); + List> errors = (List>) problemDetail.getProperties().get("errors"); assertEquals(ErrorDetails.API_USER_NOT_FOUND.getErrorCode().toString(), errors.get(0).get("code")); assertEquals(ErrorDetails.API_USER_NOT_FOUND.getErrorMessage().toString(), From 7c0faeef8647c6182a33451d32b949d2423648e6 Mon Sep 17 00:00:00 2001 From: sachin <56427366+sachin071287@users.noreply.github.com> Date: Mon, 25 Mar 2024 04:57:58 +0530 Subject: [PATCH 76/88] Prototype Scoped Bean With Runtime Arguments (#15936) * Prototype Scoped Bean With Runtime Arguments * Prototype Scoped Bean With Runtime Arguments --------- Co-authored-by: Sachin kumar --- .../dynamicarguments/Employee.java | 26 ++++++++++ .../EmployeeBeanUsingFunction.java | 17 +++++++ .../EmployeeBeanUsingLookUp.java | 14 ++++++ .../EmployeeBeanUsingObjectFactory.java | 14 ++++++ .../EmployeeBeanUsingObjectProvider.java | 14 ++++++ .../dynamicarguments/EmployeeConfig.java | 39 +++++++++++++++ .../dynamicarguments/DynamicBeanUnitTest.java | 48 +++++++++++++++++++ 7 files changed, 172 insertions(+) create mode 100644 spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/Employee.java create mode 100644 spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingFunction.java create mode 100644 spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingLookUp.java create mode 100644 spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectFactory.java create mode 100644 spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectProvider.java create mode 100644 spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeConfig.java create mode 100644 spring-di-4/src/test/java/com/baeldung/prototypebean/dynamicarguments/DynamicBeanUnitTest.java diff --git a/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/Employee.java b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/Employee.java new file mode 100644 index 0000000000..01eeb97936 --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/Employee.java @@ -0,0 +1,26 @@ +package com.baeldung.prototypebean.dynamicarguments; + +public class Employee { + + private String name; + + public Employee() { + } + + public Employee(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void printName() { + System.out.println(name); + } + +} diff --git a/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingFunction.java b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingFunction.java new file mode 100644 index 0000000000..02c283214c --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingFunction.java @@ -0,0 +1,17 @@ +package com.baeldung.prototypebean.dynamicarguments; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cglib.core.internal.Function; +import org.springframework.stereotype.Component; + +@Component +public class EmployeeBeanUsingFunction { + + @Autowired + private Function beanFactory; + + public Employee getEmployee(String name) { + Employee employee = beanFactory.apply(name); + return employee; + } +} diff --git a/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingLookUp.java b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingLookUp.java new file mode 100644 index 0000000000..2bdcc41e89 --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingLookUp.java @@ -0,0 +1,14 @@ +package com.baeldung.prototypebean.dynamicarguments; + +import org.springframework.beans.factory.annotation.Lookup; +import org.springframework.stereotype.Component; + +@Component +public class EmployeeBeanUsingLookUp { + + @Lookup + public Employee getEmployee(String arg) { + return null; + } + +} diff --git a/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectFactory.java b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectFactory.java new file mode 100644 index 0000000000..4fcb90de59 --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectFactory.java @@ -0,0 +1,14 @@ +package com.baeldung.prototypebean.dynamicarguments; + +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.annotation.Autowired; + +public class EmployeeBeanUsingObjectFactory { + + @Autowired + private ObjectFactory employeeObjectFactory; + + public Employee getEmployee() { + return employeeObjectFactory.getObject(); + } +} \ No newline at end of file diff --git a/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectProvider.java b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectProvider.java new file mode 100644 index 0000000000..e04f98278c --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeBeanUsingObjectProvider.java @@ -0,0 +1,14 @@ +package com.baeldung.prototypebean.dynamicarguments; + +import org.springframework.beans.factory.annotation.Autowired; + +public class EmployeeBeanUsingObjectProvider { + + @Autowired + private org.springframework.beans.factory.ObjectProvider objectProvider; + + public Employee getEmployee(String name) { + Employee employee = objectProvider.getObject(name); + return employee; + } +} diff --git a/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeConfig.java b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeConfig.java new file mode 100644 index 0000000000..ebbd68a22b --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/prototypebean/dynamicarguments/EmployeeConfig.java @@ -0,0 +1,39 @@ +package com.baeldung.prototypebean.dynamicarguments; + +import org.springframework.cglib.core.internal.Function; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.prototypebean.dynamicarguments" }) +public class EmployeeConfig { + + @Bean + @Scope(value = "prototype") + public Employee getEmployee(String name) { + return new Employee(name); + } + + @Bean + public EmployeeBeanUsingObjectProvider employeeBeanUsingObjectProvider() { + return new EmployeeBeanUsingObjectProvider(); + } + + @Bean + public EmployeeBeanUsingObjectFactory employeeBeanUsingObjectFactory() { + return new EmployeeBeanUsingObjectFactory(); + } + + @Bean + public Function beanFactory() { + return name -> getEmployee(name); + } + + @Bean + public EmployeeBeanUsingFunction employeeBeanUsingFunction() { + return new EmployeeBeanUsingFunction(); + } + +} diff --git a/spring-di-4/src/test/java/com/baeldung/prototypebean/dynamicarguments/DynamicBeanUnitTest.java b/spring-di-4/src/test/java/com/baeldung/prototypebean/dynamicarguments/DynamicBeanUnitTest.java new file mode 100644 index 0000000000..0c6e6a7658 --- /dev/null +++ b/spring-di-4/src/test/java/com/baeldung/prototypebean/dynamicarguments/DynamicBeanUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.prototypebean.dynamicarguments; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import junit.framework.Assert; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = EmployeeConfig.class) +public class DynamicBeanUnitTest { + + @Test + public void givenPrototypeBean_WhenFunction_ThenNewInstanceReturn() { + + AbstractApplicationContext context = new AnnotationConfigApplicationContext(EmployeeConfig.class); + EmployeeBeanUsingFunction firstContext = context.getBean(EmployeeBeanUsingFunction.class); + EmployeeBeanUsingFunction secondContext = context.getBean(EmployeeBeanUsingFunction.class); + Employee firstInstance = firstContext.getEmployee("sachin"); + Employee secondInstance = secondContext.getEmployee("kumar"); + Assert.assertTrue(firstInstance != secondInstance); + } + + @Test + public void givenPrototypeBean_WhenLookup_ThenNewInstanceReturn() { + + AbstractApplicationContext context = new AnnotationConfigApplicationContext(EmployeeConfig.class); + EmployeeBeanUsingLookUp firstContext = context.getBean(EmployeeBeanUsingLookUp.class); + EmployeeBeanUsingLookUp secondContext = context.getBean(EmployeeBeanUsingLookUp.class); + Employee firstInstance = firstContext.getEmployee("sachin"); + Employee secondInstance = secondContext.getEmployee("kumar"); + Assert.assertTrue(firstInstance != secondInstance); + } + + @Test + public void givenPrototypeBean_WhenObjectProvider_ThenNewInstanceReturn() { + AbstractApplicationContext context = new AnnotationConfigApplicationContext(EmployeeConfig.class); + EmployeeBeanUsingObjectProvider firstContext = context.getBean(EmployeeBeanUsingObjectProvider.class); + EmployeeBeanUsingObjectProvider secondContext = context.getBean(EmployeeBeanUsingObjectProvider.class); + Employee firstInstance = firstContext.getEmployee("sachin"); + Employee secondInstance = secondContext.getEmployee("kumar"); + Assert.assertTrue(firstInstance != secondInstance); + } +} From 8d8acb9117d9f5047ab4d2ccb47aead3d2f4431d Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Mon, 25 Mar 2024 23:51:56 +0200 Subject: [PATCH 77/88] [JAVA-31614] (#16224) --- spring-boot-modules/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 873232123b..b5fcb33ef7 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -101,7 +101,7 @@ spring-boot-resilience4j spring-boot-properties spring-boot-properties-2 - + spring-boot-properties-3 spring-boot-properties-4 spring-boot-properties-migrator-demo spring-boot-aws From 0facf5ca65b18d5e5eb00eaccb655322b40b062e Mon Sep 17 00:00:00 2001 From: anuragkumawat Date: Tue, 26 Mar 2024 03:25:56 +0530 Subject: [PATCH 78/88] [JAVA-27762] Upgrade spring-reactive-3 to boot-3 (#16214) --- .../spring-reactive-3/pom.xml | 13 +++++++++--- .../websocket/WebSocketController.java | 4 ++-- .../DataBufferToInputStreamUnitTest.java | 21 +++++++------------ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/spring-reactive-modules/spring-reactive-3/pom.xml b/spring-reactive-modules/spring-reactive-3/pom.xml index 15cf80fda1..dc821b111d 100644 --- a/spring-reactive-modules/spring-reactive-3/pom.xml +++ b/spring-reactive-modules/spring-reactive-3/pom.xml @@ -10,9 +10,10 @@ spring sample project about new features - com.baeldung.spring.reactive - spring-reactive-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -74,6 +75,11 @@ kotlin-stdlib ${kotlin-stdlib.version} + + commons-io + commons-io + ${commons-io.version} + @@ -93,6 +99,7 @@ 2021.0.4 5.0.0-alpha.12 2.0.0-Beta4 + com.baeldung.custom.deserialization.Application \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/websocket/WebSocketController.java b/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/websocket/WebSocketController.java index 0c8f9debc9..22f602df86 100644 --- a/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/websocket/WebSocketController.java +++ b/spring-reactive-modules/spring-reactive-3/src/main/java/com/baeldung/websocket/WebSocketController.java @@ -3,8 +3,8 @@ package com.baeldung.websocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.websocket.*; -import javax.websocket.server.ServerEndpoint; +import jakarta.websocket.*; +import jakarta.websocket.server.ServerEndpoint; import java.io.IOException; @ServerEndpoint("/event-emitter") diff --git a/spring-reactive-modules/spring-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java b/spring-reactive-modules/spring-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java index 975a2d8698..b6660e4214 100644 --- a/spring-reactive-modules/spring-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java +++ b/spring-reactive-modules/spring-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java @@ -1,11 +1,15 @@ package com.baeldung.databuffer; -import com.baeldung.databuffer.DataBufferToInputStream; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import io.restassured.internal.util.IOUtils; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.stream.Collectors; +import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.http.HttpStatus; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ExchangeFunction; @@ -13,17 +17,6 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - class DataBufferToInputStreamUnitTest { private String getResponseStub() throws IOException { InputStream inputStream = null; From c75b4b13fa54b915d7750bd6402a741b7ec9f90f Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:06:53 +0200 Subject: [PATCH 79/88] [JAVA-31545] (#16222) --- spring-boot-modules/pom.xml | 4 ++-- .../{spring-caching-2 => spring-boot-caching-2}/README.md | 1 + .../{spring-caching-2 => spring-boot-caching-2}/pom.xml | 0 .../java/com/baeldung/allkeys/config/AllKeysConfig.java | 0 .../baeldung/allkeys/service/SlowServiceWithCache.java | 0 .../main/java/com/baeldung/caching/redis/CacheConfig.java | 0 .../src/main/java/com/baeldung/caching/redis/Item.java | 0 .../java/com/baeldung/caching/redis/ItemController.java | 0 .../java/com/baeldung/caching/redis/ItemRepository.java | 0 .../main/java/com/baeldung/caching/redis/ItemService.java | 0 .../com/baeldung/caching/redis/RedisCacheApplication.java | 0 .../com/baeldung/caching/ttl/CachingTTLApplication.java | 0 .../baeldung/caching/ttl/config/SpringCachingConfig.java | 0 .../baeldung/caching/ttl/controller/HotelController.java | 0 .../baeldung/caching/ttl/exception/ControllerAdvisor.java | 0 .../caching/ttl/exception/ElementNotFoundException.java | 0 .../main/java/com/baeldung/caching/ttl/model/City.java | 0 .../main/java/com/baeldung/caching/ttl/model/Hotel.java | 0 .../baeldung/caching/ttl/repository/CityRepository.java | 0 .../baeldung/caching/ttl/repository/HotelRepository.java | 0 .../com/baeldung/caching/ttl/service/HotelService.java | 0 .../caching/ttl/service/SpringCacheCustomizer.java | 0 .../com/baeldung/caching/twolevelcache/CacheConfig.java | 0 .../java/com/baeldung/caching/twolevelcache/Customer.java | 0 .../caching/twolevelcache/CustomerCacheInterceptor.java | 0 .../caching/twolevelcache/CustomerRepository.java | 0 .../baeldung/caching/twolevelcache/CustomerService.java | 0 .../caching/twolevelcache/TwoLevelCacheApplication.java | 0 .../src/main/resources/application.properties | 0 .../src/main/resources/data.sql | 0 .../allkeys/boot/GetAllCacheKeysIntegrationTest.java | 0 .../caching/redis/ItemServiceCachingIntegrationTest.java | 0 .../caching/ttl/HotelControllerIntegrationTest.java | 0 .../src/test/java/com/baeldung/caching/ttl/SlowTest.java | 0 .../CustomerServiceCachingIntegrationTest.java | 0 .../src/test/resources/application.properties | 0 .../{spring-caching => spring-boot-caching}/README.md | 1 + .../{spring-caching => spring-boot-caching}/pom.xml | 8 +++----- .../src/main/java/com/baeldung/cachetest/Application.java | 0 .../java/com/baeldung/cachetest/config/CacheConfig.java | 0 .../com/baeldung/cachetest/config/CacheEventLogger.java | 0 .../com/baeldung/cachetest/rest/NumberController.java | 0 .../com/baeldung/cachetest/service/NumberService.java | 0 .../java/com/baeldung/caching/boot/CacheApplication.java | 0 .../com/baeldung/caching/boot/SimpleCacheCustomizer.java | 0 .../baeldung/caching/config/ApplicationCacheConfig.java | 0 .../java/com/baeldung/caching/config/CachingConfig.java | 0 .../com/baeldung/caching/config/CustomKeyGenerator.java | 0 .../caching/eviction/controllers/CachingController.java | 0 .../baeldung/caching/eviction/service/CachingService.java | 0 .../com/baeldung/caching/example/AbstractService.java | 0 .../java/com/baeldung/caching/example/BookService.java | 0 .../main/java/com/baeldung/caching/example/Customer.java | 0 .../com/baeldung/caching/example/CustomerDataService.java | 0 .../caching/example/CustomerServiceWithParent.java | 0 .../src/main/java/com/baeldung/caching/model/Book.java | 0 .../baeldung/ehcache/calculator/SquaredCalculator.java | 0 .../java/com/baeldung/ehcache/config/CacheHelper.java | 0 .../multiplecachemanager/bo/CustomerDetailBO.java | 0 .../baeldung/multiplecachemanager/bo/OrderDetailBO.java | 0 .../config/MultipleCacheManagerConfig.java | 0 .../config/MultipleCacheResolver.java | 0 .../controller/MultipleCacheManagerController.java | 0 .../baeldung/multiplecachemanager/entity/Customer.java | 0 .../com/baeldung/multiplecachemanager/entity/Item.java | 0 .../com/baeldung/multiplecachemanager/entity/Order.java | 0 .../repository/CustomerDetailRepository.java | 0 .../repository/OrderDetailRepository.java | 0 .../java/com/baeldung/springdatacaching/model/Book.java | 0 .../springdatacaching/repositories/BookRepository.java | 0 .../src/main/resources/application.properties | 0 .../src/main/resources/config.xml | 0 .../src/main/resources/data.sql | 0 .../src/main/resources/ehcache.xml | 0 .../src/main/resources/logback.xml | 0 .../src/main/resources/schema.sql | 0 .../boot/SimpleCacheCustomizerIntegrationTest.java | 0 .../caching/test/CacheEvictAnnotationIntegrationTest.java | 0 .../caching/test/CacheManagerEvictIntegrationTest.java | 0 .../caching/test/SpringCachingIntegrationTest.java | 0 .../com/baeldung/ehcache/SquareCalculatorUnitTest.java | 0 .../MultipleCacheManagerIntegrationTest.java | 0 .../BookRepositoryCachingIntegrationTest.java | 0 .../repositories/BookRepositoryIntegrationTest.java | 0 84 files changed, 7 insertions(+), 7 deletions(-) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/README.md (85%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/pom.xml (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/redis/CacheConfig.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/redis/Item.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/redis/ItemController.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/redis/ItemRepository.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/redis/ItemService.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/model/City.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/model/Hotel.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/service/HotelService.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/twolevelcache/Customer.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/resources/application.properties (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/main/resources/data.sql (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/test/java/com/baeldung/caching/ttl/SlowTest.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching-2 => spring-boot-caching-2}/src/test/resources/application.properties (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/README.md (89%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/pom.xml (92%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/cachetest/Application.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/cachetest/config/CacheConfig.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/cachetest/rest/NumberController.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/cachetest/service/NumberService.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/boot/CacheApplication.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/config/CachingConfig.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/eviction/service/CachingService.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/example/AbstractService.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/example/BookService.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/example/Customer.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/example/CustomerDataService.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/caching/model/Book.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/ehcache/config/CacheHelper.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/springdatacaching/model/Book.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/resources/application.properties (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/resources/config.xml (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/resources/data.sql (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/resources/ehcache.xml (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/resources/logback.xml (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/main/resources/schema.sql (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java (100%) rename spring-boot-modules/{spring-caching => spring-boot-caching}/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java (100%) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index b5fcb33ef7..00d6405cbf 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -27,6 +27,8 @@ spring-boot-basic-customization spring-boot-basic-customization-2 spring-boot-bootstrap + spring-boot-caching + spring-boot-caching-2 spring-boot-client spring-boot-config-jpa-error spring-boot-ctx-fluent @@ -86,8 +88,6 @@ spring-boot-data-2 spring-boot-validation - - spring-boot-cassandre spring-boot-react diff --git a/spring-boot-modules/spring-caching-2/README.md b/spring-boot-modules/spring-boot-caching-2/README.md similarity index 85% rename from spring-boot-modules/spring-caching-2/README.md rename to spring-boot-modules/spring-boot-caching-2/README.md index fffdacdfb2..a2b0c41c63 100644 --- a/spring-boot-modules/spring-caching-2/README.md +++ b/spring-boot-modules/spring-boot-caching-2/README.md @@ -3,4 +3,5 @@ - [Setting Time-To-Live Value for Caching](https://www.baeldung.com/spring-setting-ttl-value-cache) - [Get All Cached Keys with Caffeine Cache in Spring Boot](https://www.baeldung.com/spring-boot-caffeine-spring-get-all-keys) - [Implement Two-Level Cache With Spring](https://www.baeldung.com/spring-two-level-cache) +- More articles: [[<-- prev]](/spring-boot-modules/spring-boot-caching) diff --git a/spring-boot-modules/spring-caching-2/pom.xml b/spring-boot-modules/spring-boot-caching-2/pom.xml similarity index 100% rename from spring-boot-modules/spring-caching-2/pom.xml rename to spring-boot-modules/spring-boot-caching-2/pom.xml diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/config/AllKeysConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/allkeys/service/SlowServiceWithCache.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/Item.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/Item.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/CachingTTLApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/config/SpringCachingConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/controller/HotelController.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ControllerAdvisor.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/exception/ElementNotFoundException.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/City.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/model/Hotel.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/CityRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/repository/HotelRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/HotelService.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/ttl/service/SpringCacheCustomizer.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java b/spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java rename to spring-boot-modules/spring-boot-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-caching-2/src/main/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-caching-2/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-caching-2/src/main/resources/data.sql b/spring-boot-modules/spring-boot-caching-2/src/main/resources/data.sql similarity index 100% rename from spring-boot-modules/spring-caching-2/src/main/resources/data.sql rename to spring-boot-modules/spring-boot-caching-2/src/main/resources/data.sql diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/allkeys/boot/GetAllCacheKeysIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/HotelControllerIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/ttl/SlowTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/test/resources/application.properties b/spring-boot-modules/spring-boot-caching-2/src/test/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-caching-2/src/test/resources/application.properties rename to spring-boot-modules/spring-boot-caching-2/src/test/resources/application.properties diff --git a/spring-boot-modules/spring-caching/README.md b/spring-boot-modules/spring-boot-caching/README.md similarity index 89% rename from spring-boot-modules/spring-caching/README.md rename to spring-boot-modules/spring-boot-caching/README.md index e10d6080e8..1690be8f47 100644 --- a/spring-boot-modules/spring-caching/README.md +++ b/spring-boot-modules/spring-boot-caching/README.md @@ -6,3 +6,4 @@ - [Using Multiple Cache Managers in Spring](https://www.baeldung.com/spring-multiple-cache-managers) - [Testing @Cacheable on Spring Data Repositories](https://www.baeldung.com/spring-data-testing-cacheable) - [Spring Boot Ehcache Example](https://www.baeldung.com/spring-boot-ehcache) +- More articles: [[next -->]](/spring-boot-modules/spring-boot-caching-2) \ No newline at end of file diff --git a/spring-boot-modules/spring-caching/pom.xml b/spring-boot-modules/spring-boot-caching/pom.xml similarity index 92% rename from spring-boot-modules/spring-caching/pom.xml rename to spring-boot-modules/spring-boot-caching/pom.xml index 5b4dde6e8b..36fbe6ef27 100644 --- a/spring-boot-modules/spring-caching/pom.xml +++ b/spring-boot-modules/spring-boot-caching/pom.xml @@ -9,10 +9,9 @@ war - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT @@ -49,7 +48,6 @@ com.github.ben-manes.caffeine caffeine - ${caffeine.version} com.h2database diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/Application.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/Application.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/Application.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/Application.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/rest/NumberController.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/cachetest/service/NumberService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/ApplicationCacheConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CustomKeyGenerator.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/controllers/CachingController.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/eviction/service/CachingService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/AbstractService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/AbstractService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/AbstractService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/AbstractService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/BookService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/BookService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/BookService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/BookService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/Customer.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/Customer.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/Customer.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/Customer.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerDataService.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/example/CustomerServiceWithParent.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/model/Book.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/model/Book.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/caching/model/Book.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/model/Book.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/calculator/SquaredCalculator.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/ehcache/config/CacheHelper.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java diff --git a/spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java b/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java similarity index 100% rename from spring-boot-modules/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java rename to spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java diff --git a/spring-boot-modules/spring-caching/src/main/resources/application.properties b/spring-boot-modules/spring-boot-caching/src/main/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-caching/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-caching/src/main/resources/config.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/config.xml similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/config.xml rename to spring-boot-modules/spring-boot-caching/src/main/resources/config.xml diff --git a/spring-boot-modules/spring-caching/src/main/resources/data.sql b/spring-boot-modules/spring-boot-caching/src/main/resources/data.sql similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/data.sql rename to spring-boot-modules/spring-boot-caching/src/main/resources/data.sql diff --git a/spring-boot-modules/spring-caching/src/main/resources/ehcache.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/ehcache.xml similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/ehcache.xml rename to spring-boot-modules/spring-boot-caching/src/main/resources/ehcache.xml diff --git a/spring-boot-modules/spring-caching/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/logback.xml similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/logback.xml rename to spring-boot-modules/spring-boot-caching/src/main/resources/logback.xml diff --git a/spring-boot-modules/spring-caching/src/main/resources/schema.sql b/spring-boot-modules/spring-boot-caching/src/main/resources/schema.sql similarity index 100% rename from spring-boot-modules/spring-caching/src/main/resources/schema.sql rename to spring-boot-modules/spring-boot-caching/src/main/resources/schema.sql diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheEvictAnnotationIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/CacheManagerEvictIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/caching/test/SpringCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/ehcache/SquareCalculatorUnitTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java b/spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java similarity index 100% rename from spring-boot-modules/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java rename to spring-boot-modules/spring-boot-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java From 443512391896198f62c1629715298ba7449ca849 Mon Sep 17 00:00:00 2001 From: DiegoMarti2 <150871541+DiegoMarti2@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:07:55 +0200 Subject: [PATCH 80/88] baeldung-articles : BAEL-7644 (#16211) * baeldung-articles : BAEL-7644 Include null value in JSON serialization (Main) * baeldung-articles : BAEL-7644 Include null value in JSON serialization (Test). --- .../baeldung/includenullinjson/Customer.java | 27 +++++++++++++++++ .../IncludeNullValuesInJsonUnitTest.java | 30 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 json-modules/json-conversion/src/main/java/com/baeldung/includenullinjson/Customer.java create mode 100644 json-modules/json-conversion/src/test/java/com/baeldung/includenullinjson/IncludeNullValuesInJsonUnitTest.java diff --git a/json-modules/json-conversion/src/main/java/com/baeldung/includenullinjson/Customer.java b/json-modules/json-conversion/src/main/java/com/baeldung/includenullinjson/Customer.java new file mode 100644 index 0000000000..50855e16e9 --- /dev/null +++ b/json-modules/json-conversion/src/main/java/com/baeldung/includenullinjson/Customer.java @@ -0,0 +1,27 @@ +package com.baeldung.includenullinjson; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Customer { + @JsonProperty + private final String name; + @JsonProperty + private final String address; + @JsonProperty + private final int age; + + public Customer(String name, String address, int age) { + this.name = name; + this.address = address; + this.age = age; + } + + @Override + public String toString() { + return "Customer{" + + "name='" + name + '\'' + + ", address='" + address + '\'' + + ", age=" + age + + '}'; + } +} \ No newline at end of file diff --git a/json-modules/json-conversion/src/test/java/com/baeldung/includenullinjson/IncludeNullValuesInJsonUnitTest.java b/json-modules/json-conversion/src/test/java/com/baeldung/includenullinjson/IncludeNullValuesInJsonUnitTest.java new file mode 100644 index 0000000000..eb0d51b900 --- /dev/null +++ b/json-modules/json-conversion/src/test/java/com/baeldung/includenullinjson/IncludeNullValuesInJsonUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.includenullinjson; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class IncludeNullValuesInJsonUnitTest { + String expectedJson = "{\"name\":\"John\",\"address\":null,\"age\":25}"; + Customer obj = new Customer("John", null, 25); + + @Test + public void givenObjectWithNullField_whenJacksonUsed_thenIncludesNullValue() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); + String json = mapper.writeValueAsString(obj); + assertEquals(expectedJson, json); + } + + @Test + public void givenObjectWithNullField_whenGsonUsed_thenIncludesNullValue() { + Gson gson = new GsonBuilder().serializeNulls().create(); + String json = gson.toJson(obj); + assertEquals(expectedJson, json); + } +} From 5fbc3a252b26a027a3719d07f36aaaf05ef3878e Mon Sep 17 00:00:00 2001 From: sam-gardner <53271849+sam-gardner@users.noreply.github.com> Date: Mon, 25 Mar 2024 22:12:47 +0000 Subject: [PATCH 81/88] [JAVA-28949] Upgrade spring-native to spring-boot 3 (#16229) --- spring-native/pom-nativeimage.xml | 80 ++++++++----------------------- 1 file changed, 19 insertions(+), 61 deletions(-) diff --git a/spring-native/pom-nativeimage.xml b/spring-native/pom-nativeimage.xml index 4fc01e4574..08ceb09a8a 100644 --- a/spring-native/pom-nativeimage.xml +++ b/spring-native/pom-nativeimage.xml @@ -10,76 +10,41 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 - spring-release - Spring release - https://repo.spring.io/release + spring-milestone + Spring Milestone + https://repo.spring.io/milestone + + + spring-snapshot + Spring Snapshot + https://repo.spring.io/snapshot - spring-release - Spring release - https://repo.spring.io/release + spring-plugins-snapshot + Spring Plugins Snapshot + https://repo.spring.io/plugins-snapshot org.springframework.boot - spring-boot-starter-parent + spring-boot-starter ${spring-boot.version} - pom - - - org.springframework.experimental - spring-native - ${spring-native.version} - - - org.springframework.experimental - spring-aot - ${spring-native.version} - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.springframework.experimental - spring-aot-maven-plugin - ${spring-native.version} - - - test-generate - - test-generate - - - - generate - - generate - - - - - - - - + native @@ -92,28 +57,21 @@ build-native - build + compile-no-fork package - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - 2.7.1 - 0.12.1 - 0.9.17 + 3.2.0 + 17 + 0.10.1 From 4912f824c90c51196ce34a4396970b3d062f6a91 Mon Sep 17 00:00:00 2001 From: Mikhail Polivakha <68962645+Mikhail2048@users.noreply.github.com> Date: Tue, 26 Mar 2024 01:15:07 +0300 Subject: [PATCH 82/88] BAEL-6174 (#16213) --- .../hibernate-annotations/pom.xml | 12 ++++ .../config/HibernateAnnotationUtil.java | 2 + .../subselect/RuntimeConfiguration.java | 43 ++++++++++++ .../main/resources/migrations/V1__init.xml | 55 ++++++++++++++++ .../src/main/resources/migrations/master.xml | 7 ++ .../subselect/SubselectIntegrationTest.java | 65 +++++++++++++++++++ 6 files changed, 184 insertions(+) create mode 100644 persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java create mode 100644 persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml create mode 100644 persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml create mode 100644 persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java diff --git a/persistence-modules/hibernate-annotations/pom.xml b/persistence-modules/hibernate-annotations/pom.xml index 6f11888643..12a5298e95 100644 --- a/persistence-modules/hibernate-annotations/pom.xml +++ b/persistence-modules/hibernate-annotations/pom.xml @@ -81,6 +81,16 @@ hypersistence-utils-hibernate-60 ${hypersistance-utils-hibernate-60.version} + + org.liquibase + liquibase-core + ${liquibase-core.version} + + + org.projectlombok + lombok + ${lombok.version} + @@ -91,6 +101,8 @@ true 9.0.0.M26 3.3.1 + 1.18.30 + 4.24.0 \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java index 99410e1f76..0bf03e3fee 100644 --- a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java @@ -4,6 +4,7 @@ import com.baeldung.hibernate.oneToMany.model.Cart; import com.baeldung.hibernate.oneToMany.model.CartOIO; import com.baeldung.hibernate.oneToMany.model.Item; import com.baeldung.hibernate.oneToMany.model.ItemOIO; +import com.baeldung.hibernate.subselect.RuntimeConfiguration; import org.hibernate.SessionFactory; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; @@ -38,6 +39,7 @@ public class HibernateAnnotationUtil { .addAnnotatedClass(CartOIO.class) .addAnnotatedClass(Item.class) .addAnnotatedClass(ItemOIO.class) + .addAnnotatedClass(RuntimeConfiguration.class) .buildMetadata(); return metadata.buildSessionFactory(); diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java new file mode 100644 index 0000000000..0f995bfe03 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java @@ -0,0 +1,43 @@ +package com.baeldung.hibernate.subselect; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import java.time.Instant; +import lombok.Data; +import lombok.experimental.Accessors; +import org.hibernate.annotations.Subselect; + +@Data +@Accessors(chain = true) +@Entity +// language=sql +@Subselect(value = + "SELECT\n" + + " ss.id,\n" + + " ss.attr_key,\n" + + " ss.val,\n" + + " ss.created_at\n" + + " FROM system_settings AS ss\n" + + " INNER JOIN (\n" + + " SELECT\n" + + " ss2.attr_key as k2,\n" + + " MAX(ss2.created_at) as ca2\n" + + " FROM system_settings ss2\n" + + " GROUP BY ss2.attr_key\n" + + " ) AS t ON t.k2 = ss.attr_key AND t.ca2 = ss.created_at\n" + + " WHERE ss.type = 'SYSTEM' AND ss.active IS TRUE\n") +public class RuntimeConfiguration { + + @Id + private Long id; + + @Column(name = "attr_key") + private String key; + + @Column(name = "val") + private String value; + + @Column(name = "created_at") + private Instant createdAt; +} diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml b/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml new file mode 100644 index 0000000000..5970821ccd --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + splitting.enabled + true + true + SYSTEM + + + + + 2 + splitting.enabled + false + false + SYSTEM + + + + + 3 + redelivery.enabled + false + true + ORDER + + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml b/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml new file mode 100644 index 0000000000..ba16dc7b8b --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java new file mode 100644 index 0000000000..074468ca37 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.hibernate.subselect; + +import com.baeldung.hibernate.oneToMany.config.HibernateAnnotationUtil; +import jakarta.persistence.criteria.Root; +import liquibase.Contexts; +import liquibase.LabelExpression; +import liquibase.Liquibase; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.LiquibaseException; +import liquibase.resource.ClassLoaderResourceAccessor; +import org.hibernate.Session; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class SubselectIntegrationTest { + + @BeforeAll + static void setUp() { + Session currentSession = HibernateAnnotationUtil.getSessionFactory().getCurrentSession(); + currentSession.beginTransaction(); + + currentSession.doWork(it -> { + Liquibase liquibase; + try { + liquibase = new Liquibase( + "migrations/master.xml", + new ClassLoaderResourceAccessor(), + DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(it)) + ); + liquibase.update(new Contexts(), new LabelExpression(),true); + } catch (LiquibaseException e) { + throw new RuntimeException(e); + } + }); + + currentSession.getTransaction().commit(); + } + + @Test + void givenEntityMarkedWithSubselect_whenSelectingRuntimeConfigByKey_thenSelectedSuccessfully() { + String key = "splitting.enabled"; + Session entityManager = HibernateAnnotationUtil.getSessionFactory().getCurrentSession(); + + entityManager.beginTransaction(); + + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + + CriteriaQuery query = criteriaBuilder.createQuery(RuntimeConfiguration.class); + + Root root = query.from(RuntimeConfiguration.class); + + RuntimeConfiguration configurationParameter = entityManager.createQuery( + query.select(root).where(criteriaBuilder.equal(root.get("key"), key)) + ).getSingleResult(); + + entityManager.getTransaction().commit(); + + Assertions.assertThat(configurationParameter.getValue()).isEqualTo("true"); + } +} + From 452cdc58c9e8bd42987d5f1e4feff9fa97533a6d Mon Sep 17 00:00:00 2001 From: MohamedHelmyKassab <137485958+MohamedHelmyKassab@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:18:39 +0200 Subject: [PATCH 83/88] This commit is related to BAEL-6972 (#16217) This commit aims to add two classes Child and Parent. --- .../com/baeldung/statementsbeforesuper/Child.java | 14 ++++++++++++++ .../com/baeldung/statementsbeforesuper/Parent.java | 11 +++++++++++ 2 files changed, 25 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java create mode 100644 core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java new file mode 100644 index 0000000000..6b8fda032c --- /dev/null +++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Child.java @@ -0,0 +1,14 @@ +package com.baeldung.statementsbeforesuper; + +class Child extends Parent { + Child() { + super(); // Or super(10); Correct placements + System.out.println("Child constructor"); + additionalInitialization(); + // super(); Compilation error: Constructor call must be the first statement in a constructor + } + + private void additionalInitialization() { + System.out.println("Additional initialization in Child"); + } +} diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java new file mode 100644 index 0000000000..38ed9ecd1a --- /dev/null +++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/statementsbeforesuper/Parent.java @@ -0,0 +1,11 @@ +package com.baeldung.statementsbeforesuper; + +public class Parent { + public Parent(int id) { + System.out.println("Parametrized Parent constructor"); + } + + public Parent() { + System.out.println("Parent constructor"); + } +} \ No newline at end of file From 76c1a02aa83d3a19b32d725d51a5affcb56aafba Mon Sep 17 00:00:00 2001 From: vunamtien Date: Tue, 26 Mar 2024 05:20:02 +0700 Subject: [PATCH 84/88] [JAVA-30997] upgrade spring-boot-mvc to boot 3 (#16190) * [JAVA-30997] upgrade spring-boot-mvc to boot 3 * [JAVA-30997] upgrade spring-boot-mvc to boot 3 --- spring-boot-modules/pom.xml | 2 +- spring-boot-modules/spring-boot-mvc/pom.xml | 12 +++++++----- .../components/AttrListener.java | 6 +++--- .../components/EchoServlet.java | 9 +++++---- .../components/HelloFilter.java | 7 ++++--- .../components/HelloServlet.java | 13 +++++++------ .../InternationalizationApp.java | 2 +- .../responseentity/CustomResponseController.java | 3 +-- .../restvalidation/config/MessageConfig.java | 3 +-- .../RecursiveLocaleContextMessageInterpolator.java | 3 +-- .../com/baeldung/restvalidation/service1/User.java | 3 +-- .../restvalidation/service1/UserService1.java | 3 +-- .../com/baeldung/restvalidation/service2/User.java | 3 +-- .../restvalidation/service2/UserService2.java | 3 +-- .../restvalidation/service3/FieldNotEmpty.java | 5 +++-- .../service3/FieldNotEmptyValidator.java | 4 ++-- .../restvalidation/service3/UserService3.java | 3 +-- .../src/main/java/com/baeldung/rss/RssFeedView.java | 5 ++--- .../MySQLAutoconfiguration.java | 2 +- .../com/baeldung/springbootmvc/LoginController.java | 3 +-- .../jsfapplication/JsfApplication.java | 3 +-- .../com/baeldung/springbootmvc/model/LoginForm.java | 6 +++--- .../main/resources/ValidationMessages.properties | 2 +- .../main/resources/ValidationMessages_zh.properties | 2 +- .../spring-boot-mvc/src/main/webapp/WEB-INF/web.xml | 2 +- ...ringBootWithServletComponentIntegrationTest.java | 5 ++--- ...gBootWithoutServletComponentIntegrationTest.java | 5 ++--- 27 files changed, 56 insertions(+), 63 deletions(-) diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 00d6405cbf..2b62b3d1bc 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -56,7 +56,7 @@ spring-boot-process-automation spring-boot-logging-logback spring-boot-logging-log4j2 - + spring-boot-mvc spring-boot-mvc-2 spring-boot-mvc-3 spring-boot-mvc-4 diff --git a/spring-boot-modules/spring-boot-mvc/pom.xml b/spring-boot-modules/spring-boot-mvc/pom.xml index ab1c867d66..ec084df714 100644 --- a/spring-boot-modules/spring-boot-mvc/pom.xml +++ b/spring-boot-modules/spring-boot-mvc/pom.xml @@ -52,8 +52,8 @@ org.glassfish - javax.faces - ${javax.faces.version} + jakarta.faces + ${jakarta.faces.version} @@ -73,8 +73,9 @@ hibernate-validator - javax.validation - validation-api + jakarta.validation + jakarta.validation-api + ${jakarta.validation-api.version} org.springframework.boot @@ -112,8 +113,9 @@ 1.10.0 - 2.3.7 + 4.1.0-M1 1.9.20.1 + 3.1.0-M1 com.baeldung.springbootmvc.SpringBootMvcApplication diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java index b1bdc7d781..049fcc986f 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java @@ -1,8 +1,8 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.annotation.WebListener; @WebListener public class AttrListener implements ServletContextListener { diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java index d8192c2cb1..89b948ba87 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java @@ -1,9 +1,10 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + import java.io.File; import java.io.IOException; import java.nio.file.Files; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java index 146e5ae386..f6472174a2 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java @@ -1,8 +1,9 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.*; -import javax.servlet.annotation.WebFilter; -import javax.servlet.annotation.WebInitParam; +import jakarta.servlet.*; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.annotation.WebInitParam; + import java.io.IOException; @WebFilter(urlPatterns = "/hello", description = "a filter for hello servlet", initParams = { @WebInitParam(name = "msg", value = "filtering ") }, filterName = "hello filter", servletNames = { "echo servlet" }) diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java index 5269c1bf29..8caa798e76 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java @@ -1,11 +1,12 @@ package com.baeldung.annotation.servletcomponentscan.components; -import javax.servlet.ServletConfig; -import javax.servlet.annotation.WebInitParam; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.annotation.WebInitParam; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + import java.io.IOException; @WebServlet(urlPatterns = "/hello", initParams = { @WebInitParam(name = "msg", value = "hello") }) diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java index c3af611f3b..2fdd79d060 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/internationalization/InternationalizationApp.java @@ -1,7 +1,7 @@ package com.baeldung.internationalization; -import javax.annotation.security.RolesAllowed; +import jakarta.annotation.security.RolesAllowed; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java index 098c5e4794..19246e3014 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/responseentity/CustomResponseController.java @@ -3,8 +3,7 @@ package com.baeldung.responseentity; import java.io.IOException; import java.time.Year; -import javax.servlet.http.HttpServletResponse; - +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java index e37e2c9d78..c0bfd641d4 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/MessageConfig.java @@ -1,7 +1,6 @@ package com.baeldung.restvalidation.config; -import javax.validation.MessageInterpolator; - +import jakarta.validation.MessageInterpolator; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java index 003a3d79b0..a81c19148a 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/config/RecursiveLocaleContextMessageInterpolator.java @@ -4,8 +4,7 @@ import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.validation.MessageInterpolator; - +import jakarta.validation.MessageInterpolator; import org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java index f9a7d1a9b5..eff81f6dda 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/User.java @@ -1,7 +1,6 @@ package com.baeldung.restvalidation.service1; -import javax.validation.constraints.NotEmpty; - +import jakarta.validation.constraints.NotEmpty; import lombok.*; @Data diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java index 790b5031e6..6883e539f8 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service1/UserService1.java @@ -1,5 +1,6 @@ package com.baeldung.restvalidation.service1; +import jakarta.validation.Valid; import org.springframework.http.*; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; @@ -7,8 +8,6 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.stream.Collectors; -import javax.validation.Valid; - import com.baeldung.restvalidation.response.InputFieldError; import com.baeldung.restvalidation.response.UpdateUserResponse; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java index a2e567766c..dd9584e27b 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/User.java @@ -1,7 +1,6 @@ package com.baeldung.restvalidation.service2; -import javax.validation.constraints.NotEmpty; - +import jakarta.validation.constraints.NotEmpty; import lombok.*; @Data diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java index 4593a2b1bd..78ec60720d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service2/UserService2.java @@ -3,8 +3,7 @@ package com.baeldung.restvalidation.service2; import java.util.List; import java.util.stream.Collectors; -import javax.validation.Valid; - +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java index 93c7052d5b..03392af45c 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmpty.java @@ -1,5 +1,8 @@ package com.baeldung.restvalidation.service3; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; @@ -12,8 +15,6 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; @Documented @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java index 356efc590b..5d4b188911 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/FieldNotEmptyValidator.java @@ -1,7 +1,7 @@ package com.baeldung.restvalidation.service3; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class FieldNotEmptyValidator implements ConstraintValidator { diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java index e506b63d8e..3efb88c29d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/restvalidation/service3/UserService3.java @@ -3,8 +3,7 @@ package com.baeldung.restvalidation.service3; import java.util.List; import java.util.stream.Collectors; -import javax.validation.Valid; - +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java index c9b9c51bec..8cfb9b9931 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java @@ -6,9 +6,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.view.feed.AbstractRssFeedView; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java index 62b1329a54..d3d3cb44d5 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootannotations/MySQLAutoconfiguration.java @@ -3,9 +3,9 @@ package com.baeldung.springbootannotations; import java.util.Arrays; import java.util.Properties; -import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; +import jakarta.persistence.EntityManagerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionMessage; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java index 589024c0bc..190e882781 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/LoginController.java @@ -1,7 +1,6 @@ package com.baeldung.springbootmvc; -import javax.validation.Valid; - +import jakarta.validation.Valid; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java index 5b4250d5e3..86265b0b4d 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/jsfapplication/JsfApplication.java @@ -1,7 +1,6 @@ package com.baeldung.springbootmvc.jsfapplication; -import javax.faces.webapp.FacesServlet; - +import jakarta.faces.webapp.FacesServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; diff --git a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java index 107cd1bbf1..274265e97b 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java +++ b/spring-boot-modules/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/model/LoginForm.java @@ -1,8 +1,8 @@ package com.baeldung.springbootmvc.model; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; public class LoginForm { diff --git a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties index 90d3c88a8f..f8e1a6a434 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties +++ b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages.properties @@ -1 +1 @@ -javax.validation.constraints.NotEmpty.message=The field cannot be empty \ No newline at end of file +jakarta.validation.constraints.NotEmpty.message=The field cannot be empty \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties index 04f415911c..5c7bfbcb36 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties +++ b/spring-boot-modules/spring-boot-mvc/src/main/resources/ValidationMessages_zh.properties @@ -1 +1 @@ -javax.validation.constraints.NotEmpty.message=本欄不能留空 \ No newline at end of file +jakarta.validation.constraints.NotEmpty.message=本欄不能留空 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml b/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml index e0cd4d8850..45d30565fe 100644 --- a/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml +++ b/spring-boot-modules/spring-boot-mvc/src/main/webapp/WEB-INF/web.xml @@ -7,7 +7,7 @@ Faces Servlet - javax.faces.webapp.FacesServlet + jakarta.faces.webapp.FacesServlet 1 diff --git a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java index 92223892d9..230fe200e6 100644 --- a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java @@ -4,9 +4,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import javax.servlet.FilterRegistration; -import javax.servlet.ServletContext; - +import jakarta.servlet.FilterRegistration; +import jakarta.servlet.ServletContext; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java index c29cd75e9d..0d413be91e 100644 --- a/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java +++ b/spring-boot-modules/spring-boot-mvc/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java @@ -4,9 +4,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import javax.servlet.FilterRegistration; -import javax.servlet.ServletContext; - +import jakarta.servlet.FilterRegistration; +import jakarta.servlet.ServletContext; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; From 6776be43283bb56822d321cc6552aff47ca2c60e Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:31:11 +0200 Subject: [PATCH 85/88] [JAVA-32463] Move Dozer module to libraries-data-3 (#16227) --- dozer/README.md | 7 ---- dozer/pom.xml | 32 ------------------- dozer/src/main/resources/logback.xml | 13 -------- libraries-data-3/README.md | 1 + libraries-data-3/pom.xml | 12 +++++++ .../main/java/com/baeldung/dozer/Dest.java | 0 .../main/java/com/baeldung/dozer/Dest2.java | 0 .../com/baeldung/dozer/MyCustomConvertor.java | 0 .../main/java/com/baeldung/dozer/Person.java | 0 .../main/java/com/baeldung/dozer/Person2.java | 0 .../main/java/com/baeldung/dozer/Person3.java | 0 .../java/com/baeldung/dozer/Personne.java | 0 .../java/com/baeldung/dozer/Personne2.java | 0 .../java/com/baeldung/dozer/Personne3.java | 0 .../main/java/com/baeldung/dozer/Source.java | 0 .../main/java/com/baeldung/dozer/Source2.java | 0 .../baeldung/dozer/DozerIntegrationTest.java | 4 +-- .../test/resources/dozer_custom_convertor.xml | 0 .../src/test/resources/dozer_mapping.xml | 0 .../src/test/resources/dozer_mapping2.xml | 0 pom.xml | 2 -- 21 files changed, 15 insertions(+), 56 deletions(-) delete mode 100644 dozer/README.md delete mode 100644 dozer/pom.xml delete mode 100644 dozer/src/main/resources/logback.xml rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Dest.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Dest2.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/MyCustomConvertor.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Person.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Person2.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Person3.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Personne.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Personne2.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Personne3.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Source.java (100%) rename {dozer => libraries-data-3}/src/main/java/com/baeldung/dozer/Source2.java (100%) rename {dozer => libraries-data-3}/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java (98%) rename {dozer => libraries-data-3}/src/test/resources/dozer_custom_convertor.xml (100%) rename {dozer => libraries-data-3}/src/test/resources/dozer_mapping.xml (100%) rename {dozer => libraries-data-3}/src/test/resources/dozer_mapping2.xml (100%) diff --git a/dozer/README.md b/dozer/README.md deleted file mode 100644 index e87e889ce3..0000000000 --- a/dozer/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Dozer - -This module contains articles about Dozer - -### Relevant Articles: - -- [A Guide to Mapping With Dozer](https://www.baeldung.com/dozer) diff --git a/dozer/pom.xml b/dozer/pom.xml deleted file mode 100644 index 66f4ee8227..0000000000 --- a/dozer/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - dozer - dozer - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - net.sf.dozer - dozer - ${dozer.version} - - - - - 5.5.1 - - - \ No newline at end of file diff --git a/dozer/src/main/resources/logback.xml b/dozer/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/dozer/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/libraries-data-3/README.md b/libraries-data-3/README.md index e6f02bf2aa..3a68734fd1 100644 --- a/libraries-data-3/README.md +++ b/libraries-data-3/README.md @@ -12,4 +12,5 @@ This module contains articles about libraries for data processing in Java. - [Introduction to Eclipse Collections](https://www.baeldung.com/eclipse-collections) - [Introduction to Caffeine](https://www.baeldung.com/java-caching-caffeine) - [Guide to Using ModelMapper](https://www.baeldung.com/java-modelmapper) +- [A Guide to Mapping With Dozer](https://www.baeldung.com/dozer) - More articles: [[<-- prev]](/../libraries-data-2) diff --git a/libraries-data-3/pom.xml b/libraries-data-3/pom.xml index 536939d435..35da822e7c 100644 --- a/libraries-data-3/pom.xml +++ b/libraries-data-3/pom.xml @@ -71,6 +71,17 @@ modelmapper ${org.modelmapper.version} + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + net.sf.dozer + dozer + ${dozer.version} + + @@ -96,6 +107,7 @@ 3.1.8 3.0.2 3.2.0 + 5.5.1 diff --git a/dozer/src/main/java/com/baeldung/dozer/Dest.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Dest.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Dest.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Dest.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Dest2.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Dest2.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Dest2.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Dest2.java diff --git a/dozer/src/main/java/com/baeldung/dozer/MyCustomConvertor.java b/libraries-data-3/src/main/java/com/baeldung/dozer/MyCustomConvertor.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/MyCustomConvertor.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/MyCustomConvertor.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Person.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Person.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Person.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Person.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Person2.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Person2.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Person2.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Person2.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Person3.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Person3.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Person3.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Person3.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Personne.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Personne.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Personne.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Personne.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Personne2.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Personne2.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Personne2.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Personne2.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Personne3.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Personne3.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Personne3.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Personne3.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Source.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Source.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Source.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Source.java diff --git a/dozer/src/main/java/com/baeldung/dozer/Source2.java b/libraries-data-3/src/main/java/com/baeldung/dozer/Source2.java similarity index 100% rename from dozer/src/main/java/com/baeldung/dozer/Source2.java rename to libraries-data-3/src/main/java/com/baeldung/dozer/Source2.java diff --git a/dozer/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java b/libraries-data-3/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java similarity index 98% rename from dozer/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java rename to libraries-data-3/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java index 591189bca9..48ec5fc5e4 100644 --- a/dozer/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java +++ b/libraries-data-3/src/test/java/com/baeldung/dozer/DozerIntegrationTest.java @@ -171,7 +171,7 @@ public class DozerIntegrationTest { configureMapper("dozer_custom_convertor.xml"); String dateTime = "2007-06-26T21:22:39Z"; - long timestamp = new Long("1182882159000"); + long timestamp = Long.parseLong("1182882159000"); Person3 person = new Person3("Rich", dateTime); Personne3 person0 = mapper.map(person, Personne3.class); @@ -182,7 +182,7 @@ public class DozerIntegrationTest { @Test public void givenSrcAndDestWithDifferentFieldTypes_whenAbleToCustomConvertBidirectionally_thenCorrect() { - long timestamp = new Long("1182882159000"); + long timestamp = Long.parseLong("1182882159000"); Personne3 person = new Personne3("Rich", timestamp); configureMapper("dozer_custom_convertor.xml"); diff --git a/dozer/src/test/resources/dozer_custom_convertor.xml b/libraries-data-3/src/test/resources/dozer_custom_convertor.xml similarity index 100% rename from dozer/src/test/resources/dozer_custom_convertor.xml rename to libraries-data-3/src/test/resources/dozer_custom_convertor.xml diff --git a/dozer/src/test/resources/dozer_mapping.xml b/libraries-data-3/src/test/resources/dozer_mapping.xml similarity index 100% rename from dozer/src/test/resources/dozer_mapping.xml rename to libraries-data-3/src/test/resources/dozer_mapping.xml diff --git a/dozer/src/test/resources/dozer_mapping2.xml b/libraries-data-3/src/test/resources/dozer_mapping2.xml similarity index 100% rename from dozer/src/test/resources/dozer_mapping2.xml rename to libraries-data-3/src/test/resources/dozer_mapping2.xml diff --git a/pom.xml b/pom.xml index a9b80de9c4..c56d7d4c13 100644 --- a/pom.xml +++ b/pom.xml @@ -683,7 +683,6 @@ di-modules disruptor docker-modules - dozer drools dubbo feign @@ -931,7 +930,6 @@ di-modules disruptor docker-modules - dozer drools dubbo feign From 82120f03d7807e44716e46d08e670c167926add0 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Tue, 26 Mar 2024 05:43:41 +0700 Subject: [PATCH 86/88] [JAVA-26659] Upgrade jacoco-maven-plugin (#16223) --- core-java-modules/core-java-reflection-2/pom.xml | 3 ++- core-java-modules/core-java-reflection-3/pom.xml | 3 ++- jhipster-6/bookstore-monolith/pom.xml | 2 +- jhipster-modules/jhipster-microservice/car-app/pom.xml | 2 +- jhipster-modules/jhipster-microservice/dealer-app/pom.xml | 2 +- jhipster-modules/jhipster-microservice/gateway-app/pom.xml | 2 +- jhipster-modules/jhipster-monolithic/pom.xml | 2 +- maven-modules/jacoco-coverage-aggregation/pom.xml | 2 +- spring-boot-modules/spring-boot-ci-cd/pom.xml | 2 +- testing-modules/testing-libraries-2/pom.xml | 2 +- 10 files changed, 12 insertions(+), 10 deletions(-) diff --git a/core-java-modules/core-java-reflection-2/pom.xml b/core-java-modules/core-java-reflection-2/pom.xml index 69cf4f5f37..41d2b0a7ae 100644 --- a/core-java-modules/core-java-reflection-2/pom.xml +++ b/core-java-modules/core-java-reflection-2/pom.xml @@ -49,7 +49,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + ${jacoco-maven-plugin.version} @@ -73,6 +73,7 @@ 1.8 1.8 5.3.4 + 0.8.11 \ No newline at end of file diff --git a/core-java-modules/core-java-reflection-3/pom.xml b/core-java-modules/core-java-reflection-3/pom.xml index e4111b8dda..61bc424336 100644 --- a/core-java-modules/core-java-reflection-3/pom.xml +++ b/core-java-modules/core-java-reflection-3/pom.xml @@ -49,7 +49,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + ${jacoco-maven-plugin.version} @@ -73,6 +73,7 @@ 1.8 1.8 5.3.4 + 0.8.11 \ No newline at end of file diff --git a/jhipster-6/bookstore-monolith/pom.xml b/jhipster-6/bookstore-monolith/pom.xml index 97bfbe7550..a4f334fc1c 100644 --- a/jhipster-6/bookstore-monolith/pom.xml +++ b/jhipster-6/bookstore-monolith/pom.xml @@ -1168,7 +1168,7 @@ 3.2.2 0.9.11 1.7.6 - 0.8.2 + 0.8.11 1.0.0 3.4.2 3.5.0.1254 diff --git a/jhipster-modules/jhipster-microservice/car-app/pom.xml b/jhipster-modules/jhipster-microservice/car-app/pom.xml index 069a1f6848..2fee5148a0 100644 --- a/jhipster-modules/jhipster-microservice/car-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/car-app/pom.xml @@ -24,7 +24,7 @@ 1.2 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 1.8 3.21.0-GA 1.0.0 diff --git a/jhipster-modules/jhipster-microservice/dealer-app/pom.xml b/jhipster-modules/jhipster-microservice/dealer-app/pom.xml index 43f9b046c7..509651e209 100644 --- a/jhipster-modules/jhipster-microservice/dealer-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/dealer-app/pom.xml @@ -24,7 +24,7 @@ 1.2 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 3.21.0-GA 1.0.0 1.1.0 diff --git a/jhipster-modules/jhipster-microservice/gateway-app/pom.xml b/jhipster-modules/jhipster-microservice/gateway-app/pom.xml index 90d703b8c7..0e80a02e2e 100644 --- a/jhipster-modules/jhipster-microservice/gateway-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/gateway-app/pom.xml @@ -27,7 +27,7 @@ 1.2 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 3.21.0-GA 1.0.0 1.1.0 diff --git a/jhipster-modules/jhipster-monolithic/pom.xml b/jhipster-modules/jhipster-monolithic/pom.xml index f1ee479756..6b06ba2e8b 100644 --- a/jhipster-modules/jhipster-monolithic/pom.xml +++ b/jhipster-modules/jhipster-monolithic/pom.xml @@ -893,7 +893,7 @@ 2.2.3 5.2.8.Final 5.1.0 - 0.7.9 + 0.8.11 3.21.0-GA 1.0.0 1.1.0 diff --git a/maven-modules/jacoco-coverage-aggregation/pom.xml b/maven-modules/jacoco-coverage-aggregation/pom.xml index bc70c60b50..274a19c723 100644 --- a/maven-modules/jacoco-coverage-aggregation/pom.xml +++ b/maven-modules/jacoco-coverage-aggregation/pom.xml @@ -38,7 +38,7 @@ - 0.8.8 + 0.8.11 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-ci-cd/pom.xml b/spring-boot-modules/spring-boot-ci-cd/pom.xml index 6e58f1162d..51adb6bc1b 100644 --- a/spring-boot-modules/spring-boot-ci-cd/pom.xml +++ b/spring-boot-modules/spring-boot-ci-cd/pom.xml @@ -105,7 +105,7 @@ - 0.8.5 + 0.8.11 3.0.2 2.2.0 diff --git a/testing-modules/testing-libraries-2/pom.xml b/testing-modules/testing-libraries-2/pom.xml index 717ccac2b2..075e26aefa 100644 --- a/testing-modules/testing-libraries-2/pom.xml +++ b/testing-modules/testing-libraries-2/pom.xml @@ -166,7 +166,7 @@ - 0.8.6 + 0.8.11 1.19.0 1.0.0 2.1.3 From c25f863bb23d6a21bffe08bd52400f4646ea9a6a Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:01:32 +0200 Subject: [PATCH 87/88] JAVA-32055 Upgrade spring-mvc-forms-thymeleaf to Spring Boot 3 (#16203) Co-authored-by: timis1 --- spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml | 5 ++--- .../baeldung/multipartupload/EmployeeController.java | 11 +++++------ .../TodoControllerWithSessionAttributes.java | 2 +- .../main/java/com/baeldung/sessionattrs/TodoList.java | 1 - .../EmployeeControllerIntegrationTest.java | 5 +---- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml b/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml index 9c9d6804ae..d5a2cf00f4 100644 --- a/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../parent-boot-3 @@ -43,7 +43,6 @@ - 3.0.9.RELEASE com.baeldung.sessionattrs.SessionAttrsApplication diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java index e02844233e..5069f1739c 100644 --- a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java @@ -1,18 +1,17 @@ package com.baeldung.multipartupload; -import lombok.AllArgsConstructor; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; -import static org.springframework.web.bind.annotation.RequestMethod.POST; +import lombok.AllArgsConstructor; @Controller @AllArgsConstructor @@ -26,20 +25,20 @@ public class EmployeeController { return "employee/createEmployeeForm"; } - @RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + @PostMapping(path = "/employee", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) public String saveEmployee(@ModelAttribute Employee employee) { employeeService.save(employee); return "employee/success"; } - @RequestMapping(path = "/requestpart/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + @PostMapping(path = "/requestpart/employee", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) public ResponseEntity saveEmployee(@RequestPart Employee employee, @RequestPart MultipartFile document) { employee.setDocument(document); employeeService.save(employee); return ResponseEntity.ok().build(); } - @RequestMapping(path = "/requestparam/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + @PostMapping(path = "/requestparam/employee", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) public ResponseEntity saveEmployee(@RequestParam String name, @RequestPart MultipartFile document) { Employee employee = new Employee(name, document); employeeService.save(employee); diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java index 99e0b46fc2..e8c3b30265 100644 --- a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java @@ -13,7 +13,7 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.view.RedirectView; @Controller -@RequestMapping("/sessionattributes") +@RequestMapping(value = "/sessionattributes") @SessionAttributes("todos") public class TodoControllerWithSessionAttributes { diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java index 02c05f4282..cf2aba6280 100644 --- a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java @@ -2,7 +2,6 @@ package com.baeldung.sessionattrs; import java.util.ArrayDeque; -@SuppressWarnings("serial") public class TodoList extends ArrayDeque{ } diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java index 73cf905a34..f70cb21102 100644 --- a/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java @@ -1,8 +1,6 @@ package com.baeldung.multipartupload; import org.junit.jupiter.api.Test; -import org.mockito.BDDMockito; -import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -10,7 +8,6 @@ import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import static org.apache.http.entity.ContentType.DEFAULT_BINARY; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -18,7 +15,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @EnableWebMvc public class EmployeeControllerIntegrationTest { - private static final MockMultipartFile A_FILE = new MockMultipartFile("document", null, DEFAULT_BINARY.toString(), "Employee Record".getBytes()); + private static final MockMultipartFile A_FILE = new MockMultipartFile("document", null, "application/octet-stream", "Employee Record".getBytes()); @Autowired private MockMvc mockMvc; From c957410b7eabc54a8f19412b0da476cc78b3c132 Mon Sep 17 00:00:00 2001 From: Wynn Teo <49014791+wynnteo@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:19:44 +0800 Subject: [PATCH 88/88] Bael 7648 (#16176) * BAEL-7490 read write file in separate thread * Change the to try resources * Update the code to sync with article * added new module for get list entity in hibernate * Move the code to hibernate-queries module * simplify the code --- .../listentity/entity/Department.java | 40 +++++++++ .../hibernate/listentity/entity/Employee.java | 41 +++++++++ .../listentity/service/EmployeeService.java | 88 +++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java create mode 100644 persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java create mode 100644 persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java new file mode 100644 index 0000000000..62a31dd344 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Department.java @@ -0,0 +1,40 @@ +package com.baeldung.hibernate.listentity.entity; + +import java.util.List; +import jakarta.persistence.*; + +@Entity +public class Department { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @OneToMany(mappedBy = "department", fetch = FetchType.EAGER) + private List employees; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java new file mode 100644 index 0000000000..6b4b0c56b1 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/entity/Employee.java @@ -0,0 +1,41 @@ +package com.baeldung.hibernate.listentity.entity; + +import jakarta.persistence.*; + +@Entity +@NamedQuery(name = "findAllEmployees", query = "SELECT e FROM Employee e") +@NamedQuery(name = "findEmployeesByDepartment", query = "SELECT e FROM Employee e WHERE e.department = :department ORDER BY e.lastName ASC") +public class Employee { + + @Id + @GeneratedValue + private Long id; + + private String lastName; + + private String department; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } +} diff --git a/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java new file mode 100644 index 0000000000..b336fb1691 --- /dev/null +++ b/persistence-modules/hibernate-queries/src/main/java/com/baeldung/hibernate/listentity/service/EmployeeService.java @@ -0,0 +1,88 @@ +package com.baeldung.hibernate.listentity.service; + +import java.util.Collections; +import java.util.List; + +import jakarta.persistence.*; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; + +import org.springframework.stereotype.Service; + +import com.baeldung.hibernate.listentity.entity.Department; +import com.baeldung.hibernate.listentity.entity.Employee; + +@Service +public class EmployeeService { + + @PersistenceContext + private EntityManager entityManager; + + public List getAllEmployeesUsingJPQL() { + String jpqlQuery = "SELECT e FROM Employee e"; + Query query = entityManager.createQuery(jpqlQuery, Employee.class); + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingJPQL() { + String jpqlQuery = "SELECT e FROM Employee e WHERE e.department = 'Engineering' ORDER BY e.lastName ASC"; + Query query = entityManager.createQuery(jpqlQuery, Employee.class); + + return query.getResultList(); + } + + public List getAllEmployeesUsingNamedQuery() { + Query query = entityManager.createNamedQuery("findAllEmployees", Employee.class); + + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingNamedQuery(String department) { + Query query = entityManager.createNamedQuery("findEmployeesByDepartment", Employee.class); + query.setParameter("department", department); + + return query.getResultList(); + } + + public List getAllEmployeesUsingCriteriaAPI() { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Employee.class); + Root employeeRoot = criteriaQuery.from(Employee.class); + + criteriaQuery.select(employeeRoot); + Query query = entityManager.createQuery(criteriaQuery); + + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingCriteriaAPI(String department) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Employee.class); + Root employeeRoot = criteriaQuery.from(Employee.class); + Predicate departmentPredicate = criteriaBuilder.equal(employeeRoot.get("department"), department); + Path sortByPath = employeeRoot.get("lastName"); + criteriaQuery.orderBy(criteriaBuilder.asc(sortByPath)); + criteriaQuery.select(employeeRoot) + .where(departmentPredicate); + Query query = entityManager.createQuery(criteriaQuery); + + return query.getResultList(); + } + + public List getAllEmployeesByDepartmentUsingOneToManyAnnotations(String departmentName) { + try { + // Retrieve the department by its name + Department department = entityManager.createQuery("SELECT d FROM Department d WHERE d.name = :name", Department.class) + .setParameter("name", departmentName) + .getSingleResult(); + + // Return the list of employees associated with the department + return department.getEmployees(); + } catch (NoResultException e) { + return Collections.emptyList(); + } + } +}