diff --git a/algorithms-modules/algorithms-miscellaneous-7/README.md b/algorithms-modules/algorithms-miscellaneous-7/README.md index 1d53235990..a08948eda5 100644 --- a/algorithms-modules/algorithms-miscellaneous-7/README.md +++ b/algorithms-modules/algorithms-miscellaneous-7/README.md @@ -12,4 +12,6 @@ - [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) +- [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) 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..2056688659 --- /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 isHappyNumberFloyd(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.isHappyNumberFloyd(7)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(10)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(13)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(19)); + assertTrue(HappyNumberDecider.isHappyNumberFloyd(23)); + + assertFalse(HappyNumberDecider.isHappyNumberFloyd(4)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(6)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(11)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(15)); + assertFalse(HappyNumberDecider.isHappyNumberFloyd(20)); + + } + +} \ No newline at end of file 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) 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/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) 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) 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) 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..397aca8906 --- /dev/null +++ b/core-java-modules/core-java-collections-list-6/src/test/java/com/baeldung/addtoimmutablelist/AddElementsToImmutableListUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.addtoimmutablelist; + +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; + +public class AddElementsToImmutableListUnitTest { + + public static List appendAnElement(List immutableList, T element) { + List tmpList = new ArrayList<>(immutableList); + tmpList.add(element); + return Collections.unmodifiableList(tmpList); + } + + @SafeVarargs + public static List appendElements(List immutableList, T... elements) { + List tmpList = new ArrayList<>(immutableList); + tmpList.addAll(Arrays.asList(elements)); + return Collections.unmodifiableList(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 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) 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) 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) 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 0000000000..47c3ad1e1b Binary files /dev/null and b/core-java-modules/core-java-io-5/src/main/resources/myFile.gz differ 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 0000000000..47c3ad1e1b Binary files /dev/null and b/core-java-modules/core-java-io-5/src/test/resources/myFile.gz differ 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 dc33e5338a..410c164496 100644 --- a/core-java-modules/core-java-io-apis-2/pom.xml +++ b/core-java-modules/core-java-io-apis-2/pom.xml @@ -96,4 +96,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/inputstreamreader/InputStreamReaderUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java new file mode 100644 index 0000000000..d67b56e10b --- /dev/null +++ b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/inputstreamreader/InputStreamReaderUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.inputstreamreader; + +import static org.assertj.core.api.Assertions.assertThat; + +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.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class InputStreamReaderUnitTest { + @Test + public void givenAStringWrittenToAFile_whenReadByInputStreamReader_thenShouldMatchWhenRead(@TempDir Path tempDir) throws IOException { + String sampleTxt = "Good day. This is just a test. Good bye."; + Path sampleOut = tempDir.resolve("sample-out.txt"); + List lines = Arrays.asList(sampleTxt); + Files.write(sampleOut, lines); + String absolutePath = String.valueOf(sampleOut.toAbsolutePath()); + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(absolutePath), StandardCharsets.UTF_8)) { + boolean isMatched = false; + int b; + StringBuilder sb = new StringBuilder(); + while ((b = reader.read()) != -1) { + sb.append((char) b); + if (sb.toString().contains(sampleTxt)) { + isMatched = true; + break; + } + } + assertThat(isMatched).isTrue(); + } + } +} 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) 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()); + } +} + 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 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) 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); } 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) 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) 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/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..b23dd07fc8 --- /dev/null +++ b/core-java-modules/core-java-streams-maps/src/test/java/com/baeldung/streams/mapstreamtomap/MapStreamToMapUnitTest.java @@ -0,0 +1,143 @@ +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.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; + +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); + }}; + + @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 = Stream.of(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, () -> 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 = Stream.of(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, () -> 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<>(); + Stream.of(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); + }}; + 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 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); + } +} 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/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/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); + } +} 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 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) 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/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/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/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) 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/microservices-modules/saga-pattern/README.md b/microservices-modules/saga-pattern/README.md new file mode 100644 index 0000000000..853cce4c5e --- /dev/null +++ b/microservices-modules/saga-pattern/README.md @@ -0,0 +1,13 @@ +# Saga Pattern Using Orkes Conductor + +This is an example project showing how to build event driven applications using [Conductor](https://github.com/conductor-oss/conductor) + +# Pre-requisites +1. Docker +2. Running conductor server + +**Start the conductor server** + +```shell +docker run --init -p 8080:8080 -p 1234:5000 conductoross/conductor-standalone:3.15.0 +``` \ No newline at end of file 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/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 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/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"); + } +} + 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(); + } + } +} diff --git a/persistence-modules/liquibase/pom.xml b/persistence-modules/liquibase/pom.xml index a6e0ed85e9..5caf7047ac 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 + ${spring-boot.version} + + + org.slf4j + slf4j-log4j12 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring-boot.version} + + + org.liquibase + liquibase-core + ${liquibase.version} + + + org.postgresql + postgresql + ${postgresql.version} + runtime + + + net.lbruun.springboot + preliquibase-spring-boot-starter + ${preliquibase.version} + @@ -32,12 +60,30 @@ 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 + 3.2.3 + 4.26.0 + 42.7.2 + 1.5.0 \ 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-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 new file mode 100644 index 0000000000..6ae5187a92 --- /dev/null +++ b/persistence-modules/liquibase/src/main/resources/liquibase/changelog.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ 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 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) 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/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) 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()); 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 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/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 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/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 3be66dc168..2b62b3d1bc 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 @@ -54,11 +56,11 @@ 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 - + spring-boot-mvc-5 spring-boot-mvc-birt spring-boot-mvc-jersey spring-boot-nashorn @@ -86,8 +88,6 @@ spring-boot-data-2 spring-boot-validation - - spring-boot-cassandre spring-boot-react @@ -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 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) diff --git a/spring-boot-modules/spring-caching-2/README.md b/spring-boot-modules/spring-boot-caching-2/README.md similarity index 67% rename from spring-boot-modules/spring-caching-2/README.md rename to spring-boot-modules/spring-boot-caching-2/README.md index 864a17d98b..a2b0c41c63 100644 --- a/spring-boot-modules/spring-caching-2/README.md +++ b/spring-boot-modules/spring-boot-caching-2/README.md @@ -2,4 +2,6 @@ - [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) +- 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/dozer/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-caching/src/main/resources/logback.xml similarity index 100% rename from dozer/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 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/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>>(){}); 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 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))); 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; diff --git a/spring-boot-modules/spring-caching/src/main/resources/logback.xml b/spring-boot-modules/spring-caching/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/spring-boot-modules/spring-caching/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/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 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 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/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..5faf5d2707 --- /dev/null +++ b/spring-di-4/src/main/java/com/baeldung/registrypostprocessor/ApiClientConfiguration.java @@ -0,0 +1,41 @@ +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; + +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/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/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); + } +} diff --git a/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationUnitTest.java b/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationUnitTest.java new file mode 100644 index 0000000000..80e578166c --- /dev/null +++ b/spring-di-4/src/test/java/com/baeldung/registrypostprocessor/ApiClientConfigurationUnitTest.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 ApiClientConfigurationUnitTest { + @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 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 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-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"; 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-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) 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) 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 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-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; 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(), 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; 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/SpringJwtApplication.java b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java new file mode 100644 index 0000000000..611935e566 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/SpringJwtApplication.java @@ -0,0 +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 new file mode 100644 index 0000000000..37de1682db --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/controller/JwtAuthController.java @@ -0,0 +1,77 @@ +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.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; + +@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 { + + 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())); + + 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())); + + } + + @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 new file mode 100644 index 0000000000..1cc64f3550 --- /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..a149c71121 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/AuthTokenFilter.java @@ -0,0 +1,59 @@ +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..5fbd4c6de3 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/jwtconfig/JwtUtils.java @@ -0,0 +1,81 @@ +package com.baeldung.jwtsignkey.jwtconfig; + +import com.baeldung.jwtsignkey.userservice.UserDetailsImpl; + +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; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +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() + .subject((userPrincipal.getUsername())) + .issuedAt(new Date()) + .expiration(new Date((new Date()).getTime() + jwtExpirationMs)) + .signWith(getSigningKey()) + .compact(); + + } + + private SecretKey getSigningKey() { + byte[] keyBytes = Decoders.BASE64.decode(jwtSecret); + return Keys.hmacShaKeyFor(keyBytes); + } + + public String getUserNameFromJwtToken(String token) { + return Jwts.parser() + .verifyWith(getSigningKey()) + .build() + .parseSignedClaims(token) + .getPayload() + .getSubject(); + + } + + public boolean validateJwtToken(String authToken) { + try { + Jwts.parser() + .verifyWith(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/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..886338242c --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/repository/UserRepository.java @@ -0,0 +1,14 @@ +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 { + + Boolean existsByUsername(String username); + + Optional findByUsername(String username); + +} 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 new file mode 100644 index 0000000000..f5b3148c42 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/response/JwtResponse.java @@ -0,0 +1,37 @@ +package com.baeldung.jwtsignkey.response; + +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 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/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..30e8c552c9 --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/securityconfig/SecurityConfiguration.java @@ -0,0 +1,79 @@ +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; +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 org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; + +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 = { "/h2-console/**", "/signin", "/signup", "/user-dashboard" }; + + @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, 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); + + 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..a651a1088a --- /dev/null +++ b/spring-security-modules/spring-security-core-2/src/main/java/com/baeldung/jwtsignkey/userservice/UserDetailsImpl.java @@ -0,0 +1,85 @@ +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..c544f748cd --- /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/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 9d154c9cc0..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 +1,2 @@ -spring.thymeleaf.prefix=classpath:/templates/ \ No newline at end of file +baeldung.app.jwtSecret= 404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970 +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()); + } + + +} + 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; 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.*; 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/"; 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/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) 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 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