diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java index ba424772d5..ec7081bec7 100644 --- a/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java +++ b/algorithms-modules/algorithms-miscellaneous-8/src/main/java/com/baeldung/algorithms/mergeintervals/MergeOverlappingIntervals.java @@ -1,23 +1,22 @@ package com.baeldung.algorithms.mergeintervals; +import static java.lang.Integer.max; + import java.util.ArrayList; +import java.util.Comparator; import java.util.List; public class MergeOverlappingIntervals { public List doMerge(List intervals) { - // Sort the intervals based on start time - intervals.sort((one, two) -> one.start - two.start); - - // Create somewhere to put the merged list, start it off with the earliest starting interval + intervals.sort(Comparator.comparingInt(interval -> interval.start)); ArrayList merged = new ArrayList<>(); merged.add(intervals.get(0)); - // Loop over each interval and merge if start time is before the end time of the - // previous interval intervals.forEach(interval -> { - if (merged.get(merged.size() - 1).end > interval.start) { - merged.get(merged.size() - 1).setEnd(interval.end); + Interval lastMerged = merged.get(merged.size() - 1); + if (interval.start <= lastMerged.end){ + lastMerged.setEnd(max(interval.end, lastMerged.end)); } else { merged.add(interval); } @@ -25,5 +24,4 @@ public class MergeOverlappingIntervals { return merged; } - -} +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java index 5f15fe00f6..2d8a94dca4 100644 --- a/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java +++ b/algorithms-modules/algorithms-miscellaneous-8/src/test/java/com/baeldung/algorithms/mergeintervals/MergeIntervalsUnitTest.java @@ -1,30 +1,38 @@ package com.baeldung.algorithms.mergeintervals; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.Test; class MergeIntervalsUnitTest { - private ArrayList intervals = new ArrayList<>(Arrays.asList( - new Interval(2, 5), - new Interval(13, 20), - new Interval(11, 15), - new Interval(1, 3) + private List intervals = new ArrayList<>(Arrays.asList( + // @formatter:off + new Interval(3, 5), + new Interval(13, 20), + new Interval(11, 15), + new Interval(15, 16), + new Interval(1, 3), + new Interval(4, 5), + new Interval(16, 17) + // @formatter:on )); - private ArrayList intervalsMerged = new ArrayList<>(Arrays.asList( - new Interval(1, 5), - new Interval(11, 20) + private List intervalsMerged = new ArrayList<>(Arrays.asList( + // @formatter:off + new Interval(1, 5), + new Interval(11, 20) + // @formatter:on )); @Test void givenIntervals_whenMerging_thenReturnMergedIntervals() { MergeOverlappingIntervals merger = new MergeOverlappingIntervals(); - ArrayList result = (ArrayList) merger.doMerge(intervals); - assertArrayEquals(intervalsMerged.toArray(), result.toArray()); + List result = merger.doMerge(intervals); + assertEquals(intervalsMerged, result); } -} +} \ No newline at end of file diff --git a/apache-poi/pom.xml b/apache-poi/pom.xml index 876fca0efe..027ee06968 100644 --- a/apache-poi/pom.xml +++ b/apache-poi/pom.xml @@ -40,6 +40,16 @@ fastexcel-reader ${fastexcel.version} + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + @@ -64,6 +74,7 @@ 1.0.9 0.17.0 3.3.1 + 2.23.1 \ No newline at end of file diff --git a/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml b/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml index acc14b55ff..2aa48a2f92 100644 --- a/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml +++ b/aws-modules/aws-lambda-modules/todo-reminder-lambda/ToDoFunction/pom.xml @@ -71,7 +71,7 @@ org.mockito mockito-core - ${mockito-core.version} + ${mockito.version} test @@ -112,7 +112,6 @@ 11.2 5.1.0 2.0.2 - 4.1.0 3.19.0 5.8.1 diff --git a/core-java-modules/core-java-11/src/main/java/com/baeldung/Unrelated.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/Unrelated.java new file mode 100644 index 0000000000..f122b89f6e --- /dev/null +++ b/core-java-modules/core-java-11/src/main/java/com/baeldung/Unrelated.java @@ -0,0 +1,4 @@ +package com.baeldung; + +public class Unrelated { +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java index 9e6bd72680..8699e94b47 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java @@ -1,7 +1,7 @@ package com.baeldung; -import static org.junit.Assert.assertTrue; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.*; import java.util.Arrays; import java.util.Set; @@ -14,22 +14,22 @@ public class OuterUnitTest { @Test public void whenGetNestHostFromOuter_thenGetNestHost() { - is(Outer.class.getNestHost().getName()).equals(NEST_HOST_NAME); + assertEquals(NEST_HOST_NAME, Outer.class.getNestHost().getName()); } @Test public void whenGetNestHostFromInner_thenGetNestHost() { - is(Outer.Inner.class.getNestHost().getName()).equals(NEST_HOST_NAME); + assertEquals(NEST_HOST_NAME, Outer.Inner.class.getNestHost().getName()); } @Test public void whenCheckNestmatesForNestedClasses_thenGetTrue() { - is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(true); + assertTrue(Outer.Inner.class.isNestmateOf(Outer.class)); } @Test public void whenCheckNestmatesForUnrelatedClasses_thenGetFalse() { - is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(false); + assertFalse(Outer.Inner.class.isNestmateOf(Unrelated.class)); } @Test diff --git a/core-java-modules/core-java-18/README.md b/core-java-modules/core-java-18/README.md index 7616b84a57..21c57a3db9 100644 --- a/core-java-modules/core-java-18/README.md +++ b/core-java-modules/core-java-18/README.md @@ -1,3 +1,4 @@ ## Relevant Articles - [Deprecate Finalization in Java 18](https://www.baeldung.com/java-18-deprecate-finalization) - [Simple Web Server in Java 18](https://www.baeldung.com/simple-web-server-java-18) +- [Internet Address Resolution SPI in Java](https://www.baeldung.com/java-service-provider-interface) 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 e762508bcd..2df723e9c9 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 @@ -3,3 +3,4 @@ - [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) +- [Set Matrix Elements to Zero in Java](https://www.baeldung.com/java-set-matrix-elements-to-zero) diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/matrixtozero/SetMatrixToZero.java b/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/matrixtozero/SetMatrixToZero.java new file mode 100644 index 0000000000..57c558caa7 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/matrixtozero/SetMatrixToZero.java @@ -0,0 +1,147 @@ +package com.baeldung.matrixtozero; + +import java.util.*; + +public class SetMatrixToZero{ + static void setZeroesByNaiveApproach(int[][] matrix) { + int row = matrix.length; + int col = matrix[0].length; + int [][] result = new int[row][col]; + + for(int i = 0; i rowSet = new HashSet<>(); + Set colSet = new HashSet<>(); + + for(int i = 0; i < rows; i++){ + for(int j = 0; j < cols; j++){ + if (matrix[i][j] == 0){ + rowSet.add(i); + colSet.add(j); + } + } + } + + for(int row: rowSet){ + for(int j = 0; j < cols; j++){ + matrix[row][j] = 0; + } + } + + for(int col: colSet) { + for(int i = 0; i < rows; i++){ + matrix[i][col] = 0; + } + } + } + + static boolean hasZeroInFirstRow(int[][] matrix, int cols) { + for (int j = 0; j < cols; j++) { + if (matrix[0][j] == 0) { + return true; + } + } + return false; + } + + static boolean hasZeroInFirstCol(int[][] matrix, int rows) { + for (int i = 0; i < rows; i++) { + if (matrix[i][0] == 0) { + return true; + } + } + return false; + } + + static void markZeroesInMatrix(int[][] matrix, int rows, int cols) { + for (int i = 1; i < rows; i++) { + for (int j = 1; j < cols; j++) { + if (matrix[i][j] == 0) { + matrix[i][0] = 0; + matrix[0][j] = 0; + } + } + } + } + + static void setZeroesInRows(int[][] matrix, int rows, int cols) { + for (int i = 1; i < rows; i++) { + if (matrix[i][0] == 0) { + for (int j = 1; j < cols; j++) { + matrix[i][j] = 0; + } + } + } + } + + static void setZeroesInCols(int[][] matrix, int rows, int cols) { + for (int j = 1; j < cols; j++) { + if (matrix[0][j] == 0) { + for (int i = 1; i < rows; i++) { + matrix[i][j] = 0; + } + } + } + } + + static void setZeroesInFirstRow(int[][] matrix, int cols) { + for (int j = 0; j < cols; j++) { + matrix[0][j] = 0; + } + } + + static void setZeroesInFirstCol(int[][] matrix, int rows) { + for (int i = 0; i < rows; i++) { + matrix[i][0] = 0; + } + } + + static void setZeroesByOptimalApproach(int[][] matrix) { + int rows = matrix.length; + int cols = matrix[0].length; + + boolean firstRowZero = hasZeroInFirstRow(matrix, cols); + boolean firstColZero = hasZeroInFirstCol(matrix, rows); + + markZeroesInMatrix(matrix, rows, cols); + + setZeroesInRows(matrix, rows, cols); + setZeroesInCols(matrix, rows, cols); + + if (firstRowZero) { + setZeroesInFirstRow(matrix, cols); + } + if (firstColZero) { + setZeroesInFirstCol(matrix, rows); + } + } + +} diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/matrixtozero/SetMatrixToZeroUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/matrixtozero/SetMatrixToZeroUnitTest.java new file mode 100644 index 0000000000..ee4996457e --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/matrixtozero/SetMatrixToZeroUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.matrixtozero; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import org.junit.jupiter.api.Test; + +public class SetMatrixToZeroUnitTest{ + @Test + void givenMatrix_whenUsingSetZeroesByNaiveApproach_thenSetZeroes() { + int[][] matrix = { + {1, 2, 3}, + {4, 0, 6}, + {7, 8, 9} + }; + int[][] expected = { + {1, 0, 3}, + {0, 0, 0}, + {7, 0, 9} + }; + SetMatrixToZero.setZeroesByNaiveApproach(matrix); + assertArrayEquals(expected, matrix); + } + + @Test + void givenMatrix_whenUsingSetZeroesByTimeOptimizedApproach_thenSetZeroes() { + int[][] matrix = { + {1, 2, 3}, + {4, 0, 6}, + {7, 8, 9} + }; + int[][] expected = { + {1, 0, 3}, + {0, 0, 0}, + {7, 0, 9} + }; + SetMatrixToZero.setZeroesByTimeOptimizedApproach(matrix); + assertArrayEquals(expected, matrix); + } + + @Test + void givenMatrix_whenUsingSetZeroesByOptimalApproach_thenSetZeroes() { + int[][] matrix = { + {1, 2, 3}, + {4, 0, 6}, + {7, 8, 9} + }; + int[][] expected = { + {1, 0, 3}, + {0, 0, 0}, + {7, 0, 9} + }; + SetMatrixToZero.setZeroesByOptimalApproach(matrix); + assertArrayEquals(expected, matrix); + } +} diff --git a/core-java-modules/core-java-collections-5/README.md b/core-java-modules/core-java-collections-5/README.md index 2fc7f7c699..e1ad221a31 100644 --- a/core-java-modules/core-java-collections-5/README.md +++ b/core-java-modules/core-java-collections-5/README.md @@ -13,4 +13,5 @@ - [Check if List Contains at Least One Enum](https://www.baeldung.com/java-list-check-enum-presence) - [Comparison of for Loops and Iterators](https://www.baeldung.com/java-for-loops-vs-iterators) - [PriorityQueue iterator() Method in Java](https://www.baeldung.com/java-priorityqueue-iterator) +- [Immutable vs Unmodifiable Collection in Java](https://www.baeldung.com/java-collection-immutable-unmodifiable-differences) - More articles: [[<-- prev]](/core-java-modules/core-java-collections-4) diff --git a/core-java-modules/core-java-collections-6/README.md b/core-java-modules/core-java-collections-6/README.md index b5f1adbf48..736e91f110 100644 --- a/core-java-modules/core-java-collections-6/README.md +++ b/core-java-modules/core-java-collections-6/README.md @@ -3,3 +3,5 @@ ## Core Java Collections Cookbooks and Examples ### Relevant Articles: + +- More articles: [[<-- prev]](/core-java-modules/core-java-collections-5) diff --git a/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/iteratorvsforeach/IteratorVsForeachUnitTest.java b/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/iteratorvsforeach/IteratorVsForeachUnitTest.java new file mode 100644 index 0000000000..ca9390a3ee --- /dev/null +++ b/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/iteratorvsforeach/IteratorVsForeachUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.iteratorvsforeach; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class IteratorVsForeachUnitTest { + + private static Stream listProvider() { + return Stream.of(Arguments.of(List.of("String1", "String2", "unwanted"), List.of("String1", "String2"))); + } + + @Test + public void givenEmptyCollection_whenUsingForEach_thenNoElementsAreIterated() { + List names = Collections.emptyList(); + StringBuilder stringBuilder = new StringBuilder(); + names.forEach(stringBuilder::append); + assertEquals("", stringBuilder.toString()); + } + + @ParameterizedTest + @MethodSource("listProvider") + public void givenCollectionWithElements_whenRemovingElementDuringForEachIteration_thenElementIsRemoved(List input, List expected) { + List mutableList = new ArrayList<>(input); + // Separate collection for items to be removed + List toRemove = new ArrayList<>(); + + // Using forEach to identify items to remove + input.forEach(item -> { + if (item.equals("unwanted")) { + toRemove.add(item); + } + }); + + // Removing the identified items from the original list + mutableList.removeAll(toRemove); + assertIterableEquals(expected, mutableList); + } + + @ParameterizedTest + @MethodSource("listProvider") + public void givenCollectionWithElements_whenRemovingElementDuringIteratorIteration_thenElementIsRemoved(List input, List expected) { + List mutableList = new ArrayList<>(input); + Iterator it = mutableList.iterator(); + while (it.hasNext()) { + String item = it.next(); + if (item.equals("unwanted")) { + it.remove(); // Safely remove item + } + } + assertIterableEquals(expected, mutableList); + } + +} diff --git a/core-java-modules/core-java-io-5/README.md b/core-java-modules/core-java-io-5/README.md index d596a7a3a7..c5054b6f5e 100644 --- a/core-java-modules/core-java-io-5/README.md +++ b/core-java-modules/core-java-io-5/README.md @@ -11,5 +11,6 @@ This module contains articles about core Java input and output (IO) - [Read and Write Files in Java Using Separate Threads](https://www.baeldung.com/java-read-write-files-different-threads) - [Convert an OutputStream to a Byte Array in Java](https://www.baeldung.com/java-outputstream-byte-array) - [Reading a .gz File Line by Line Using GZIPInputStream](https://www.baeldung.com/java-gzipinputstream-read-gz-file-line-by-line) +- [Opening HTML File Using Java](https://www.baeldung.com/java-open-html-file) - [[<-- Prev]](/core-java-modules/core-java-io-4) diff --git a/core-java-modules/core-java-io-5/src/test/java/com/baeldung/printwriterwritevsprint/WriteVsPrintUnitTest.java b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/printwriterwritevsprint/WriteVsPrintUnitTest.java new file mode 100644 index 0000000000..ad9c0f4619 --- /dev/null +++ b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/printwriterwritevsprint/WriteVsPrintUnitTest.java @@ -0,0 +1,113 @@ +package com.baeldung.printwriterwritevsprint; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class WriteVsPrintUnitTest { + + Object outputFromPrintWriter; + Object outputFromPrintWriter() { + try (BufferedReader br = new BufferedReader(new FileReader("output.txt"))){ + outputFromPrintWriter = br.readLine(); + } catch (IOException e){ + e.printStackTrace(); + Assertions.fail(); + } + return outputFromPrintWriter; + } + + @Test + void whenUsingWriteInt_thenASCIICharacterIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.write(48); + printWriter.close(); + + assertEquals("0", outputFromPrintWriter()); + } + + @Test + void whenUsingWriteCharArrayFromOffset_thenCharArrayIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.write(new char[]{'A','/','&','4','E'}, 1, 4 ); + printWriter.close(); + + assertEquals("/&4E", outputFromPrintWriter()); + } + + @Test + void whenUsingWriteStringFromOffset_thenLengthOfStringIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.write("StringExample", 6, 7 ); + printWriter.close(); + + assertEquals("Example", outputFromPrintWriter()); + } + + @Test + void whenUsingPrintBoolean_thenStringValueIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.print(true); + printWriter.close(); + + assertEquals("true", outputFromPrintWriter()); + } + + @Test + void whenUsingPrintChar_thenCharIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.print('A'); + printWriter.close(); + + assertEquals("A", outputFromPrintWriter()); + } + + @Test + void whenUsingPrintInt_thenValueOfIntIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.print(420); + printWriter.close(); + + assertEquals("420", outputFromPrintWriter()); + } + + @Test + void whenUsingPrintString_thenStringIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + printWriter.print("RandomString"); + printWriter.close(); + + assertEquals("RandomString", outputFromPrintWriter()); + } + + @Test + void whenUsingPrintObject_thenObjectToStringIsPrinted() throws FileNotFoundException { + + PrintWriter printWriter = new PrintWriter("output.txt"); + + Map example = new HashMap(); + + printWriter.print(example); + printWriter.close(); + + assertEquals(example.toString(), outputFromPrintWriter()); + } +} \ No newline at end of file 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 410c164496..dd71f2b53b 100644 --- a/core-java-modules/core-java-io-apis-2/pom.xml +++ b/core-java-modules/core-java-io-apis-2/pom.xml @@ -20,28 +20,6 @@ ${lombok.version} provided - - org.junit.jupiter - junit-jupiter-engine - 5.7.2 - test - - - org.junit.jupiter - junit-jupiter - - - org.junit.jupiter - junit-jupiter - - - org.junit.jupiter - junit-jupiter - - - org.junit.jupiter - junit-jupiter - org.junit.jupiter @@ -63,18 +41,6 @@ ${junit-jupiter-version} test - - org.junit.jupiter - junit-jupiter - - - org.junit.jupiter - junit-jupiter - - - org.junit.jupiter - junit-jupiter - org.testng testng diff --git a/core-java-modules/core-java-jar/pom.xml b/core-java-modules/core-java-jar/pom.xml index 460adf45e7..e87fba922e 100644 --- a/core-java-modules/core-java-jar/pom.xml +++ b/core-java-modules/core-java-jar/pom.xml @@ -260,7 +260,6 @@ 0.4 1.8.7 - 4.6.1 1.1 3.6.2 diff --git a/core-java-modules/core-java-lang-oop-others/README.md b/core-java-modules/core-java-lang-oop-others/README.md index ffd1d47f79..e4970553bd 100644 --- a/core-java-modules/core-java-lang-oop-others/README.md +++ b/core-java-modules/core-java-lang-oop-others/README.md @@ -10,3 +10,4 @@ This module contains articles about Object Oriented Programming (OOP) in Java - [Law of Demeter in Java](https://www.baeldung.com/java-demeter-law) - [Java Interface Naming Conventions](https://www.baeldung.com/java-interface-naming-conventions) - [Difference Between Information Hiding and Encapsulation](https://www.baeldung.com/java-information-hiding-vs-encapsulation) +- [Statements Before super() in Java](https://www.baeldung.com/java-statements-before-super-constructor) diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/printnullvalues/Employee.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/printnullvalues/Employee.java new file mode 100644 index 0000000000..b4cd62897b --- /dev/null +++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/printnullvalues/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.printnullvalues; + +import java.util.Objects; +import java.util.Optional; + +public class Employee { + private String name; + private int age; + private String department; + + public Employee(String name, int age, String department) { + this.name = name; + this.age = age; + this.department = department; + } + + public String toStringUsingNullCheck() { + return "Name: " + (name != null ? name : "Unknown") + + ", Age: " + age + + ", Department: " + (department != null ? department : "Unknown"); + } + + public String toStringUsingOptional() { + return "Name: " + Optional.ofNullable(name).orElse("Unknown") + + ", Age: " + age + + ", Department: " + Optional.ofNullable(department).orElse("Unknown"); + } + + private String getDefaultIfNull(String value, String defaultValue) { + return value != null ? value : defaultValue; + } + + public String toStringUsingCustomHelper() { + return "Name: " + getDefaultIfNull(name, "Unknown") + + ", Age: " + age + + ", Department: " + getDefaultIfNull(department, "Unknown"); + } + + public String toStringUsingObjects() { + return "Name: " + Objects.toString(name, "Unknown") + + ", Age: " + age + + ", Department: " + Objects.toString(department, "Unknown"); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-others/src/test/java/com/baeldung/printnullvalues/PrintingNullValuesUnitTest.java b/core-java-modules/core-java-lang-oop-others/src/test/java/com/baeldung/printnullvalues/PrintingNullValuesUnitTest.java new file mode 100644 index 0000000000..7526cd9ac4 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-others/src/test/java/com/baeldung/printnullvalues/PrintingNullValuesUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.printnullvalues; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PrintingNullValuesUnitTest { + Employee employee = new Employee(null, 30, null); + String expected = "Name: Unknown, Age: 30, Department: Unknown"; + + @Test + public void givenNullValues_whenToStringUsingNullCheck_thenCorrectStringReturned() { + assertEquals(expected, employee.toStringUsingNullCheck()); + } + + @Test + public void givenNullValues_whenToStringUsingOptional_thenCorrectStringReturned() { + assertEquals(expected, employee.toStringUsingOptional()); + } + + @Test + public void givenNullValues_whenToStringUsingCustomHelper_thenCorrectStringReturned() { + assertEquals(expected, employee.toStringUsingCustomHelper()); + } + + @Test + public void givenNullValues_whenToStringUsingObjects_thenCorrectStringReturned() { + assertEquals(expected, employee.toStringUsingObjects()); + } +} diff --git a/core-java-modules/core-java-networking-5/README.md b/core-java-modules/core-java-networking-5/README.md new file mode 100644 index 0000000000..5d69c73138 --- /dev/null +++ b/core-java-modules/core-java-networking-5/README.md @@ -0,0 +1,2 @@ +## Relevant Articles: +- [[<-- Prev]](/core-java-modules/core-java-networking-4) diff --git a/core-java-modules/core-java-networking-5/pom.xml b/core-java-modules/core-java-networking-5/pom.xml new file mode 100644 index 0000000000..978a294204 --- /dev/null +++ b/core-java-modules/core-java-networking-5/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + core-java-networking-5 + jar + core-java-networking-5 + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + + + + + commons-validator + commons-validator + ${commons-validator.version} + + + org.jsoup + jsoup + ${jsoup.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + javax.ws.rs + javax.ws.rs-api + ${javax.ws.rs-api.version} + + + org.glassfish.jersey.core + jersey-common + ${jersey-common.version} + test + + + org.springframework + spring-web + ${spring-web.version} + + + + + 1.7 + 1.17.2 + 4.5.2 + 2.1.1 + 2.22.2 + 6.0.6 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-networking-5/src/test/java/com/baeldung/redirectedurl/RedirectedUrlUnitTest.java b/core-java-modules/core-java-networking-5/src/test/java/com/baeldung/redirectedurl/RedirectedUrlUnitTest.java new file mode 100644 index 0000000000..1fc1dc3699 --- /dev/null +++ b/core-java-modules/core-java-networking-5/src/test/java/com/baeldung/redirectedurl/RedirectedUrlUnitTest.java @@ -0,0 +1,57 @@ +package com.baeldung.redirectedurl; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +import static org.junit.Assert.assertEquals; + +public class RedirectedUrlUnitTest { + String canonicalUrl = "http://www.baeldung.com/"; + String expectedRedirectedUrl = "https://www.baeldung.com/"; + + @Test + public void givenOriginalUrl_whenFindRedirectUrlUsingHttpURLConnection_thenCorrectRedirectedUrlReturned() throws IOException { + URL url = new URL(canonicalUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setInstanceFollowRedirects(true); + int status = connection.getResponseCode(); + String redirectedUrl = null; + if (status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_MOVED_TEMP) { + redirectedUrl = connection.getHeaderField("Location"); + } + connection.disconnect(); + assertEquals(expectedRedirectedUrl, redirectedUrl); + } + + @Test + public void givenOriginalUrl_whenFindRedirectUrlUsingHttpClient_thenCorrectRedirectedUrlReturned() throws IOException { + RequestConfig config = RequestConfig.custom() + .setRedirectsEnabled(false) + .build(); + try (CloseableHttpClient httpClient = HttpClients.custom() + .setDefaultRequestConfig(config) + .build()) { + HttpGet httpGet = new HttpGet(canonicalUrl); + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + int statusCode = response.getStatusLine().getStatusCode(); + String redirectedUrl = null; + if (statusCode == HttpURLConnection.HTTP_MOVED_PERM || statusCode == HttpURLConnection.HTTP_MOVED_TEMP) { + org.apache.http.Header[] headers = response.getHeaders("Location"); + if (headers.length > 0) { + redirectedUrl = headers[0].getValue(); + } + } + assertEquals(expectedRedirectedUrl, redirectedUrl); + } + } + } + +} diff --git a/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/complexnumbers/ComplexNumber.java b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/complexnumbers/ComplexNumber.java new file mode 100644 index 0000000000..8e509cfbbb --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/main/java/com/baeldung/complexnumbers/ComplexNumber.java @@ -0,0 +1,57 @@ +package com.baeldung.complexnumbers; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public record ComplexNumber(double real, double imaginary) { + + public static ComplexNumber fromString(String complexNumberStr) { + + Pattern pattern = Pattern.compile("(-?\\d*\\.?\\d+)?(?:([+-]?\\d*\\.?\\d+)i)?"); + Matcher matcher = pattern.matcher(complexNumberStr.replaceAll("\\s", "")); + + if (matcher.matches()) { + // Extract real and imaginary parts + String realPartStr = matcher.group(1); + String imaginaryPartStr = matcher.group(2); + + // Parse real part (if present) + double real = (realPartStr != null) ? Double.parseDouble(realPartStr) : 0; + + // Parse imaginary part (if present) + double imaginary = (imaginaryPartStr != null) ? Double.parseDouble(imaginaryPartStr) : 0; + return new ComplexNumber(real, imaginary); + } else { + throw new IllegalArgumentException("Invalid complex number format(" + complexNumberStr + "), supported format is `a+bi`"); + } + } + + public String toString() { + return real + "+" + imaginary + "i"; + } + + public ComplexNumber add(ComplexNumber that) { + return new ComplexNumber(real + that.real, imaginary + that.imaginary); + } + + public ComplexNumber multiply(ComplexNumber that) { + double newReal = this.real * that.real - this.imaginary * that.imaginary; + double newImaginary = this.real * that.imaginary + this.imaginary * that.real; + return new ComplexNumber(newReal, newImaginary); + } + + public ComplexNumber subtract(ComplexNumber that) { + return new ComplexNumber(real - that.real, imaginary - that.imaginary); + } + + public ComplexNumber divide(ComplexNumber that) { + if(that.real == 0 && that.imaginary == 0 ){ + throw new ArithmeticException("Division by 0 is not allowed!"); + } + double c2d2 = Math.pow(that.real, 2) + Math.pow(that.imaginary, 2); + double newReal = (this.real * that.real + this.imaginary * that.imaginary) / c2d2; + double newImaginary = (this.imaginary * that.real - this.real * that.imaginary) / c2d2; + return new ComplexNumber(newReal, newImaginary); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/complexnumbers/ComplexNumberOperationsUnitTest.java b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/complexnumbers/ComplexNumberOperationsUnitTest.java new file mode 100644 index 0000000000..b2b7253fb8 --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/complexnumbers/ComplexNumberOperationsUnitTest.java @@ -0,0 +1,103 @@ +package com.baeldung.complexnumbers; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class ComplexNumberOperationsUnitTest { + + @ParameterizedTest(name = "Multiplying {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, -11+23i", + "2, 4, 8", + "2, 4i, 8i", + "1+1i, 1+1i, 0+2i", + " 3+2i, 1 + 7i, -11 + 23i ", + "0+5i, 3+0i, 0+15i", + "0+0i, -2+0i, 0+0i", + "-3+2i, 1-7i, 11+23i", + "2+4i, 0, 0" + }) + public void givenTwoComplexNumbers_multiplyAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber product = complex1.multiply(complex2); + Assertions.assertTrue(isSame(product, expected)); + } + + @ParameterizedTest(name = "Adding {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, 4+9i", + "2, 4, 6", + "2, 4i, 2+4i", + "1+1i, 1+1i, 2+2i", + " 3+2i, 1 + 7i, 4 + 9i ", + "0+5i, 3+0i, 3+5i", + "0+0i, -2+0i, -2+0i", + "-3+2i, 1-7i, -2-5i", + "2+4i, 0, 2+4i" + }) + public void givenTwoComplexNumbers_addThemAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber sum = complex1.add(complex2); + Assertions.assertTrue(isSame(sum, expected)); + } + + @ParameterizedTest(name = "Subtracting {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, 2-5i", + "2, 4, -2", + "2, 4i, 2-4i", + "1+1i, 1+1i, 0", + " 3+ 2i, 1+ 7i, 2-5i", + "0+5i, 3+0i, -3+5i", + "0+0i, -2+0i, 2+0i", + "-3+2i, 1-7i, -4+9i", + "2+4i, 0, 2+4i" + }) + public void givenTwoComplexNumbers_subtractAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber sum = complex1.subtract(complex2); + Assertions.assertTrue(isSame(sum, expected)); + } + + @ParameterizedTest(name = "Dividing {0} and {1}") + @CsvSource({ + "3+2i, 1+7i, 0.34-0.38i", + "2, 4, 0.5", + "2, 4i, 0-0.5i", + "1+1i, 1+1i, 1", + "3 + 2i, 1 + 7i, 0.34-0.38i", + "0+5i, 3+0i, 0+1.6666666666666667i", + "0+0i, -2+0i, 0+0i", + "-3+2i, 1-7i, -0.34-0.38i", + "2+4i, 1, 2+4i" + }) + public void givenTwoComplexNumbers_divideThemAndGetResult(String complexStr1, String complexStr2, String expectedStr) { + ComplexNumber complex1 = ComplexNumber.fromString(complexStr1); + ComplexNumber complex2 = ComplexNumber.fromString(complexStr2); + ComplexNumber expected = ComplexNumber.fromString(expectedStr); + ComplexNumber sum = complex1.divide(complex2); + Assertions.assertTrue(isSame(sum, expected)); + } + + @Test + public void givenAComplexNumberAsZero_handleDivideByZeroScenario() { + ComplexNumber complex1 = new ComplexNumber(1, 1); + ComplexNumber zero = new ComplexNumber(0, 0); + Exception exception = Assertions.assertThrows(ArithmeticException.class, () -> { + complex1.divide(zero); + }); + Assertions.assertEquals(exception.getMessage(), "Division by 0 is not allowed!"); + } + + public boolean isSame(ComplexNumber result, ComplexNumber expected) { + return result.real() == expected.real() && result.imaginary() == expected.imaginary(); + } +} diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/symmetricsubstringlength/SymmetricSubstringMaxLengthUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/symmetricsubstringlength/SymmetricSubstringMaxLengthUnitTest.java index 2ae37862dd..ff94aeaea8 100644 --- a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/symmetricsubstringlength/SymmetricSubstringMaxLengthUnitTest.java +++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/symmetricsubstringlength/SymmetricSubstringMaxLengthUnitTest.java @@ -5,73 +5,70 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; public class SymmetricSubstringMaxLengthUnitTest { - String input = "<>>"; + String input = "abba"; int expected = 4; - @Test - public void givenString_whenUsingSymmetricSubstringExpansion_thenFindLongestSymmetricSubstring() { - int start = 0; - int mid = 0; - int last_gt = 0; - int end = 0; - int best = 0; + static int findLongestSymmetricSubstringUsingSymmetricApproach(String str) { + int maxLength = 1; - while (start < input.length()) { - int current = Math.min(mid - start, end - mid); - if (best < current) { - best = current; - } - - if (end - mid == current && end < input.length()) { - if (input.charAt(end) == '?') { - end++; - } else if (input.charAt(end) == '>') { - end++; - last_gt = end; - } else { - end++; - mid = end; - start = Math.max(start, last_gt); + for (int i = 0; i < str.length(); i++) { + for (int j = i; j < str.length(); j++) { + int flag = 1; + for (int k = 0; k < (j - i + 1) / 2; k++) { + if (str.charAt(i + k) != str.charAt(j - k)) { + flag = 0; + break; + } + } + if (flag != 0 && (j - i + 1) > maxLength) { + maxLength = j - i + 1; } - } else if (mid < input.length() && input.charAt(mid) == '?') { - mid++; - } else if (start < mid) { - start++; - } else { - start = Math.max(start, last_gt); - mid++; - end = Math.max(mid, end); } } - int result = 2 * best; - - assertEquals(expected, result); + return maxLength; } @Test public void givenString_whenUsingBruteForce_thenFindLongestSymmetricSubstring() { - int max = 0; - for (int i = 0; i < input.length(); i++) { - for (int j = i + 1; j <= input.length(); j++) { - String t = input.substring(i, j); - if (t.length() % 2 == 0) { - int k = 0, l = t.length() - 1; - boolean isSym = true; - while (k < l && isSym) { - if (!(t.charAt(k) == '<' || t.charAt(k) == '?') && (t.charAt(l) == '>' || t.charAt(l) == '?')) { - isSym = false; - } - k++; - l--; - } - if (isSym) { - max = Math.max(max, t.length()); - } + assertEquals(expected, findLongestSymmetricSubstringUsingBruteForce(input).length()); + } + + @Test + public void givenString_whenUsingSymmetricSubstring_thenFindLongestSymmetricSubstring() { + assertEquals(expected, findLongestSymmetricSubstringUsingSymmetricApproach(input)); + } + + private String findLongestSymmetricSubstringUsingBruteForce(String str) { + if (str == null || str.length() == 0) { + return ""; + } + + int maxLength = 0; + String longestPalindrome = ""; + + for (int i = 0; i < str.length(); i++) { + for (int j = i + 1; j <= str.length(); j++) { + String substring = str.substring(i, j); + if (isPalindrome(substring) && substring.length() > maxLength) { + maxLength = substring.length(); + longestPalindrome = substring; } } } - assertEquals(expected, max); + return longestPalindrome; } + private boolean isPalindrome(String s) { + int left = 0; + int right = s.length() - 1; + while (left < right) { + if (s.charAt(left) != s.charAt(right)) { + return false; + } + left++; + right--; + } + return true; + } } diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index f6c5f8191a..00c40151e4 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -165,6 +165,7 @@ core-java-networking core-java-networking-2 core-java-networking-4 + core-java-networking-5 core-java-nio core-java-nio-2 core-java-numbers diff --git a/graphql-modules/pom.xml b/graphql-modules/pom.xml index 2525f75eff..0d01798556 100644 --- a/graphql-modules/pom.xml +++ b/graphql-modules/pom.xml @@ -20,7 +20,7 @@ org.springframework.boot spring-boot-dependencies - 2.6.4 + 2.6.15 pom import @@ -34,4 +34,11 @@ graphql-spqr-boot-starter + + 1.7.32 + 1.2.7 + + 4.4.0 + + \ No newline at end of file diff --git a/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java b/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java new file mode 100644 index 0000000000..f3a4491adf --- /dev/null +++ b/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java @@ -0,0 +1,41 @@ +package com.baeldung.imageprocessing.imagetobufferedimage; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +public class ImageToBufferedImage { + + // Method 1: Using BufferedImage Constructor + public BufferedImage convertUsingConstructor(Image image) throws IllegalArgumentException { + int width = image.getWidth(null); + int height = image.getHeight(null); + if (width <= 0 || height <= 0) { + throw new IllegalArgumentException("Image dimensions are invalid"); + } + BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + bufferedImage.getGraphics().drawImage(image, 0, 0, null); + return bufferedImage; + } + + // Method 2: Casting Image to BufferedImage + public BufferedImage convertUsingCasting(Image image) throws ClassCastException { + if (image instanceof BufferedImage) { + return (BufferedImage) image; + } else { + throw new ClassCastException("Image type is not compatible with BufferedImage"); + } + } + + // Method 3: Using ImageIO Class + public BufferedImage convertUsingImageIO(String filePath) throws IOException { + try { + File file = new File(filePath); + return ImageIO.read(file); + } catch (Exception e) { + throw new IOException("Error reading image file: " + e.getMessage()); + } + } +} diff --git a/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageUnitTest.java b/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageUnitTest.java new file mode 100644 index 0000000000..74b16e2501 --- /dev/null +++ b/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.image.resize.imagetobufferedimage; + +import com.baeldung.imageprocessing.imagetobufferedimage.ImageToBufferedImage; +import org.junit.Test; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ImageToBufferedImageUnitTest { + Image image = ImageIO.read(new File("src/main/resources/images/sampleImage.jpg")); + + public ImageToBufferedImageUnitTest() throws IOException { + } + + @Test + public void whenConvertUsingConstructorWithValidDimensions_thenImageGeneratedWithoutError() { + ImageToBufferedImage converter = new ImageToBufferedImage(); + BufferedImage bufferedImage = converter.convertUsingConstructor(image); + assertNotNull(bufferedImage); + assertEquals(image.getWidth(null), bufferedImage.getWidth()); + assertEquals(image.getHeight(null), bufferedImage.getHeight()); + } + + @Test(expected = IllegalArgumentException.class) + public void whenConvertUsingConstructorWithInvalidDimensions_thenImageGeneratedWithError() { + ImageToBufferedImage converter = new ImageToBufferedImage(); + converter.convertUsingConstructor(new BufferedImage(-100, -100, BufferedImage.TYPE_INT_ARGB)); + } + + @Test + public void whenConvertUsingCastingWithCompatibleImageType_thenImageGeneratedWithoutError() { + ImageToBufferedImage converter = new ImageToBufferedImage(); + BufferedImage bufferedImage = converter.convertUsingCasting(image); + assertNotNull(bufferedImage); + assertEquals(image.getWidth(null), bufferedImage.getWidth()); + assertEquals(image.getHeight(null), bufferedImage.getHeight()); + } + + @Test(expected = ClassCastException.class) + public void whenConvertUsingCastingWithIncompatibleImageType_thenImageGeneratedWithError() { + ImageToBufferedImage converter = new ImageToBufferedImage(); + // PNG format is not directly supported by BufferedImage + Image image = new ImageIcon("src/main/resources/images/baeldung.png").getImage(); + converter.convertUsingCasting(image); + } + + @Test + public void whenConvertUsingImageIOWithValidFile_thenImageGeneratedWithoutError() throws IOException { + ImageToBufferedImage converter = new ImageToBufferedImage(); + BufferedImage bufferedImage = converter.convertUsingImageIO("src/main/resources/images/sampleImage.jpg"); + assertNotNull(bufferedImage); + assertEquals(image.getWidth(null), bufferedImage.getWidth()); + assertEquals(image.getHeight(null), bufferedImage.getHeight()); + } + + @Test(expected = IOException.class) + public void whenConvertUsingImageIOWithInvalidFile_thenImageGeneratedWithError() throws IOException { + ImageToBufferedImage converter = new ImageToBufferedImage(); + converter.convertUsingImageIO("invalid_file.jpg"); + } +} + diff --git a/jackson-modules/jackson-annotations/pom.xml b/jackson-modules/jackson-annotations/pom.xml index 158b5b189a..3097656961 100644 --- a/jackson-modules/jackson-annotations/pom.xml +++ b/jackson-modules/jackson-annotations/pom.xml @@ -60,7 +60,7 @@ 2.1.214 5.4.0 - 2.5.0 + 3.1.5 \ No newline at end of file diff --git a/jackson-modules/jackson-annotations/src/main/java/com/baeldung/jackson/jsonignorevstransient/User.java b/jackson-modules/jackson-annotations/src/main/java/com/baeldung/jackson/jsonignorevstransient/User.java index c12e5225db..5031c8d047 100644 --- a/jackson-modules/jackson-annotations/src/main/java/com/baeldung/jackson/jsonignorevstransient/User.java +++ b/jackson-modules/jackson-annotations/src/main/java/com/baeldung/jackson/jsonignorevstransient/User.java @@ -1,9 +1,9 @@ package com.baeldung.jackson.jsonignorevstransient; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import java.io.Serializable; @Entity diff --git a/jhipster-modules/jhipster-microservice/car-app/pom.xml b/jhipster-modules/jhipster-microservice/car-app/pom.xml index 2fee5148a0..b53245f751 100644 --- a/jhipster-modules/jhipster-microservice/car-app/pom.xml +++ b/jhipster-modules/jhipster-microservice/car-app/pom.xml @@ -31,9 +31,9 @@ 1.1.0 0.12.3 1.0.0 - 3.6 + 4.27.0 2.0.0 - 3.6.2 + 4.27.0 4.8 jdt_apt 1.1.0.Final diff --git a/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml b/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml index 2a1ee4d6bf..97b2a70aa8 100644 --- a/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml +++ b/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml @@ -1,10 +1,6 @@ - + diff --git a/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml b/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml index 0b8c3f5136..db2af1ac89 100644 --- a/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml +++ b/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/changelog/20170503041524_added_entity_Car.xml @@ -1,10 +1,6 @@ - + @@ -36,6 +32,6 @@ - + diff --git a/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml b/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml index 398b615ea1..1464b50cb8 100644 --- a/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml +++ b/jhipster-modules/jhipster-microservice/car-app/src/main/resources/config/liquibase/master.xml @@ -1,9 +1,6 @@ - - + diff --git a/libraries-http-2/pom.xml b/libraries-http-2/pom.xml index 934e0d2900..fa6b65f79f 100644 --- a/libraries-http-2/pom.xml +++ b/libraries-http-2/pom.xml @@ -85,7 +85,7 @@ org.mockito mockito-inline - ${mockito.version} + ${mockito-inline.version} test @@ -120,6 +120,7 @@ 1.0.3 3.6.0 1.49 + 5.2.0 \ No newline at end of file diff --git a/libraries-stream/pom.xml b/libraries-stream/pom.xml index 6cd931c299..fea437db6b 100644 --- a/libraries-stream/pom.xml +++ b/libraries-stream/pom.xml @@ -49,11 +49,23 @@ 0.9.12 - 2.6.0 + 3.0.0 0.9.0 8.2.0 0.8.1 1.15 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + + + + diff --git a/libraries-stream/src/test/java/com/baeldung/parallel_collectors/ParallelCollectorsVirtualThreadsManualTest.java b/libraries-stream/src/test/java/com/baeldung/parallel_collectors/ParallelCollectorsVirtualThreadsManualTest.java new file mode 100644 index 0000000000..3038fb74f9 --- /dev/null +++ b/libraries-stream/src/test/java/com/baeldung/parallel_collectors/ParallelCollectorsVirtualThreadsManualTest.java @@ -0,0 +1,73 @@ +package com.baeldung.parallel_collectors; + +import com.pivovarit.collectors.ParallelCollectors; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.Executors; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; + +public class ParallelCollectorsVirtualThreadsManualTest { + + private static final Logger log = LoggerFactory.getLogger(ParallelCollectorsVirtualThreadsManualTest.class); + + // increase the number of parallel processes to find the max number of threads on your machine + @Test + public void givenParallelism_whenUsingOSThreads_thenShouldRunOutOfThreads() { + int parallelProcesses = 50_000; + + var e = Executors.newFixedThreadPool(parallelProcesses); + + var result = timed(() -> Stream.iterate(0, i -> i + 1).limit(parallelProcesses) + .collect(ParallelCollectors.parallel(i -> fetchById(i), toList(), e, parallelProcesses)) + .join()); + + log.info("{}", result); + } + + @Test + public void givenParallelism_whenUsingVThreads_thenShouldProcessInParallel() { + int parallelProcesses = 1000_000; + + var result = timed(() -> Stream.iterate(0, i -> i + 1).limit(parallelProcesses) + .collect(ParallelCollectors.parallel(i -> fetchById(i), toList())) + .join()); + + log.info("{}", result); + } + + @Test + public void givenParallelismAndPCollectors2_whenUsingVThreads_thenShouldProcessInParallel() { + int parallelProcesses = 1000_000; + + var result = timed(() -> Stream.iterate(0, i -> i + 1).limit(parallelProcesses) + .collect(ParallelCollectors.parallel(i -> fetchById(i), toList(), Executors.newVirtualThreadPerTaskExecutor(), Integer.MAX_VALUE)) + .join()); + + log.info("{}", result); + } + + private static String fetchById(int id) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore shamelessly + } + + return "user-" + id; + } + + private static T timed(Supplier supplier) { + var before = Instant.now(); + T result = supplier.get(); + var after = Instant.now(); + log.info("Execution time: {} ms", Duration.between(before, after).toMillis()); + return result; + } +} diff --git a/logging-modules/logback/pom.xml b/logging-modules/logback/pom.xml index 376e75786e..557875d570 100644 --- a/logging-modules/logback/pom.xml +++ b/logging-modules/logback/pom.xml @@ -78,40 +78,20 @@ - - - integration-lite-first - - - - org.apache.maven.plugins - maven-surefire-plugin - - - ${project.basedir}/src/test/resources/logback-test.xml - - - - - - - - integration-lite-second - - - - org.apache.maven.plugins - maven-surefire-plugin - - - ${project.basedir}/src/test/resources/logback-test.xml - - - - - - - + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.basedir}/src/test/resources/logback-test.xml + + + + + 20240303 diff --git a/mapstruct/README.md b/mapstruct/README.md index dd2a3bddd8..81ba8a2c45 100644 --- a/mapstruct/README.md +++ b/mapstruct/README.md @@ -12,3 +12,5 @@ This module contains articles about MapStruct. - [Use Mapper in Another Mapper with Mapstruct and Java](https://www.baeldung.com/java-mapstruct-nested-mapping) - [Throw Exception for Unexpected Input for Enum With MapStruct](https://www.baeldung.com/java-mapstruct-enum-unexpected-input-exception) - [How to Use Conditional Mapping With MapStruct](https://www.baeldung.com/java-mapstruct-bean-types-conditional) +- [Mapping Enum With MapStruct](https://www.baeldung.com/java-mapstruct-enum) + diff --git a/messaging-modules/spring-jms/pom.xml b/messaging-modules/spring-jms/pom.xml index aad416433d..0df1e9fff2 100644 --- a/messaging-modules/spring-jms/pom.xml +++ b/messaging-modules/spring-jms/pom.xml @@ -44,7 +44,7 @@ org.mockito mockito-core - ${mockito-core.version} + ${mockito.version} test @@ -83,7 +83,6 @@ 5.14.1 1.5.10.RELEASE 3.3.2 - 4.6.1 5.16.5 1.17.3 5.10.1 diff --git a/microservices-modules/event-driven-microservice/pom.xml b/microservices-modules/event-driven-microservice/pom.xml index a1ba8d6e35..6b6df3b14b 100644 --- a/microservices-modules/event-driven-microservice/pom.xml +++ b/microservices-modules/event-driven-microservice/pom.xml @@ -34,7 +34,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${spring.webmvc.version} + ${springdoc-openapi-webmvc-ui.version} @@ -71,6 +71,7 @@ 17 2.0.8 2.1.0 + 2.5.0 diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index 9b40dbbe8e..fe70964e98 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -107,6 +107,8 @@ 2.7.11 1.9.20.1 8.2.0 + 1.7.32 + 1.2.7 \ No newline at end of file diff --git a/parent-boot-3/pom.xml b/parent-boot-3/pom.xml index d4ca41291d..bb4d170894 100644 --- a/parent-boot-3/pom.xml +++ b/parent-boot-3/pom.xml @@ -47,12 +47,12 @@ org.slf4j slf4j-api - ${slf4j.version} + ${org.slf4j.version} org.slf4j jcl-over-slf4j - ${slf4j.version} + ${org.slf4j.version} org.springframework.boot @@ -232,8 +232,6 @@ 3.1.5 5.8.2 0.9.17 - 1.4.4 - 2.0.3 diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index d03eb3def6..5a1c2f6c97 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -15,13 +15,75 @@ 1.0.0-SNAPSHOT - - - org.springframework - spring-core - ${spring.version} - - + + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-test + ${spring.version} + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-web + ${spring.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + org.springframework + spring-orm + ${spring.version} + + + org.springframework + spring-websocket + ${spring.version} + + + org.springframework + spring-messaging + ${spring.version} + + + org.springframework + spring-aspects + ${spring.version} + + + org.springframework + spring-expression + ${spring.version} + + + org.springframework + spring-tx + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + 5.3.28 diff --git a/patterns-modules/design-patterns-architectural/pom.xml b/patterns-modules/design-patterns-architectural/pom.xml index ec7dae42b3..276e2a41a9 100644 --- a/patterns-modules/design-patterns-architectural/pom.xml +++ b/patterns-modules/design-patterns-architectural/pom.xml @@ -72,6 +72,8 @@ 5.5.14 3.20.4 3.14.0 + 1.7.32 + 1.2.7 \ No newline at end of file diff --git a/patterns-modules/design-patterns-creational-2/pom.xml b/patterns-modules/design-patterns-creational-2/pom.xml index 27c83c9eb7..bfb8f3ff7c 100644 --- a/patterns-modules/design-patterns-creational-2/pom.xml +++ b/patterns-modules/design-patterns-creational-2/pom.xml @@ -16,9 +16,18 @@ org.mockito mockito-inline - ${mockito.version} + ${mockito-inline.version} test + + org.projectlombok + lombok + 1.18.32 + - \ No newline at end of file + + 5.2.0 + + + diff --git a/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/GenericBuilder.java b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/GenericBuilder.java new file mode 100644 index 0000000000..6159f92189 --- /dev/null +++ b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/GenericBuilder.java @@ -0,0 +1,29 @@ +package com.baeldung.builder.implementation; + +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +public class GenericBuilder { + + private final Supplier supplier; + + private GenericBuilder(Supplier supplier) { + this.supplier = supplier; + } + + public static GenericBuilder of(Supplier supplier) { + return new GenericBuilder<>(supplier); + } + + public

GenericBuilder with(BiConsumer consumer, P value) { + return new GenericBuilder<>(() -> { + T object = supplier.get(); + consumer.accept(object, value); + return object; + }); + } + + public T build() { + return supplier.get(); + } +} diff --git a/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/LombokPost.java b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/LombokPost.java new file mode 100644 index 0000000000..76edf2390c --- /dev/null +++ b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/LombokPost.java @@ -0,0 +1,18 @@ +package com.baeldung.builder.implementation; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class LombokPost { + + private String title; + + private String text; + + private String category; + +} diff --git a/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/Post.java b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/Post.java new file mode 100644 index 0000000000..621618a0e6 --- /dev/null +++ b/patterns-modules/design-patterns-creational-2/src/main/java/com/baeldung/builder/implementation/Post.java @@ -0,0 +1,74 @@ +package com.baeldung.builder.implementation; + +public class Post { + + private String title; + + private String text; + + private String category; + + Post(Builder builder) { + this.title = builder.title; + this.text = builder.text; + this.category = builder.category; + } + + Post() {} + + public String getTitle() { + return title; + } + + public String getText() { + return text; + } + + public String getCategory() { + return category; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setText(String text) { + this.text = text; + } + + public void setCategory(String category) { + this.category = category; + } + + @Override + public String toString() { + return "Post{" + "title='" + title + '\'' + ", text='" + text + '\'' + ", category='" + category + '\'' + '}'; + } + + public static class Builder { + private String title; + private String text; + private String category; + + public Builder() {} + + public Builder title(String title) { + this.title = title; + return this; + } + + public Builder text(String text) { + this.text = text; + return this; + } + + public Builder category(String category) { + this.category = category; + return this; + } + + public Post build() { + return new Post(this); + } + } +} diff --git a/patterns-modules/design-patterns-creational-2/src/test/java/com/baeldung/builder/implementation/BuilderImplementationUnitTest.java b/patterns-modules/design-patterns-creational-2/src/test/java/com/baeldung/builder/implementation/BuilderImplementationUnitTest.java new file mode 100644 index 0000000000..e05d4f476a --- /dev/null +++ b/patterns-modules/design-patterns-creational-2/src/test/java/com/baeldung/builder/implementation/BuilderImplementationUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.builder.implementation; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class BuilderImplementationUnitTest { + + @Test + void givenClassicBuilder_whenBuild_thenReturnObject() { + + Post post = new Post.Builder() + .title("Java Builder Pattern") + .text("Explaining how to implement the Builder Pattern in Java") + .category("Programming") + .build(); + + assertEquals("Java Builder Pattern", post.getTitle()); + assertEquals("Explaining how to implement the Builder Pattern in Java", post.getText()); + assertEquals("Programming", post.getCategory()); + } + + @Test + void givenGenericBuilder_whenBuild_thenReturnObject() { + + Post post = GenericBuilder.of(Post::new) + .with(Post::setTitle, "Java Builder Pattern") + .with(Post::setText, "Explaining how to implement the Builder Pattern in Java") + .with(Post::setCategory, "Programming") + .build(); + + assertEquals("Java Builder Pattern", post.getTitle()); + assertEquals("Explaining how to implement the Builder Pattern in Java", post.getText()); + assertEquals("Programming", post.getCategory()); + } + + @Test + void givenLombokBuilder_whenBuild_thenReturnObject() { + + LombokPost post = LombokPost.builder() + .title("Java Builder Pattern") + .text("Explaining how to implement the Builder Pattern in Java") + .category("Programming") + .build(); + + assertEquals("Java Builder Pattern", post.getTitle()); + assertEquals("Explaining how to implement the Builder Pattern in Java", post.getText()); + assertEquals("Programming", post.getCategory()); + } +} diff --git a/patterns-modules/monkey-patching/pom.xml b/patterns-modules/monkey-patching/pom.xml index 1d0146d990..93693a7fe3 100644 --- a/patterns-modules/monkey-patching/pom.xml +++ b/patterns-modules/monkey-patching/pom.xml @@ -3,7 +3,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung monkey-patching 1.0.0-SNAPSHOT monkey-patching @@ -19,12 +18,12 @@ org.springframework.boot spring-boot-starter-web - 2.7.0 + ${spring-boot.version} org.springframework.boot spring-boot-starter-test - 2.7.0 + ${spring-boot.version} org.springframework.boot @@ -45,5 +44,7 @@ 2.7.0 + 1.7.32 + 1.2.7 diff --git a/persistence-modules/duckdb/pom.xml b/persistence-modules/duckdb/pom.xml new file mode 100644 index 0000000000..9ce4205ee6 --- /dev/null +++ b/persistence-modules/duckdb/pom.xml @@ -0,0 +1,42 @@ + + 4.0.0 + + org.baeldung + duckdb + duckdb + + + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + + + + 0.0.1-SNAPSHOT + + + com.baeldung + persistence-modules + 1.0.0-SNAPSHOT + + + + UTF-8 + 0.10.0 + + + + + org.duckdb + duckdb_jdbc + ${duckdb.version} + + + + diff --git a/persistence-modules/duckdb/src/test/java/com/baeldung/DuckDbAccess.java b/persistence-modules/duckdb/src/test/java/com/baeldung/DuckDbAccess.java new file mode 100644 index 0000000000..47c70a2256 --- /dev/null +++ b/persistence-modules/duckdb/src/test/java/com/baeldung/DuckDbAccess.java @@ -0,0 +1,198 @@ +package com.baeldung; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + + +class DuckDbAccessIntegrationTest { + + private Connection conn = null; + private Statement stmt = null; + + @BeforeAll + static void setupOnce() throws Exception { + Class.forName("org.duckdb.DuckDBDriver"); + } + + @BeforeEach + void setup() throws SQLException { + conn = DriverManager.getConnection("jdbc:duckdb:"); + stmt = conn.createStatement(); + } + + @Test + void whenQueryCurrentDate_thenReturnToday() throws SQLException { + ResultSet rs = stmt.executeQuery("SELECT current_date"); + Date currentDate = rs.next() ? rs.getDate(1) : null; + + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + Date expectedDate = calendar.getTime(); + + assertThat(currentDate).isEqualTo(expectedDate); + } + + @Test + void whenReadCsv_thenReturnHeaderAndData() throws SQLException { + String filePath = getResourceAbsolutePath("/customer.csv"); + String query = String.format("SELECT * FROM read_csv('%s')", filePath); + + ResultSet rs = stmt.executeQuery(query); + ResultSetMetaData metadata = rs.getMetaData(); + + List actualHeaderNames = new ArrayList<>(); + for (int n=1; n<=metadata.getColumnCount(); n++) { + actualHeaderNames.add(metadata.getColumnLabel(n)); + } + + // Then + List expectedHeaderNames = List.of("CustomerId", "FirstName", "LastName", "Gender"); + assertThat(actualHeaderNames).isEqualTo(expectedHeaderNames); + + int rowCount = 0; + while (rs.next()) { + rowCount++; + } + assertThat(rowCount).isEqualTo(10); + } + + @Test + void whenImportByCsv_thenReturnCorrectRowCount() throws SQLException { + // When + String filePath = getResourceAbsolutePath("/customer.csv"); + String query = String.format("CREATE TABLE customer AS SELECT * FROM read_csv('%s')", filePath); + stmt.executeUpdate(query); + + // Then + assertThat(getTableRowCount(conn, "customer")).isEqualTo(10); + } + + @Test + void whenImportByJson_thenReturnCorrectRowCount() throws SQLException { + // When + String filePath = getResourceAbsolutePath("/product.json"); + String query = String.format("CREATE TABLE product AS SELECT * FROM read_json('%s')", filePath); + stmt.executeUpdate(query); + + // Then + assertThat(getTableRowCount(conn, "product")).isEqualTo(3); + } + + @Test + void whenImportByInsert_thenReturnCorrectRowCount() throws SQLException { + // When + stmt.executeUpdate("CREATE TABLE purchase(customerId BIGINT, productId BIGINT)"); + + String query = "INSERT INTO purchase(customerId, productId) VALUES (?,?)"; + try (PreparedStatement pStmt = conn.prepareStatement(query)) { + + pStmt.setInt(1, 101); + pStmt.setInt(2, 1); + pStmt.addBatch(); + + pStmt.setInt(1, 101); + pStmt.setInt(2, 2); + pStmt.addBatch(); + + pStmt.setInt(1, 102); + pStmt.setInt(2, 2); + pStmt.addBatch(); + + pStmt.executeBatch(); + } + + // Then + assertThat(getTableRowCount(conn, "purchase")).isEqualTo(3); + } + + @Test + void whenQueryWithJoin_thenReturnCorrectCount() throws SQLException { + String customerFilePath = getResourceAbsolutePath("/customer.csv"); + String productFilePath = getResourceAbsolutePath("/product.json"); + whenImportByInsert_thenReturnCorrectRowCount(); + + String query = String.format("SELECT C.firstName, C.lastName, P.productName " + + "FROM read_csv('%s') AS C, read_json('%s') AS P, purchase S " + + "WHERE S.customerId = C.customerId " + + "AND S.productId = P.productId ", + customerFilePath, productFilePath); + + int count = 0; + ResultSet rs = stmt.executeQuery(query); + while (rs.next()) { + count++; + } + + assertThat(count).isEqualTo(3); + } + + @Test + void whenExportData_thenFileIsCreated() throws IOException, SQLException { + createPurchaseView(conn); + + File tempFile = File.createTempFile("temp", ""); + String exportFilePath = tempFile.getAbsolutePath(); + String query = String.format("COPY purchase_view TO '%s'", exportFilePath); + stmt.executeUpdate(query); + + assertThat(tempFile.length()).isGreaterThan(0); + tempFile.delete(); + } + + @AfterEach + void tearDown() throws SQLException { + stmt.close(); + conn.close(); + } + + private String getResourceAbsolutePath(String name) { + return this.getClass().getResource(name).getPath().replaceFirst("/", ""); + } + + private int getTableRowCount(Connection conn, String tableName) throws SQLException { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery(String.format("SELECT COUNT(*) FROM %s", tableName)); + return (rs.next()) ? rs.getInt(1) : 0; + } + } + + private void createPurchaseView(Connection conn) throws SQLException { + whenImportByCsv_thenReturnCorrectRowCount(); + whenImportByJson_thenReturnCorrectRowCount(); + whenImportByInsert_thenReturnCorrectRowCount(); + + String query = "CREATE VIEW purchase_view AS " + + "SELECT P.productName, COUNT(*) AS purchaseCount " + + "FROM customer C, product P, purchase S " + + "WHERE S.customerId = C.customerId " + + "AND S.productId = P.productId " + + "GROUP BY P.productName " + + "ORDER BY COUNT(*) DESC "; + + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(query); + } + } + +} \ No newline at end of file diff --git a/persistence-modules/duckdb/src/test/resources/customer.csv b/persistence-modules/duckdb/src/test/resources/customer.csv new file mode 100644 index 0000000000..f0da8f569d --- /dev/null +++ b/persistence-modules/duckdb/src/test/resources/customer.csv @@ -0,0 +1,11 @@ +CustomerId,FirstName,LastName,Gender +101,John,Smith,Male +102,Sarah,Jones,Female +103,Michael,Johnson,Male +104,Emily,Davis,Female +105,David,Brown,Male +106,Emma,Williams,Female +107,Alexander,Miller,Male +108,Samantha,Anderson,Female +109,Matthew,Taylor,Male +110,Olivia,Thompson,Female \ No newline at end of file diff --git a/persistence-modules/duckdb/src/test/resources/product.json b/persistence-modules/duckdb/src/test/resources/product.json new file mode 100644 index 0000000000..ae3b47de28 --- /dev/null +++ b/persistence-modules/duckdb/src/test/resources/product.json @@ -0,0 +1,17 @@ +[ + { + "productId": 1, + "productName":"EZ Curl Bar", + "category": "Sports Equipment" + }, + { + "productId": 2, + "productName": "7' Barbell", + "category": "Sports Equipment" + }, + { + "productId": 3, + "productName": "Single Mouthguard - Black", + "category": "Sports Equipment" + } +] \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations-2/README.md b/persistence-modules/hibernate-annotations-2/README.md new file mode 100644 index 0000000000..9da9b37245 --- /dev/null +++ b/persistence-modules/hibernate-annotations-2/README.md @@ -0,0 +1,6 @@ +## Hibernate Annotations + +This module contains articles about Annotations used in Hibernate. + +### Relevant Articles: +- [@Subselect Annotation in Hibernate](https://www.baeldung.com/hibernate-subselect) diff --git a/persistence-modules/hibernate-annotations-2/pom.xml b/persistence-modules/hibernate-annotations-2/pom.xml new file mode 100644 index 0000000000..046fbae619 --- /dev/null +++ b/persistence-modules/hibernate-annotations-2/pom.xml @@ -0,0 +1,109 @@ + + + 4.0.0 + + hibernate-annotations-2 + 0.1-SNAPSHOT + hibernate-annotations-2 + jar + Hibernate annotations module, part 2 + + + com.baeldung + persistence-modules + 1.0.0-SNAPSHOT + + + + + + org.springframework + spring-context + ${org.springframework.version} + + + org.springframework.data + spring-data-jpa + ${org.springframework.data.version} + + + org.hibernate.orm + hibernate-core + ${hibernate-core.version} + + + org.hsqldb + hsqldb + ${hsqldb.version} + + + com.h2database + h2 + ${h2.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.hibernate.orm + hibernate-testing + ${hibernate-core.version} + + + org.hibernate.orm + hibernate-spatial + ${hibernate-core.version} + + + org.apache.tomcat + tomcat-dbcp + ${tomcat-dbcp.version} + + + + + com.google.guava + guava + ${guava.version} + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + io.hypersistence + hypersistence-utils-hibernate-60 + ${hypersistance-utils-hibernate-60.version} + + + org.liquibase + liquibase-core + ${liquibase-core.version} + + + org.projectlombok + lombok + ${lombok.version} + + + + + + 6.0.6 + 3.0.3 + 6.4.2.Final + 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-2/src/main/java/com/baeldung/hibernate/HibernateAnnotationUtil.java b/persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/HibernateAnnotationUtil.java new file mode 100644 index 0000000000..74046854e7 --- /dev/null +++ b/persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/HibernateAnnotationUtil.java @@ -0,0 +1,50 @@ +package com.baeldung.hibernate; + +import com.baeldung.hibernate.subselect.RuntimeConfiguration; +import java.util.HashMap; +import java.util.Map; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Environment; +import org.hibernate.service.ServiceRegistry; + +public class HibernateAnnotationUtil { + + private static final SessionFactory SESSION_FACTORY = buildSessionFactory(); + + /** + * Utility class + */ + private HibernateAnnotationUtil() { + } + + public static SessionFactory getSessionFactory() { + return SESSION_FACTORY; + } + + private static SessionFactory buildSessionFactory() { + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() + .applySettings(dbSettings()) + .build(); + + Metadata metadata = new MetadataSources(serviceRegistry) + .addAnnotatedClass(RuntimeConfiguration.class) + .buildMetadata(); + + return metadata.buildSessionFactory(); + } + + private static Map dbSettings() { + Map dbSettings = new HashMap<>(); + dbSettings.put(Environment.URL, "jdbc:h2:mem:spring_hibernate_one_to_many"); + dbSettings.put(Environment.USER, "sa"); + dbSettings.put(Environment.PASS, ""); + dbSettings.put(Environment.DRIVER, "org.h2.Driver"); + dbSettings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread"); + dbSettings.put(Environment.SHOW_SQL, "true"); + dbSettings.put(Environment.HBM2DDL_AUTO, "create"); + return dbSettings; + } +} diff --git a/persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/PersistenceConfig.java b/persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/PersistenceConfig.java new file mode 100644 index 0000000000..c34b77282c --- /dev/null +++ b/persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/PersistenceConfig.java @@ -0,0 +1,67 @@ +package com.baeldung.hibernate; + +import com.google.common.base.Preconditions; +import java.util.Properties; +import javax.sql.DataSource; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +public class PersistenceConfig { + + @Autowired + private Environment env; + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(dataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.hibernate" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + return sessionFactory; + } + + @Bean + public DataSource dataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.show_sql", "false"); + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java b/persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java similarity index 100% rename from persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java rename to persistence-modules/hibernate-annotations-2/src/main/java/com/baeldung/hibernate/subselect/RuntimeConfiguration.java diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml b/persistence-modules/hibernate-annotations-2/src/main/resources/migrations/V1__init.xml similarity index 100% rename from persistence-modules/hibernate-annotations/src/main/resources/migrations/V1__init.xml rename to persistence-modules/hibernate-annotations-2/src/main/resources/migrations/V1__init.xml diff --git a/persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml b/persistence-modules/hibernate-annotations-2/src/main/resources/migrations/master.xml similarity index 100% rename from persistence-modules/hibernate-annotations/src/main/resources/migrations/master.xml rename to persistence-modules/hibernate-annotations-2/src/main/resources/migrations/master.xml diff --git a/persistence-modules/hibernate-annotations-2/src/main/resources/persistence-h2.properties b/persistence-modules/hibernate-annotations-2/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..4bc5e98f56 --- /dev/null +++ b/persistence-modules/hibernate-annotations-2/src/main/resources/persistence-h2.properties @@ -0,0 +1,15 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.eventGeneratedId=sa +jdbc.user=sa +jdbc.pass= + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=true +hibernate.cache.use_query_cache=true +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory + diff --git a/persistence-modules/hibernate-annotations-2/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/hibernate-annotations-2/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..2db3ec53d5 --- /dev/null +++ b/persistence-modules/hibernate-annotations-2/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,18 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.hibernate.PersistenceConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java b/persistence-modules/hibernate-annotations-2/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java similarity index 96% rename from persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java rename to persistence-modules/hibernate-annotations-2/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java index 074468ca37..fee67240e4 100644 --- a/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java +++ b/persistence-modules/hibernate-annotations-2/src/test/java/com/baeldung/hibernate/subselect/SubselectIntegrationTest.java @@ -1,6 +1,6 @@ package com.baeldung.hibernate.subselect; -import com.baeldung.hibernate.oneToMany.config.HibernateAnnotationUtil; +import com.baeldung.hibernate.HibernateAnnotationUtil; import jakarta.persistence.criteria.Root; import liquibase.Contexts; import liquibase.LabelExpression; 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 0bf03e3fee..99410e1f76 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,7 +4,6 @@ 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; @@ -39,7 +38,6 @@ public class HibernateAnnotationUtil { .addAnnotatedClass(CartOIO.class) .addAnnotatedClass(Item.class) .addAnnotatedClass(ItemOIO.class) - .addAnnotatedClass(RuntimeConfiguration.class) .buildMetadata(); return metadata.buildSessionFactory(); diff --git a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/jointables/JoinTablesIntegrationTest.java b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/jointables/JoinTablesLiveTest.java similarity index 98% rename from persistence-modules/jooq/src/test/java/com/baeldung/jooq/jointables/JoinTablesIntegrationTest.java rename to persistence-modules/jooq/src/test/java/com/baeldung/jooq/jointables/JoinTablesLiveTest.java index 5396c27e14..a5daf53542 100644 --- a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/jointables/JoinTablesIntegrationTest.java +++ b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/jointables/JoinTablesLiveTest.java @@ -20,7 +20,7 @@ import com.baeldung.jooq.jointables.public_.tables.Book; import com.baeldung.jooq.jointables.public_.tables.Bookauthor; import com.baeldung.jooq.jointables.public_.tables.Store; -public class JoinTablesIntegrationTest { +public class JoinTablesLiveTest { static DSLContext context; diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index 7512e99441..620fbe0825 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -24,6 +24,7 @@ core-java-persistence-2 core-java-persistence-3 couchbase + duckdb elasticsearch flyway flyway-repair @@ -68,6 +69,7 @@ spring-boot-persistence-mongodb spring-boot-persistence-mongodb-2 spring-boot-persistence-mongodb-3 + spring-boot-persistence-mongodb-4 spring-data-arangodb spring-data-cassandra-test diff --git a/persistence-modules/spring-boot-persistence-4/pom.xml b/persistence-modules/spring-boot-persistence-4/pom.xml index 75b444f7cc..d4bf8ba5cb 100644 --- a/persistence-modules/spring-boot-persistence-4/pom.xml +++ b/persistence-modules/spring-boot-persistence-4/pom.xml @@ -60,6 +60,11 @@ ${lombok.version} provided + + org.springframework + spring-tx + ${spring.tx.version} + @@ -84,6 +89,7 @@ 3.2.0 1.16.1 1.18.30 + 6.1.4 \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/Account.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/Account.java new file mode 100644 index 0000000000..6bb070cad2 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/Account.java @@ -0,0 +1,23 @@ +package com.baeldung.transactionalandasync; + +import jakarta.persistence.*; +import lombok.*; + +import java.math.BigDecimal; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(of = {"id"}) +@Table(name = "account") +@Data +public class Account { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + + @Column(name = "balance") + private BigDecimal balance; +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/AccountRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/AccountRepository.java new file mode 100644 index 0000000000..a3c15e25eb --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/AccountRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.transactionalandasync; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AccountRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/AccountService.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/AccountService.java new file mode 100644 index 0000000000..d54f90e2e5 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/AccountService.java @@ -0,0 +1,41 @@ +package com.baeldung.transactionalandasync; + +import jakarta.transaction.Transactional; +import lombok.AllArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; + +@Service +@AllArgsConstructor +@Transactional +public class AccountService { + + private final AccountRepository accountRepository; + + @Async + public void transferAsync(Long depositorId, Long favoredId, BigDecimal amount) { + transfer(depositorId, favoredId, amount); + + printReceipt(); + } + + @Transactional + public void transfer(Long depositorId, Long favoredId, BigDecimal amount) { + Account depositorAccount = accountRepository.findById(depositorId) + .orElseThrow(IllegalArgumentException::new); + Account favoredAccount = accountRepository.findById(favoredId) + .orElseThrow(IllegalArgumentException::new); + + depositorAccount.setBalance(depositorAccount.getBalance().subtract(amount)); + favoredAccount.setBalance(favoredAccount.getBalance().add(amount)); + + accountRepository.save(depositorAccount); + accountRepository.save(favoredAccount); + } + + public void printReceipt() { + // logic to print the receipt + } +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/BankAccountApplication.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/BankAccountApplication.java new file mode 100644 index 0000000000..403a098df8 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/transactionalandasync/BankAccountApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.transactionalandasync; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BankAccountApplication { + public static void main(String[] args) { + SpringApplication.run(BankAccountApplication.class, args); + } + +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-4/README.md b/persistence-modules/spring-boot-persistence-mongodb-4/README.md new file mode 100644 index 0000000000..b6922eb10d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-4/README.md @@ -0,0 +1,5 @@ +# Relevant Articles + +- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime) +- [A Guide to @DBRef in MongoDB](https://www.baeldung.com/spring-mongodb-dbref-annotation) +- More articles: [[<--prev]](../spring-boot-persistence-mongodb-3) diff --git a/persistence-modules/spring-boot-persistence-mongodb-4/pom.xml b/persistence-modules/spring-boot-persistence-mongodb-4/pom.xml new file mode 100644 index 0000000000..ae387c5709 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-4/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + spring-boot-persistence-mongodb-4 + spring-boot-persistence-mongodb-4 + This is simple boot application for Spring boot persistence mongodb test + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + test + + + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/DbRefApplication.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/DbRefApplication.java similarity index 100% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/DbRefApplication.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/DbRefApplication.java diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/DbRefTester.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/DbRefTester.java similarity index 99% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/DbRefTester.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/DbRefTester.java index 58641e1258..b0c6bebd53 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/DbRefTester.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/DbRefTester.java @@ -1,5 +1,6 @@ package com.baeldung.mongodb.dbref; +import com.baeldung.mongodb.dbref.repository.PersonRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -7,8 +8,6 @@ import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; -import com.baeldung.mongodb.dbref.repository.PersonRepository; - @Component public class DbRefTester implements ApplicationRunner { diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/model/Person.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/model/Person.java similarity index 100% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/model/Person.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/model/Person.java index 7b7826e716..93f372d8ef 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/model/Person.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/model/Person.java @@ -1,11 +1,11 @@ package com.baeldung.mongodb.dbref.model; -import java.util.List; - import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.List; + @Document(collection = "Person") public class Person { diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/model/Pet.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/model/Pet.java similarity index 100% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/model/Pet.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/model/Pet.java diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/repository/PersonRepository.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/repository/PersonRepository.java similarity index 99% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/repository/PersonRepository.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/repository/PersonRepository.java index 2ef5a9dbd6..7eebf8869b 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/dbref/repository/PersonRepository.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/mongodb/dbref/repository/PersonRepository.java @@ -1,8 +1,7 @@ package com.baeldung.mongodb.dbref.repository; -import org.springframework.data.mongodb.repository.MongoRepository; - import com.baeldung.mongodb.dbref.model.Person; +import org.springframework.data.mongodb.repository.MongoRepository; public interface PersonRepository extends MongoRepository { diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java similarity index 99% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java index 4eb3872e34..cf2d24c630 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java @@ -1,15 +1,14 @@ package com.baeldung.zoneddatetime.config; -import java.util.ArrayList; -import java.util.List; - +import com.baeldung.zoneddatetime.converter.ZonedDateTimeReadConverter; +import com.baeldung.zoneddatetime.converter.ZonedDateTimeWriteConverter; import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; -import com.baeldung.zoneddatetime.converter.ZonedDateTimeReadConverter; -import com.baeldung.zoneddatetime.converter.ZonedDateTimeWriteConverter; +import java.util.ArrayList; +import java.util.List; @EnableMongoRepositories(basePackages = { "com.baeldung" }) public class MongoConfig extends AbstractMongoClientConfiguration { diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java similarity index 100% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java similarity index 100% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/model/Action.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/model/Action.java similarity index 100% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/model/Action.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/model/Action.java diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java similarity index 99% rename from persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java index e214c4b3c4..8fc33a6b6e 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java @@ -1,7 +1,6 @@ package com.baeldung.zoneddatetime.repository; +import com.baeldung.zoneddatetime.model.Action; import org.springframework.data.mongodb.repository.MongoRepository; -import com.baeldung.zoneddatetime.model.Action; - public interface ActionRepository extends MongoRepository { } \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb-4/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/resources/application.properties new file mode 100644 index 0000000000..b1c7e18ea3 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.application.name=spring-boot-persistence-mongodb-4 diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/dbref/DbRefIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/test/java/com/baeldung/mongodb/dbref/DbRefIntegrationTest.java similarity index 99% rename from persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/dbref/DbRefIntegrationTest.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/test/java/com/baeldung/mongodb/dbref/DbRefIntegrationTest.java index c357c0283c..8668bf9404 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/dbref/DbRefIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/test/java/com/baeldung/mongodb/dbref/DbRefIntegrationTest.java @@ -1,11 +1,11 @@ package com.baeldung.mongodb.dbref; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.ArrayList; -import java.util.List; - +import com.baeldung.mongodb.dbref.model.Person; +import com.baeldung.mongodb.dbref.model.Pet; +import com.baeldung.mongodb.dbref.repository.PersonRepository; +import com.mongodb.BasicDBObjectBuilder; +import com.mongodb.DBObject; +import com.mongodb.DBRef; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -14,12 +14,11 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.mongodb.dbref.model.Person; -import com.baeldung.mongodb.dbref.model.Pet; -import com.baeldung.mongodb.dbref.repository.PersonRepository; -import com.mongodb.BasicDBObjectBuilder; -import com.mongodb.DBObject; -import com.mongodb.DBRef; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; @RunWith(SpringRunner.class) @SpringBootTest diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java b/persistence-modules/spring-boot-persistence-mongodb-4/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java similarity index 99% rename from persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java rename to persistence-modules/spring-boot-persistence-mongodb-4/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java index 3a241418ca..09ff1d9375 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java @@ -1,5 +1,8 @@ package com.baeldung.zoneddatetime; +import com.baeldung.zoneddatetime.config.MongoConfig; +import com.baeldung.zoneddatetime.model.Action; +import com.baeldung.zoneddatetime.repository.ActionRepository; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -10,10 +13,6 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.baeldung.zoneddatetime.config.MongoConfig; -import com.baeldung.zoneddatetime.model.Action; -import com.baeldung.zoneddatetime.repository.ActionRepository; - import java.time.ZoneOffset; import java.time.ZonedDateTime; diff --git a/persistence-modules/spring-boot-persistence-mongodb-4/src/test/resources/application.properties b/persistence-modules/spring-boot-persistence-mongodb-4/src/test/resources/application.properties new file mode 100644 index 0000000000..a5b5fb9804 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-4/src/test/resources/application.properties @@ -0,0 +1 @@ +spring.mongodb.embedded.version=4.4.9 \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/README.md b/persistence-modules/spring-boot-persistence-mongodb/README.md index 5453eb0052..867b31c639 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/README.md +++ b/persistence-modules/spring-boot-persistence-mongodb/README.md @@ -4,8 +4,6 @@ - [Spring Boot Integration Testing with Embedded MongoDB](http://www.baeldung.com/spring-boot-embedded-mongodb) - [Upload and Retrieve Files Using MongoDB and Spring Boot](https://www.baeldung.com/spring-boot-mongodb-upload-file) - [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) -- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime) -- [A Guide to @DBRef in MongoDB](https://www.baeldung.com/spring-mongodb-dbref-annotation) - [Import Data to MongoDB From JSON File Using Java](https://www.baeldung.com/java-import-json-mongodb) - [Spring Data MongoDB – Configure Connection](https://www.baeldung.com/spring-data-mongodb-connection) - More articles: [[next-->]](../spring-boot-persistence-mongodb-2) diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index 39edc01170..a816732e52 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -70,7 +70,6 @@ - 2.23.0 2.0.1.Final 8.2.0 com.baeldung.boot.Application diff --git a/persistence-modules/spring-data-dynamodb/pom.xml b/persistence-modules/spring-data-dynamodb/pom.xml index 5252aa5481..5d31f13518 100644 --- a/persistence-modules/spring-data-dynamodb/pom.xml +++ b/persistence-modules/spring-data-dynamodb/pom.xml @@ -136,6 +136,12 @@ so test + + net.bytebuddy + byte-buddy + 1.14.13 + test + diff --git a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java index 3ad54e2267..13c1c162f1 100644 --- a/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java +++ b/persistence-modules/spring-data-dynamodb/src/test/java/com/baeldung/SpringContextTest.java @@ -5,8 +5,6 @@ import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.Application; - @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringContextTest { diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntity.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntity.java new file mode 100644 index 0000000000..4cd267162f --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntity.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.data.jpa.getnextseq; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; + +@Entity +public class MyEntity { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeqGen") + @SequenceGenerator(name = "mySeqGen", sequenceName = "my_sequence_name", allocationSize = 1) + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityApplication.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityApplication.java new file mode 100644 index 0000000000..4b31ad768c --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.data.jpa.getnextseq; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MyEntityApplication { + + public static void main(String[] args) { + SpringApplication.run(MyEntityApplication.class); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityRepository.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityRepository.java new file mode 100644 index 0000000000..c864c43fda --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.data.jpa.getnextseq; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface MyEntityRepository extends JpaRepository { + + @Query(value = "SELECT NEXTVAL('my_sequence_name')", nativeQuery = true) + Long getNextSequenceValue(); +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityService.java b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityService.java new file mode 100644 index 0000000000..74825d2a82 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/main/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityService.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.data.jpa.getnextseq; + +import java.math.BigInteger; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.stereotype.Service; + +@Service +public class MyEntityService { + + @PersistenceContext + private EntityManager entityManager; + + public Long getNextSequenceValue(String sequenceName) { + BigInteger nextValue = (BigInteger) entityManager.createNativeQuery("SELECT NEXTVAL(:sequenceName)") + .setParameter("sequenceName", sequenceName) + .getSingleResult(); + return nextValue.longValue(); + } +} diff --git a/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityRepositoryIntegrationTest.java new file mode 100644 index 0000000000..3444bbbd49 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/getnextseq/MyEntityRepositoryIntegrationTest.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.data.jpa.getnextseq; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +@SpringBootTest +@ActiveProfiles("test") +@Sql(scripts = "/testsequence.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) +public class MyEntityRepositoryIntegrationTest { + @Autowired + private MyEntityRepository myEntityRepository; + + @Autowired + private MyEntityService myEntityService; + + @Test + void whenUsingSequenceGenerator_thenNextValueReturned() { + MyEntity entity = new MyEntity(); + myEntityRepository.save(entity); + + long generatedId = entity.getId(); + assertNotNull(generatedId); + assertEquals(1L, generatedId); + } + + + @Test + void whenUsingCustomQuery_thenNextValueReturned() { + long generatedId = myEntityRepository.getNextSequenceValue(); + assertNotNull(generatedId); + assertEquals(1L, generatedId); + } + + @Test + void whenUsingEntityManager_thenNextValueReturned() { + long generatedId = myEntityService.getNextSequenceValue("my_sequence_name"); + assertNotNull(generatedId); + assertEquals(1L, generatedId); + } + +} diff --git a/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryLiveTest.java similarity index 98% rename from persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryLiveTest.java index 2385590d7f..ac68d55139 100644 --- a/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-4/src/test/java/com/baeldung/spring/data/jpa/queryjsonb/ProductRepositoryLiveTest.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootTest @ActiveProfiles("test") @Sql(scripts = "/testdata.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) -public class ProductRepositoryIntegrationTest { +public class ProductRepositoryLiveTest { @Autowired private ProductRepository productRepository; diff --git a/persistence-modules/spring-data-jpa-query-4/src/test/resources/testsequence.sql b/persistence-modules/spring-data-jpa-query-4/src/test/resources/testsequence.sql new file mode 100644 index 0000000000..518353ad12 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-4/src/test/resources/testsequence.sql @@ -0,0 +1,3 @@ +DROP SEQUENCE IF EXISTS my_sequence_name; + +CREATE SEQUENCE my_sequence_name START 1; \ No newline at end of file diff --git a/persistence-modules/spring-data-mongodb-2/src/main/java/com/baeldung/projection/model/Student.java b/persistence-modules/spring-data-mongodb-2/src/main/java/com/baeldung/projection/model/Student.java new file mode 100644 index 0000000000..5560d9c689 --- /dev/null +++ b/persistence-modules/spring-data-mongodb-2/src/main/java/com/baeldung/projection/model/Student.java @@ -0,0 +1,36 @@ +package com.baeldung.projection.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "student") +public class Student { + @Id + private String id; + private String name; + private Long age; + + public Student(String id, String name, Long age) { + this.id = id; + this.name = name; + this.age = age; + } + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public Long getAge() { + return age; + } + public void setAge(Long age) { + this.age = age; + } +} diff --git a/persistence-modules/spring-data-mongodb-2/src/main/java/com/baeldung/projection/repository/StudentRepository.java b/persistence-modules/spring-data-mongodb-2/src/main/java/com/baeldung/projection/repository/StudentRepository.java new file mode 100644 index 0000000000..ec148400a9 --- /dev/null +++ b/persistence-modules/spring-data-mongodb-2/src/main/java/com/baeldung/projection/repository/StudentRepository.java @@ -0,0 +1,32 @@ +package com.baeldung.projection.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.mongodb.repository.Aggregation; +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.projection.model.Student; + +import java.util.List; + +public interface StudentRepository extends MongoRepository { + @Aggregation(pipeline = { + "{ '$skip': ?0 }", + "{ '$limit': ?1 }" + }) + List findAll(Long skip, Long limit); + @Aggregation(pipeline = { + "{ '$match': { 'age': ?0 } }", + "{ $skip: ?1 }", + "{ $limit: ?2 }" + }) + List findAllByAgeCriteria(Long age, Long skip, Long limit); + @Aggregation(pipeline = { + "{ '$match': { 'id' : ?0 } }", + "{ '$sort' : { 'id' : 1 } }", + "{ '$skip' : ?1 }", + "{ '$limit' : ?2 }" + }) + List findByStudentId(final String studentId, Long skip, Long limit); + Page findAll(Pageable pageable); +} diff --git a/persistence-modules/spring-data-mongodb-2/src/test/java/com/baeldung/projection/StudentIntegrationTest.java b/persistence-modules/spring-data-mongodb-2/src/test/java/com/baeldung/projection/StudentIntegrationTest.java new file mode 100644 index 0000000000..ac68a2db32 --- /dev/null +++ b/persistence-modules/spring-data-mongodb-2/src/test/java/com/baeldung/projection/StudentIntegrationTest.java @@ -0,0 +1,90 @@ +package com.baeldung.projection; + +import com.baeldung.projection.config.ProjectionConfig; +import com.baeldung.projection.model.Student; +import com.baeldung.projection.repository.StudentRepository; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ProjectionConfig.class) +public class StudentIntegrationTest { + @Autowired + private StudentRepository studentRepository; + private List studentList; + + @Before + public void setUp() { + Student student1 = new Student("A", "Abraham", 15L); + Student student2 = new Student("B", "Usman", 30L); + Student student3 = new Student("C", "David", 20L); + Student student4 = new Student("D", "Tina", 45L); + Student student5 = new Student("E", "Maria", 33L); + + studentList = Arrays.asList(student1, student2, student3, student4, student5); + studentRepository.saveAll(studentList); + } + + @Test + public void whenRetrievingAllStudents_thenReturnsCorrectNumberOfRecords() { + // WHEN + List result = studentRepository.findAll(0L, 5L); + // THEN + assertEquals(5, result.size()); + } + + @Test + public void whenLimitingAndSkipping_thenReturnsLimitedStudents() { + // WHEN + List result = studentRepository.findAll(3L, 2L); + // THEN + assertEquals(2, result.size()); + assertEquals("Tina", result.get(0).getName()); + assertEquals("Maria", result.get(1).getName()); + } + + @Test + public void whenFilteringByAge_thenReturnsStudentsMatchingCriteria() { + // WHEN + List result = studentRepository.findAllByAgeCriteria(30L, 0L, 10L); + // THEN + assertEquals(1, result.size()); + assertEquals("Usman", result.get(0).getName()); + } + + @Test + public void whenFindingById_thenReturnsMatchingStudent() { + // WHEN + List result = studentRepository.findByStudentId("A", 0L, 5L); + // THEN + assertEquals(1, result.size()); + assertEquals("Abraham", result.get(0).getName()); + } + + @Test + public void whenFindByStudentIdUsingPageable_thenReturnsPageOfStudents() { + // GIVEN + Sort sort = Sort.by(Sort.Direction.DESC, "id"); + Pageable pageable = PageRequest.of(0, 5, sort); + + // WHEN + Page resultPage = studentRepository.findAll(pageable); + + // THEN + assertEquals(5, resultPage.getTotalElements()); + assertEquals("Maria", resultPage.getContent().get(0).getName()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-neo4j/pom.xml b/persistence-modules/spring-data-neo4j/pom.xml index 8a0a9ff464..a1d1e4660e 100644 --- a/persistence-modules/spring-data-neo4j/pom.xml +++ b/persistence-modules/spring-data-neo4j/pom.xml @@ -48,6 +48,8 @@ 2.7.14 5.10.0 + 1.7.32 + 1.2.7 \ No newline at end of file diff --git a/persistence-modules/spring-jdbc-2/pom.xml b/persistence-modules/spring-jdbc-2/pom.xml index 7942e7675d..374c87d358 100644 --- a/persistence-modules/spring-jdbc-2/pom.xml +++ b/persistence-modules/spring-jdbc-2/pom.xml @@ -20,6 +20,7 @@ org.springframework.boot spring-boot-starter-jdbc + ${spring-boot.version} @@ -30,7 +31,7 @@ org.springframework.boot spring-boot-starter-test - + ${spring-boot.version} @@ -46,47 +47,11 @@ - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - 3.2.0-SNAPSHOT 5.10.0 UTF-8 + 3.2.4 \ No newline at end of file diff --git a/persistence-modules/spring-jdbc-2/src/main/java/com/baeldung/jdbcclient/JdbcClientDemoApplication.java b/persistence-modules/spring-jdbc-2/src/main/java/com/baeldung/jdbcclient/JdbcClientDemoApplication.java index d10124fdef..1e7a6034ee 100644 --- a/persistence-modules/spring-jdbc-2/src/main/java/com/baeldung/jdbcclient/JdbcClientDemoApplication.java +++ b/persistence-modules/spring-jdbc-2/src/main/java/com/baeldung/jdbcclient/JdbcClientDemoApplication.java @@ -4,8 +4,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; -@SpringBootApplication -@ComponentScan(basePackages = "com.baledung.jdbcclient") +@SpringBootApplication(scanBasePackages = "com.baeldung") public class JdbcClientDemoApplication { public static void main(String[] args) { diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml index c486a95e96..04c0dfe297 100644 --- a/persistence-modules/spring-persistence-simple/pom.xml +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -101,6 +101,8 @@ 2.2.7.RELEASE 0.23.0 2.5.2 + 1.7.32 + 1.2.7 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7496d4ca93..54c54bf7b8 100644 --- a/pom.xml +++ b/pom.xml @@ -737,7 +737,7 @@ libraries-security libraries-server-2 libraries-server - libraries-stream + libraries-testing-2 libraries-transform libraries @@ -826,6 +826,7 @@ spring-reactive-modules spring-remoting-modules spring-scheduling + spring-scheduling-2 spring-security-modules spring-shell spring-soap @@ -1074,6 +1075,7 @@ spring-reactive-modules spring-remoting-modules spring-scheduling + spring-scheduling-2 spring-security-modules spring-shell spring-soap @@ -1149,23 +1151,23 @@ 3.21.0 2.2 1.3 - 4.4.0 + 5.11.0 1.14.11 - 1.7.32 - 1.2.7 + 2.0.12 + 1.5.3 2.22.2 - 3.12.1 - 3.1.0 + 3.13.0 + 3.2.0 1.8 1.2.17 1.37 1.37 - 3.1.2 + 3.2.5 4.4 2.15.1 3.14.0 diff --git a/protobuffer/README.md b/protobuffer/README.md index 329ad0e071..6d742837fd 100644 --- a/protobuffer/README.md +++ b/protobuffer/README.md @@ -5,3 +5,4 @@ This module contains articles about Google Protocol Buffer. ### Relevant articles - [Introduction to Google Protocol Buffer](https://www.baeldung.com/google-protocol-buffer) +- [Convert Google Protocol Buffer Timestamp to LocalDate](https://www.baeldung.com/convert-google-protocol-buffer-timestamp-to-localdate) diff --git a/protobuffer/src/main/java/com/baeldung/protobuftimestamptolocaldate/TimestampInstance.java b/protobuffer/src/main/java/com/baeldung/protobuftimestamptolocaldate/TimestampInstance.java new file mode 100644 index 0000000000..0544c698f3 --- /dev/null +++ b/protobuffer/src/main/java/com/baeldung/protobuftimestamptolocaldate/TimestampInstance.java @@ -0,0 +1,21 @@ +package com.baeldung.protobuftimestamptolocaldate; + +import com.google.protobuf.Timestamp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Instant; + +public class TimestampInstance { + + private static final Logger logger = LoggerFactory.getLogger(TimestampInstance.class); + + public static void main(String[] args) { + Instant currentTimestamp = Instant.now(); + Timestamp timestamp = Timestamp.newBuilder() + .setSeconds(currentTimestamp.getEpochSecond()) + .setNanos(currentTimestamp.getNano()) + .build(); + logger.info(timestamp.toString()); + } +} diff --git a/protobuffer/src/main/java/com/baeldung/protobuftimestamptolocaldate/TimestampToLocalDate.java b/protobuffer/src/main/java/com/baeldung/protobuftimestamptolocaldate/TimestampToLocalDate.java new file mode 100644 index 0000000000..97caf8ad64 --- /dev/null +++ b/protobuffer/src/main/java/com/baeldung/protobuftimestamptolocaldate/TimestampToLocalDate.java @@ -0,0 +1,19 @@ +package com.baeldung.protobuftimestamptolocaldate; + +import com.google.protobuf.Timestamp; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; + +public class TimestampToLocalDate { + + public static LocalDate convertToLocalDate(Timestamp timestamp) { + Instant instant = Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()); + LocalDate time = instant.atZone(ZoneId.of("America/Montreal")) + .toLocalDate(); + return time; + + } + +} diff --git a/protobuffer/src/test/java/com/baeldung/protobuftimestamptolocaldate/TimestampToLocalDateUnitTest.java b/protobuffer/src/test/java/com/baeldung/protobuftimestamptolocaldate/TimestampToLocalDateUnitTest.java new file mode 100644 index 0000000000..bde8a98ac9 --- /dev/null +++ b/protobuffer/src/test/java/com/baeldung/protobuftimestamptolocaldate/TimestampToLocalDateUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.protobuftimestamptolocaldate; + +import com.google.protobuf.Timestamp; +import org.junit.Test; + +import java.time.LocalDate; + +import static org.junit.Assert.assertEquals; + +public class TimestampToLocalDateUnitTest { + + @Test + public void givenTimestamp_whenConvertedToLocalDate_thenSuccess() { + Timestamp timestamp = Timestamp.newBuilder() + .setSeconds(1000000000) + .setNanos(778866000) + .build(); + LocalDate time = TimestampToLocalDate.convertToLocalDate(timestamp); + assertEquals(LocalDate.of(2001, 9, 8), time); + } + +} \ No newline at end of file diff --git a/quarkus-modules/quarkus-virtual-threads/pom.xml b/quarkus-modules/quarkus-virtual-threads/pom.xml index f2da9390b5..0b8cf46c3e 100644 --- a/quarkus-modules/quarkus-virtual-threads/pom.xml +++ b/quarkus-modules/quarkus-virtual-threads/pom.xml @@ -37,7 +37,6 @@ 3.0.0 0.3.0 3.6.0 - 3.11.2 @@ -92,7 +91,7 @@ org.mockito mockito-core - ${mockito-core.version} + ${mockito.version} test diff --git a/quarkus-modules/quarkus/pom.xml b/quarkus-modules/quarkus/pom.xml index fc3d294beb..5ddd9826e9 100644 --- a/quarkus-modules/quarkus/pom.xml +++ b/quarkus-modules/quarkus/pom.xml @@ -180,7 +180,7 @@ 2.16.3.Final - 3.3.0 + 4.4.0 \ No newline at end of file diff --git a/spring-ai/pom.xml b/spring-ai/pom.xml index 8864b03568..da4a38a868 100644 --- a/spring-ai/pom.xml +++ b/spring-ai/pom.xml @@ -18,7 +18,7 @@ spring-snapshots Spring Snapshots - https://repo.spring.io/snapshot + https://repo.spring.io/snapshot false diff --git a/spring-aop-2/pom.xml b/spring-aop-2/pom.xml index 3a60739315..7aea3b64de 100644 --- a/spring-aop-2/pom.xml +++ b/spring-aop-2/pom.xml @@ -45,6 +45,7 @@ org.mockito mockito-core + ${mockito.version} test diff --git a/spring-boot-modules/spring-boot-3-2/pom.xml b/spring-boot-modules/spring-boot-3-2/pom.xml index d427aff835..72dffa588a 100644 --- a/spring-boot-modules/spring-boot-3-2/pom.xml +++ b/spring-boot-modules/spring-boot-3-2/pom.xml @@ -14,14 +14,6 @@ 1.0.0-SNAPSHOT - - - repository.spring.release - Spring GA Repository - https://repo.spring.io/milestone - - - org.springframework.boot @@ -73,7 +65,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${springdoc.version} + ${springdoc-openapi-webmvc-ui.version} org.projectlombok @@ -102,7 +94,6 @@ org.springframework.boot spring-boot-starter-test - 3.2.0-M2 org.junit.jupiter @@ -202,18 +193,6 @@ - - - - org.springframework.boot - spring-boot-dependencies - 3.2.0-M2 - import - pom - - - - @@ -300,6 +279,8 @@ 0.2.0 5.0.2 3.1.2 + 3.2.4 + 2.5.0 diff --git a/spring-boot-modules/spring-boot-3-native/pom.xml b/spring-boot-modules/spring-boot-3-native/pom.xml index 1e42cb6035..e446b19f03 100644 --- a/spring-boot-modules/spring-boot-3-native/pom.xml +++ b/spring-boot-modules/spring-boot-3-native/pom.xml @@ -22,7 +22,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${springdoc.version} + ${springdoc-openapi-webmvc-ui.version} org.springframework.boot @@ -100,6 +100,7 @@ 3.0.0-M7 0.9.17 17 + 2.5.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/pom.xml b/spring-boot-modules/spring-boot-3/pom.xml index 0c00a8af34..0cb9d33cb8 100644 --- a/spring-boot-modules/spring-boot-3/pom.xml +++ b/spring-boot-modules/spring-boot-3/pom.xml @@ -89,7 +89,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${springdoc.version} + ${springdoc-openapi-webmvc-ui.version} org.projectlombok @@ -211,46 +211,10 @@ 3.0.0-M7 com.baeldung.sample.TodoApplication 5.14.0 - 3.2.0-SNAPSHOT + 3.2.4 0.2.0 5.10.0 + 2.5.0 - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - false - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java index f90c7b2889..8108902913 100644 --- a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/filter/AppConfig.java @@ -1,6 +1,5 @@ package com.baeldung.filter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -18,7 +17,6 @@ public class AppConfig { } @Bean - @Autowired public FilterRegistrationBean loggingFilterRegistration(LoggingService loggingService) { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new LoggingFilterRegistrationBean(loggingService)); diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/FilterConfig.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/FilterConfig.java new file mode 100644 index 0000000000..212dbd8626 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/FilterConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.responsebody; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FilterConfig { + + @Bean + public FilterRegistrationBean loggingFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new MD5Filter()); + return registrationBean; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/HelloWorldController.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/HelloWorldController.java new file mode 100644 index 0000000000..657b7972bb --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/HelloWorldController.java @@ -0,0 +1,15 @@ +package com.baeldung.responsebody; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/example") +public class HelloWorldController { + + @GetMapping + public String getExample() { + return "Hello, World!"; + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/MD5Filter.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/MD5Filter.java new file mode 100644 index 0000000000..8f6e86f17e --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/MD5Filter.java @@ -0,0 +1,39 @@ +package com.baeldung.responsebody; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.logging.Logger; + +import org.springframework.stereotype.Component; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.xml.bind.DatatypeConverter; + +@Component +public class MD5Filter implements Filter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + ContentCachingResponseWrapper responseCacheWrapperObject = new ContentCachingResponseWrapper((HttpServletResponse) servletResponse); + filterChain.doFilter(servletRequest, responseCacheWrapperObject); + + byte[] responseBody = responseCacheWrapperObject.getContentAsByteArray(); + + try { + MessageDigest md5Digest = MessageDigest.getInstance("MD5"); + byte[] md5Hash = md5Digest.digest(responseBody); + String md5HashString = DatatypeConverter.printHexBinary(md5Hash); + responseCacheWrapperObject.setHeader("Response-Body-MD5", md5HashString); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + responseCacheWrapperObject.copyBodyToResponse(); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/ResponseBodyApplication.java b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/ResponseBodyApplication.java new file mode 100644 index 0000000000..4084dffccf --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/main/java/com/baeldung/responsebody/ResponseBodyApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.responsebody; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = "com.baeldung.responsebody") +public class ResponseBodyApplication { + + public static void main(String[] args) { + SpringApplication.run(ResponseBodyApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/responsebody/ResponseBodyUnitTest.java b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/responsebody/ResponseBodyUnitTest.java new file mode 100644 index 0000000000..bebbd5a4b9 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-3/src/test/java/com/baeldung/responsebody/ResponseBodyUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.responsebody; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import jakarta.xml.bind.DatatypeConverter; + +@SpringBootTest(classes = ResponseBodyApplication.class) +@AutoConfigureMockMvc +class ResponseBodyUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void whenExampleApiCallThenResponseHasMd5Header() throws Exception { + String endpoint = "/api/example"; + String expectedResponse = "Hello, World!"; + String expectedMD5 = getMD5Hash(expectedResponse); + + MvcResult mvcResult = mockMvc.perform(get(endpoint).accept(MediaType.TEXT_PLAIN_VALUE)) + .andExpect(status().isOk()) + .andReturn(); + + String md5Header = mvcResult.getResponse() + .getHeader("Response-Body-MD5"); + assertThat(md5Header).isEqualTo(expectedMD5); + } + + private String getMD5Hash(String input) throws NoSuchAlgorithmException { + MessageDigest md5Digest = MessageDigest.getInstance("MD5"); + byte[] md5Hash = md5Digest.digest(input.getBytes(StandardCharsets.UTF_8)); + return DatatypeConverter.printHexBinary(md5Hash); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-autoconfigure/pom.xml b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-autoconfigure/pom.xml index d7f437633d..96cfd622db 100644 --- a/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-autoconfigure/pom.xml +++ b/spring-boot-modules/spring-boot-custom-starter/greeter-spring-boot-autoconfigure/pom.xml @@ -42,6 +42,12 @@ ${spring-boot.version} test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + @@ -61,6 +67,7 @@ 2.2.6.RELEASE 0.0.1-SNAPSHOT + 1.14.13 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java index 171d703621..a1318c0519 100644 --- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java @@ -4,10 +4,17 @@ import com.baeldung.barcodes.generators.BarbecueBarcodeGenerator; import com.baeldung.barcodes.generators.Barcode4jBarcodeGenerator; import com.baeldung.barcodes.generators.QRGenBarcodeGenerator; import com.baeldung.barcodes.generators.ZxingBarcodeGenerator; +import com.baeldung.barcodes.generators.ZxingBarcodeGeneratorWithText; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; import java.awt.image.BufferedImage; @@ -76,6 +83,11 @@ public class BarcodesController { return okResponse(ZxingBarcodeGenerator.generateCode128BarcodeImage(barcode)); } + @GetMapping(value = "/zxing/qrcode/text", produces = MediaType.IMAGE_PNG_VALUE) + public ResponseEntity zxingCodeQRcodeText(@RequestParam("barcode") String barcode, @RequestParam("toptext") String toptext, @RequestParam("bottomtext") String bottomtext) throws Exception { + return okResponse(ZxingBarcodeGeneratorWithText.createQRwithText(barcode, toptext, bottomtext)); + } + @PostMapping(value = "/zxing/pdf417", produces = MediaType.IMAGE_PNG_VALUE) public ResponseEntity zxingPDF417Barcode(@RequestBody String barcode) throws Exception { return okResponse(ZxingBarcodeGenerator.generatePDF417BarcodeImage(barcode)); diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/ZxingBarcodeGeneratorWithText.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/ZxingBarcodeGeneratorWithText.java new file mode 100644 index 0000000000..e6ebcf9bae --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/ZxingBarcodeGeneratorWithText.java @@ -0,0 +1,59 @@ +package com.baeldung.barcodes.generators; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; + +import java.awt.Graphics2D; +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.image.BufferedImage; +import java.io.IOException; + +public class ZxingBarcodeGeneratorWithText { + + public static BufferedImage createQRwithText(String data, String topText, String bottomText) throws WriterException, IOException { + QRCodeWriter barcodeWriter = new QRCodeWriter(); + BitMatrix matrix = barcodeWriter.encode(data, BarcodeFormat.QR_CODE, 200, 200); + return modifiedQRCode(matrix, topText, bottomText); + } + + public static BufferedImage modifiedQRCode(BitMatrix matrix, String topText, String bottomText) throws IOException { + int matrixWidth = matrix.getWidth(); + int matrixHeight = matrix.getHeight(); + + BufferedImage image = new BufferedImage(matrixWidth, matrixHeight, BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = image.createGraphics(); + graphics.setColor(Color.WHITE); + graphics.fillRect(0, 0, matrixWidth, matrixHeight); + graphics.setColor(Color.BLACK); + + for (int i = 0; i < matrixWidth; i++) { + for (int j = 0; j < matrixHeight; j++) { + if (matrix.get(i, j)) { + graphics.fillRect(i, j, 1, 1); + } + } + } + + FontMetrics fontMetrics = graphics.getFontMetrics(); + int topTextWidth = fontMetrics.stringWidth(topText); + int bottomTextWidth = fontMetrics.stringWidth(bottomText); + int finalWidth = Math.max(matrixWidth, Math.max(topTextWidth, bottomTextWidth)) + 1; + int finalHeight = matrixHeight + fontMetrics.getHeight() + fontMetrics.getAscent() + 1; + + BufferedImage finalImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_RGB); + Graphics2D finalGraphics = finalImage.createGraphics(); + finalGraphics.setColor(Color.WHITE); + finalGraphics.fillRect(0, 0, finalWidth, finalHeight); + finalGraphics.setColor(Color.BLACK); + + finalGraphics.drawImage(image, (finalWidth - matrixWidth) / 2, fontMetrics.getAscent() + 2, null); + finalGraphics.drawString(topText, (finalWidth - topTextWidth) / 2, fontMetrics.getAscent() + 2); + finalGraphics.drawString(bottomText, (finalWidth - bottomTextWidth) / 2, finalHeight - fontMetrics.getDescent() - 2); + + return finalImage; + } + +} diff --git a/spring-boot-modules/spring-boot-logging-logback/src/main/java/com/baeldung/logging/LogbackConfiguration.java b/spring-boot-modules/spring-boot-logging-logback/src/main/java/com/baeldung/logging/LogbackConfiguration.java new file mode 100644 index 0000000000..6f1ffe4730 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-logback/src/main/java/com/baeldung/logging/LogbackConfiguration.java @@ -0,0 +1,11 @@ +package com.baeldung.logging; + +import org.springframework.stereotype.Component; + +@Component +public class LogbackConfiguration { + public void setLogbackConfigurationFile(String path) { + System.setProperty("logback.configurationFile", path); + } +} + diff --git a/spring-boot-modules/spring-boot-logging-logback/src/test/java/com/baeldung/logging/LogbackConfigurationUnitTest.java b/spring-boot-modules/spring-boot-logging-logback/src/test/java/com/baeldung/logging/LogbackConfigurationUnitTest.java new file mode 100644 index 0000000000..006305cac0 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-logback/src/test/java/com/baeldung/logging/LogbackConfigurationUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.logging; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {LogbackConfiguration.class}) +public class LogbackConfigurationUnitTest { + + @Autowired + LogbackConfiguration logbackConfiguration; + + @Test + public void givenLogbackConfigurationFile_whenSettingLogbackConfiguration_thenFileLocationSet() { + // Set the expected logback.xml location + String expectedLocation = "/test/path/to/logback.xml"; + // Call the method to set the logback configuration file + logbackConfiguration.setLogbackConfigurationFile(expectedLocation); + // Verify that the system property is correctly set + assertThat(System.getProperty("logback.configurationFile")).isEqualTo(expectedLocation); + } +} diff --git a/spring-boot-modules/spring-boot-springdoc-2/pom.xml b/spring-boot-modules/spring-boot-springdoc-2/pom.xml index 89f176e668..56d118e15f 100644 --- a/spring-boot-modules/spring-boot-springdoc-2/pom.xml +++ b/spring-boot-modules/spring-boot-springdoc-2/pom.xml @@ -40,7 +40,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${springdoc.version} + ${springdoc-openapi-webmvc-ui.version} org.springdoc @@ -119,6 +119,7 @@ 2.2.0 + 2.5.0 1.4 17 diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml b/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml index df08a68a30..60aad3b4a4 100644 --- a/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml +++ b/spring-boot-modules/spring-boot-swagger-keycloak/pom.xml @@ -32,7 +32,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${springdoc.version} + ${springdoc-openapi-webmvc-ui.version} javax.annotation @@ -53,6 +53,7 @@ 2.1.0 1.3.2 + 2.5.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/ApplicationRunnerTaskExecutor.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/ApplicationRunnerTaskExecutor.java index 3bf08491bf..8143b97f94 100644 --- a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/ApplicationRunnerTaskExecutor.java +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/ApplicationRunnerTaskExecutor.java @@ -14,14 +14,16 @@ import org.springframework.stereotype.Component; matchIfMissing = true) @Component public class ApplicationRunnerTaskExecutor implements ApplicationRunner { - private TaskService taskService; + + private final TaskService taskService; public ApplicationRunnerTaskExecutor(TaskService taskService) { this.taskService = taskService; } @Override - public void run(ApplicationArguments args) throws Exception { + public void run(ApplicationArguments args) { taskService.execute("application runner task"); } + } diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/CommandLineTaskExecutor.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/CommandLineTaskExecutor.java index 38fd3b9c0a..0dd26eed8a 100644 --- a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/CommandLineTaskExecutor.java +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/CommandLineTaskExecutor.java @@ -13,14 +13,14 @@ import org.springframework.stereotype.Component; matchIfMissing = true) @Component public class CommandLineTaskExecutor implements CommandLineRunner { - private TaskService taskService; + private final TaskService taskService; public CommandLineTaskExecutor(TaskService taskService) { this.taskService = taskService; } @Override - public void run(String... args) throws Exception { + public void run(String... args) { taskService.execute("command line runner task"); } } diff --git a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/TaskService.java b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/TaskService.java index dac437e72d..9190b12a22 100644 --- a/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/TaskService.java +++ b/spring-boot-modules/spring-boot-testing/src/main/java/com/baeldung/prevent/commandline/application/runner/execution/TaskService.java @@ -6,9 +6,9 @@ import org.springframework.stereotype.Service; @Service public class TaskService { - private static Logger logger = LoggerFactory.getLogger(TaskService.class); + private static final Logger logger = LoggerFactory.getLogger(TaskService.class); public void execute(String task) { - logger.info("do " + task); + logger.info("do {}", task); } } diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java index 26a7339f1d..43447ca178 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java @@ -1,16 +1,13 @@ package com.baeldung.prevent.commandline.application.runner.execution; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; - -import com.baeldung.prevent.commandline.application.runner.execution.ApplicationRunnerTaskExecutor; -import com.baeldung.prevent.commandline.application.runner.execution.CommandLineTaskExecutor; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; + @SpringBootTest class RunApplicationIntegrationTest { @SpyBean @@ -21,6 +18,6 @@ class RunApplicationIntegrationTest { @Test void whenContextLoads_thenRunnersRun() throws Exception { verify(applicationRunnerTaskExecutor, times(1)).run(any()); - verify(commandLineTaskExecutor, times(1)).run(any()); + verify(commandLineTaskExecutor, times(1)).run(any(String[].class)); } } diff --git a/spring-boot-modules/spring-caching-3/README.md b/spring-boot-modules/spring-caching-3/README.md index 5429a0bb2f..2e33ad3c6c 100644 --- a/spring-boot-modules/spring-caching-3/README.md +++ b/spring-boot-modules/spring-caching-3/README.md @@ -1,2 +1,3 @@ ## Relevant articles +- [Disable @Cacheable in Spring Boot](https://www.baeldung.com/spring-boot-disable-cacheable-annotation) diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml index 86644a4999..3c059e65fa 100644 --- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml @@ -90,14 +90,6 @@ - - - repository.spring.milestone - Spring Milestone Repository - https://repo.spring.io/release - - - diff --git a/spring-cloud-modules/spring-cloud-netflix-feign/pom.xml b/spring-cloud-modules/spring-cloud-netflix-feign/pom.xml index 92d66c03df..5915bb3c6d 100644 --- a/spring-cloud-modules/spring-cloud-netflix-feign/pom.xml +++ b/spring-cloud-modules/spring-cloud-netflix-feign/pom.xml @@ -75,6 +75,8 @@ Camden.SR7 8.18.0 + 1.7.32 + 1.2.7 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml b/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml index 952b7867de..d4a651f3dd 100644 --- a/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml +++ b/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml @@ -44,8 +44,18 @@ ${spring-boot.version} test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + 1.14.13 + + diff --git a/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml b/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml index 50169ff03a..de477f810a 100644 --- a/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml +++ b/spring-cloud-modules/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml @@ -44,8 +44,18 @@ ${spring-boot.version} test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + 1.14.13 + + diff --git a/spring-cloud-modules/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml b/spring-cloud-modules/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml index 890e26bf19..937689db73 100644 --- a/spring-cloud-modules/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml +++ b/spring-cloud-modules/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml @@ -52,8 +52,19 @@ spring-boot-starter-test test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + 1.14.13 + + + diff --git a/spring-cloud-modules/spring-cloud-zuul/pom.xml b/spring-cloud-modules/spring-cloud-zuul/pom.xml index beb996521a..0e56ccfbdb 100644 --- a/spring-cloud-modules/spring-cloud-zuul/pom.xml +++ b/spring-cloud-modules/spring-cloud-zuul/pom.xml @@ -60,6 +60,12 @@ spring-boot-starter-test test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + @@ -82,6 +88,7 @@ 2021.0.3 2.2.7.RELEASE + 1.14.13 \ No newline at end of file diff --git a/spring-core-2/pom.xml b/spring-core-2/pom.xml index e05b839f00..5e40e20965 100644 --- a/spring-core-2/pom.xml +++ b/spring-core-2/pom.xml @@ -30,22 +30,18 @@ org.springframework spring-web - ${spring.version} org.springframework spring-webmvc - ${spring.version} org.springframework spring-orm - ${spring.version} org.springframework spring-context - ${spring.version} org.springframework.retry @@ -55,12 +51,10 @@ org.springframework spring-websocket - ${spring.version} org.springframework spring-messaging - ${spring.version} javax.annotation @@ -71,7 +65,6 @@ org.springframework spring-aspects - ${spring.version} @@ -106,7 +99,6 @@ org.springframework spring-test - ${spring.version} test diff --git a/spring-core-3/pom.xml b/spring-core-3/pom.xml index 9e777a4a03..526c18321f 100644 --- a/spring-core-3/pom.xml +++ b/spring-core-3/pom.xml @@ -17,17 +17,14 @@ org.springframework spring-beans - ${spring.version} org.springframework spring-tx - ${spring.version} org.springframework spring-jdbc - ${spring.version} org.springframework.boot @@ -37,12 +34,10 @@ org.springframework spring-context - ${spring.version} org.springframework spring-core - ${spring.version} javax.annotation @@ -52,7 +47,6 @@ org.springframework spring-test - ${spring.version} test diff --git a/spring-core-4/pom.xml b/spring-core-4/pom.xml index 5e86542224..2c6821e5d7 100644 --- a/spring-core-4/pom.xml +++ b/spring-core-4/pom.xml @@ -17,27 +17,22 @@ org.springframework spring-context - ${spring.version} org.springframework spring-core - ${spring.version} org.springframework spring-web - ${spring.version} org.springframework spring-webmvc - ${spring.version} org.springframework spring-expression - ${spring.version} org.projectlombok @@ -52,7 +47,6 @@ org.springframework spring-test - ${spring.version} test diff --git a/spring-core/pom.xml b/spring-core/pom.xml index 5134ad42f7..89155d4d94 100644 --- a/spring-core/pom.xml +++ b/spring-core/pom.xml @@ -19,17 +19,14 @@ org.springframework spring-test - ${spring.version} org.springframework spring-beans - ${spring.version} org.springframework spring-context - ${spring.version} javax.inject @@ -49,7 +46,7 @@ org.springframework.boot spring-boot-test - ${mockito.spring.boot.version} + ${spring-boot.version} test @@ -78,10 +75,8 @@ - 1.4.4.RELEASE 1 1.5.2.RELEASE - 1.10.19 1.3.2 diff --git a/spring-ejb-modules/ejb-beans/pom.xml b/spring-ejb-modules/ejb-beans/pom.xml index 6203db5f5a..52503922b6 100644 --- a/spring-ejb-modules/ejb-beans/pom.xml +++ b/spring-ejb-modules/ejb-beans/pom.xml @@ -189,7 +189,6 @@ 5.2.3.RELEASE 5.16.3 5.16.3 - 2.21.0 2.8 8.2.1.Final 2.12.5 diff --git a/spring-native/pom-nativeimage.xml b/spring-native/pom-nativeimage.xml index 08ceb09a8a..15712902e4 100644 --- a/spring-native/pom-nativeimage.xml +++ b/spring-native/pom-nativeimage.xml @@ -15,27 +15,6 @@ ../parent-boot-3 - - - spring-milestone - Spring Milestone - https://repo.spring.io/milestone - - - spring-snapshot - Spring Snapshot - https://repo.spring.io/snapshot - - - - - - spring-plugins-snapshot - Spring Plugins Snapshot - https://repo.spring.io/plugins-snapshot - - - org.springframework.boot diff --git a/spring-native/pom.xml b/spring-native/pom.xml index 97eb33c1c7..e2bf3d4078 100644 --- a/spring-native/pom.xml +++ b/spring-native/pom.xml @@ -15,32 +15,6 @@ ../parent-boot-2 - - - spring-milestone - Spring Milestone - https://repo.spring.io/milestone - - - spring-snapshot - Spring Snapshot - https://repo.spring.io/snapshot - - - - - - spring-plugins-snapshot - Spring Plugins Snapshot - https://repo.spring.io/plugins-snapshot - - - spring-plugins-milestone - Spring Plugins Milestone - https://repo.spring.io/plugins-milestone - - - org.springframework.boot @@ -84,5 +58,31 @@ 0.12.1 2.17.1 + + + + spring-milestone + Spring Milestone + https://repo.spring.io/milestone + + + spring-snapshot + Spring Snapshot + https://repo.spring.io/snapshot + + + + + + spring-plugins-snapshot + Spring Plugins Snapshot + https://repo.spring.io/plugins-snapshot + + + spring-plugins-milestone + Spring Plugins Milestone + https://repo.spring.io/plugins-milestone + + \ No newline at end of file diff --git a/spring-reactive-modules/pom.xml b/spring-reactive-modules/pom.xml index a8a9d6de8a..2618ea67aa 100644 --- a/spring-reactive-modules/pom.xml +++ b/spring-reactive-modules/pom.xml @@ -20,6 +20,7 @@ spring-reactive-data spring-reactive-2 spring-reactive-3 + spring-reactive-4 spring-reactive-client spring-reactive-client-2 spring-reactive-filters diff --git a/spring-reactive-modules/spring-reactive-4/pom.xml b/spring-reactive-modules/spring-reactive-4/pom.xml new file mode 100644 index 0000000000..7fb099ec1e --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + spring-reactive-4 + 0.0.1-SNAPSHOT + spring-reactive-4 + jar + spring sample project about new features + + + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 + + + + 3.4.2 + + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.projectreactor + reactor-test + test + + + + io.netty + netty-all + + + + org.wiremock + wiremock-standalone + ${wiremock-standalone.version} + test + + + + diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/SpringReactiveApplication.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/SpringReactiveApplication.java new file mode 100644 index 0000000000..21fbfdac3e --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/SpringReactiveApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringReactiveApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringReactiveApplication.class, args); + } + +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/controller/TraceController.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/controller/TraceController.java new file mode 100644 index 0000000000..c6a564e6d6 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/controller/TraceController.java @@ -0,0 +1,21 @@ +package com.baeldung.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import reactor.core.publisher.Mono; + +@RestController +public class TraceController { + + @GetMapping(value = "/trace-annotated") + public Mono trace(@RequestHeader(name = "traceId") final String traceId) { + return Mono.just("TraceId: ".concat(traceId)); + } + + @GetMapping(value = "/trace-exceptional") + public Mono traceExceptional() { + return Mono.just("Traced"); + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/ExceptionalTraceFilter.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/ExceptionalTraceFilter.java new file mode 100644 index 0000000000..b721d10109 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/ExceptionalTraceFilter.java @@ -0,0 +1,25 @@ +package com.baeldung.filters; + +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; + +import reactor.core.publisher.Mono; + +@Component +public class ExceptionalTraceFilter implements WebFilter { + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + if (exchange.getRequest() + .getPath() + .toString() + .equals("/trace-exceptional")) { + exchange.getRequest() + .getHeaders() + .add("traceId", "TRACE-ID"); + } + return chain.filter(exchange); + } +} \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/TraceHandlerFilterFunction.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/TraceHandlerFilterFunction.java new file mode 100644 index 0000000000..708e4dc509 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/TraceHandlerFilterFunction.java @@ -0,0 +1,20 @@ +package com.baeldung.filters; + +import org.springframework.web.reactive.function.server.HandlerFilterFunction; +import org.springframework.web.reactive.function.server.HandlerFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +import reactor.core.publisher.Mono; + +public class TraceHandlerFilterFunction implements HandlerFilterFunction { + + @Override + public Mono filter(ServerRequest request, HandlerFunction handlerFunction) { + + ServerRequest serverRequest = ServerRequest.from(request) + .header("traceId", "FUNCTIONAL-TRACE-ID") + .build(); + return handlerFunction.handle(serverRequest); + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/TraceWebFilter.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/TraceWebFilter.java new file mode 100644 index 0000000000..fcb5570db6 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/TraceWebFilter.java @@ -0,0 +1,20 @@ +package com.baeldung.filters; + +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; + +import reactor.core.publisher.Mono; + +@Component +public class TraceWebFilter implements WebFilter { + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + exchange.getRequest() + .mutate() + .header("traceId", "ANNOTATED-TRACE-ID"); + return chain.filter(exchange); + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/WebClientFilters.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/WebClientFilters.java new file mode 100644 index 0000000000..1748d4d103 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/filters/WebClientFilters.java @@ -0,0 +1,18 @@ +package com.baeldung.filters; + +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; + +public final class WebClientFilters { + + public static ExchangeFilterFunction modifyRequestHeaders(final MultiValueMap changedMap) { + return (request, next) -> { + final ClientRequest clientRequest = ClientRequest.from(request) + .header("traceId", "TRACE-ID") + .build(); + changedMap.addAll(clientRequest.headers()); + return next.exchange(clientRequest); + }; + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/handler/TraceRouterHandler.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/handler/TraceRouterHandler.java new file mode 100644 index 0000000000..7285a564c3 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/handler/TraceRouterHandler.java @@ -0,0 +1,22 @@ +package com.baeldung.handler; + +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +import reactor.core.publisher.Mono; + +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +@Component +public class TraceRouterHandler { + + public Mono handle(final ServerRequest serverRequest) { + + final String traceId = serverRequest.headers() + .firstHeader("traceId"); + assert traceId != null; + final Mono body = Mono.just("TraceId: ".concat(traceId)); + return ok().body(body, String.class); + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/router/TraceRouter.java b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/router/TraceRouter.java new file mode 100644 index 0000000000..cd25477965 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/java/com/baeldung/router/TraceRouter.java @@ -0,0 +1,27 @@ +package com.baeldung.router; + +import com.baeldung.filters.TraceHandlerFilterFunction; +import com.baeldung.handler.TraceRouterHandler; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; + +@Configuration +public class TraceRouter { + + @Bean + public RouterFunction routes(TraceRouterHandler routerHandler) { + return route(GET("/trace-functional-filter"), routerHandler::handle).filter(new TraceHandlerFilterFunction()) + .and(route().GET("/trace-functional-before", routerHandler::handle) + .before(request -> ServerRequest.from(request) + .header("traceId", "FUNCTIONAL-TRACE-ID") + .build()) + .build()); + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/main/resources/application.properties b/spring-reactive-modules/spring-reactive-4/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-reactive-modules/spring-reactive-4/src/main/resources/logback.xml b/spring-reactive-modules/spring-reactive-4/src/main/resources/logback.xml new file mode 100644 index 0000000000..26beb6d5b4 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/controller/TraceControllerIntegrationTest.java b/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/controller/TraceControllerIntegrationTest.java new file mode 100644 index 0000000000..eba9ba10a3 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/controller/TraceControllerIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.controller; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.EntityExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; + +@ExtendWith(SpringExtension.class) +@WebFluxTest(controllers = TraceController.class) +public class TraceControllerIntegrationTest { + + @Autowired + private WebTestClient webTestClient; + + @Test + void whenCallTraceAnnotatedEndpoint_thenResponseContainsTraceId() { + EntityExchangeResult result = webTestClient.get() + .uri("/trace-annotated") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .returnResult(); + + final String body = "TraceId: ANNOTATED-TRACE-ID"; + assertEquals(result.getResponseBody(), body); + + } + + @Test + void whenCallTraceExceptionalEndpoint_thenThrowsException() { + EntityExchangeResult result = webTestClient.get() + .uri("/trace-exceptional") + .exchange() + .expectStatus() + .is5xxServerError() + .expectBody(Map.class) + .returnResult(); + + assertNotNull(result.getResponseBody()); + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/filters/WebClientFilterUnitTest.java b/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/filters/WebClientFilterUnitTest.java new file mode 100644 index 0000000000..319f1e6f75 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/filters/WebClientFilterUnitTest.java @@ -0,0 +1,55 @@ +package com.baeldung.filters; + +import static com.baeldung.filters.WebClientFilters.modifyRequestHeaders; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient; + +import com.github.tomakehurst.wiremock.junit5.WireMockExtension; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; + +@WireMockTest +public class WebClientFilterUnitTest { + + @RegisterExtension + static WireMockExtension extension = WireMockExtension.newInstance() + .options(wireMockConfig().dynamicPort() + .dynamicHttpsPort()) + .build(); + + @Test + void whenCallEndpoint_thenRequestHeadersModified() { + extension.stubFor(get("/test").willReturn(aResponse().withStatus(200) + .withBody("SUCCESS"))); + + final MultiValueMap map = new LinkedMultiValueMap<>(); + + WebClient webClient = WebClient.builder() + .filter(modifyRequestHeaders(map)) + .build(); + String actual = sendGetRequest(webClient); + + final String body = "SUCCESS"; + Assertions.assertEquals(actual, body); + Assertions.assertEquals("TRACE-ID", map.getFirst("traceId")); + } + + private String sendGetRequest(final WebClient webClient) { + return webClient.get() + .uri(getUrl()) + .retrieve() + .bodyToMono(String.class) + .block(); + } + + private String getUrl() { + return "http://localhost:" + extension.getPort() + "/test"; + } +} diff --git a/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/handler/TraceRouteHandlerIntegrationTest.java b/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/handler/TraceRouteHandlerIntegrationTest.java new file mode 100644 index 0000000000..ee30dfd3a2 --- /dev/null +++ b/spring-reactive-modules/spring-reactive-4/src/test/java/com/baeldung/handler/TraceRouteHandlerIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.handler; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.EntityExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; + +import com.baeldung.router.TraceRouter; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { TraceRouter.class, TraceRouterHandler.class }) +@WebFluxTest +public class TraceRouteHandlerIntegrationTest { + + @Autowired + private ApplicationContext context; + private WebTestClient webTestClient; + + @BeforeEach + void setUp() { + webTestClient = WebTestClient.bindToApplicationContext(context) + .build(); + } + + @Test + void whenCallTraceFunctionalFilterEndpoint_thenResponseContainsTraceId() { + EntityExchangeResult result = webTestClient.get() + .uri("/trace-functional-filter") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .returnResult(); + + final String body = "TraceId: FUNCTIONAL-TRACE-ID"; + assertEquals(result.getResponseBody(), body); + } + + @Test + void whenCallTraceFunctionalBeforeEndpoint_thenResponseContainsTraceId() { + EntityExchangeResult result = webTestClient.get() + .uri("/trace-functional-before") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .returnResult(); + + final String body = "TraceId: FUNCTIONAL-TRACE-ID"; + assertEquals(result.getResponseBody(), body); + } +} diff --git a/spring-reactive-modules/spring-reactive-client/pom.xml b/spring-reactive-modules/spring-reactive-client/pom.xml index 797529b980..bcfbe31ed6 100644 --- a/spring-reactive-modules/spring-reactive-client/pom.xml +++ b/spring-reactive-modules/spring-reactive-client/pom.xml @@ -9,9 +9,10 @@ spring boot 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 @@ -42,8 +43,13 @@ ${reactor-spring.version} - javax.json.bind - javax.json.bind-api + jakarta.json.bind + jakarta.json.bind-api + + + jakarta.json + jakarta.json-api + ${jakarta.json-api.version} org.apache.geronimo.specs @@ -53,6 +59,7 @@ org.apache.johnzon johnzon-jsonb + ${johnzon-jsonb.version} @@ -92,7 +99,7 @@ test - com.github.tomakehurst + org.wiremock wiremock-standalone ${wiremock-standalone.version} test @@ -183,12 +190,14 @@ 1.0.1.RELEASE 1.0 - 1.1.6 + 4.0.3 5.0.0-alpha.12 3.5.3 - 2.26.0 - 3.1.4 + 3.4.2 + 4.0.3 2.0.0-Beta4 + 2.0.0 + 2.1.3 \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/controller/UploadController.java b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/controller/UploadController.java index 08d6ff55ef..55562f58f4 100644 --- a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/controller/UploadController.java +++ b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/controller/UploadController.java @@ -2,7 +2,7 @@ package com.baeldung.reactive.controller; import com.baeldung.reactive.service.ReactiveUploadService; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import reactor.core.publisher.Mono; @@ -18,13 +18,13 @@ public class UploadController { @PostMapping(path = "/upload") @ResponseBody - public Mono uploadPdf(@RequestParam("file") final MultipartFile multipartFile) { + public Mono uploadPdf(@RequestParam("file") final MultipartFile multipartFile) { return uploadService.uploadPdf(multipartFile.getResource()); } @PostMapping(path = "/upload/multipart") @ResponseBody - public Mono uploadMultipart(@RequestParam("file") final MultipartFile multipartFile) { + public Mono uploadMultipart(@RequestParam("file") final MultipartFile multipartFile) { return uploadService.uploadMultipart(multipartFile); } } diff --git a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/EmployeeService.java b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/EmployeeService.java index b841dbfe3f..c402efcbc1 100644 --- a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/EmployeeService.java +++ b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/EmployeeService.java @@ -1,4 +1,5 @@ package com.baeldung.reactive.service; + import com.baeldung.reactive.model.Employee; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; diff --git a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/ReactiveUploadService.java b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/ReactiveUploadService.java index a12d54960a..130e09816e 100644 --- a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/ReactiveUploadService.java +++ b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/reactive/service/ReactiveUploadService.java @@ -4,6 +4,7 @@ package com.baeldung.reactive.service; import com.baeldung.reactive.exception.ServiceException; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.client.MultipartBodyBuilder; import org.springframework.stereotype.Service; @@ -26,10 +27,10 @@ public class ReactiveUploadService { } - public Mono uploadPdf(final Resource resource) { + public Mono uploadPdf(final Resource resource) { final URI url = UriComponentsBuilder.fromHttpUrl(EXTERNAL_UPLOAD_URL).build().toUri(); - Mono httpStatusMono = webClient.post() + Mono httpStatusMono = webClient.post() .uri(url) .contentType(MediaType.APPLICATION_PDF) .body(BodyInserters.fromResource(resource)) @@ -44,13 +45,13 @@ public class ReactiveUploadService { } - public Mono uploadMultipart(final MultipartFile multipartFile) { + public Mono uploadMultipart(final MultipartFile multipartFile) { final URI url = UriComponentsBuilder.fromHttpUrl(EXTERNAL_UPLOAD_URL).build().toUri(); final MultipartBodyBuilder builder = new MultipartBodyBuilder(); builder.part("file", multipartFile.getResource()); - Mono httpStatusMono = webClient.post() + Mono httpStatusMono = webClient.post() .uri(url) .contentType(MediaType.MULTIPART_FORM_DATA) .body(BodyInserters.fromMultipartData(builder.build())) diff --git a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java index 784fcf2812..5c655430dd 100644 --- a/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java +++ b/spring-reactive-modules/spring-reactive-client/src/main/java/com/baeldung/webclient/status/WebClientStatusCodeHandler.java @@ -3,6 +3,7 @@ package com.baeldung.webclient.status; import com.baeldung.webclient.status.exception.CustomBadRequestException; import com.baeldung.webclient.status.exception.CustomServerErrorException; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; @@ -40,7 +41,7 @@ public class WebClientStatusCodeHandler { } private static Mono exchangeFilterResponseProcessor(ClientResponse response) { - HttpStatus status = response.statusCode(); + HttpStatusCode status = response.statusCode(); if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { return response.bodyToMono(String.class) .flatMap(body -> Mono.error(new CustomServerErrorException(body))); diff --git a/spring-reactive-modules/spring-reactive-client/src/main/resources/application.properties b/spring-reactive-modules/spring-reactive-client/src/main/resources/application.properties index 05033054b1..92e3aed117 100644 --- a/spring-reactive-modules/spring-reactive-client/src/main/resources/application.properties +++ b/spring-reactive-modules/spring-reactive-client/src/main/resources/application.properties @@ -1,5 +1,3 @@ logging.level.root=INFO - server.port=8081 - logging.level.reactor.netty.http.client.HttpClient=DEBUG \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/SpringContextTest.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/SpringContextTest.java index c0ca9b7e64..2434afd62e 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/SpringContextTest.java @@ -5,10 +5,10 @@ import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.reactive.Spring5ReactiveTestApplication; +import com.baeldung.reactive.SpringReactiveTestApplication; @RunWith(SpringRunner.class) -@SpringBootTest(classes = Spring5ReactiveTestApplication.class) +@SpringBootTest(classes = SpringReactiveTestApplication.class) public class SpringContextTest { @Test diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/ReactiveIntegrationTest.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/ReactiveIntegrationTest.java index 1d2197a381..c399667444 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/ReactiveIntegrationTest.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/ReactiveIntegrationTest.java @@ -49,7 +49,9 @@ public class ReactiveIntegrationTest { .withHeader("Content-Type", "application/json") .withBody("{\"id\":123, \"name\":\"foo\"}"))); - final Mono fooMono = client.get().uri("/foo/123").exchange().log(); + final Mono fooMono = client.get().uri("/foo/123").retrieve() + .bodyToMono(ClientResponse.class) + .log(); System.out.println(fooMono.subscribe()); } diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/Spring5ReactiveTestApplication.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/SpringReactiveTestApplication.java similarity index 87% rename from spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/Spring5ReactiveTestApplication.java rename to spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/SpringReactiveTestApplication.java index c884ace323..f6c578c48f 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/Spring5ReactiveTestApplication.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/SpringReactiveTestApplication.java @@ -9,7 +9,7 @@ import org.springframework.web.reactive.function.client.WebClient; import com.baeldung.reactive.model.Foo; @SpringBootApplication -public class Spring5ReactiveTestApplication { +public class SpringReactiveTestApplication { @Bean public WebClient client() { @@ -29,7 +29,7 @@ public class Spring5ReactiveTestApplication { // public static void main(String[] args) { - SpringApplication.run(Spring5ReactiveTestApplication.class, args); + SpringApplication.run(SpringReactiveTestApplication.class, args); } } diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java index 27dde13608..3686733de9 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -10,8 +10,8 @@ import static org.mockito.Mockito.when; import java.net.URI; import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; import org.springframework.http.client.reactive.JettyClientHttpConnector; @@ -73,9 +73,9 @@ public class WebClientLoggingIntegrationTest { } @Test + @Disabled public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { - SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); - org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient(sslContextFactory) { + org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient(){ @Override public Request newRequest(URI uri) { Request request = super.newRequest(uri); @@ -91,8 +91,7 @@ public class WebClientLoggingIntegrationTest { .uri(sampleUrl) .body(BodyInserters.fromObject(post)) .retrieve() - .bodyToMono(String.class) - .block(); + .bodyToMono(String.class); verify(jettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); } @@ -103,14 +102,16 @@ public class WebClientLoggingIntegrationTest { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() .wiretap(true); + WebClient .builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build() .post() .uri(sampleUrl) - .body(BodyInserters.fromObject(post)) - .exchange() + .body(BodyInserters.fromValue(post)) + .retrieve() + .bodyToMono(String.class) .block(); verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("00000300"))); @@ -126,8 +127,9 @@ public class WebClientLoggingIntegrationTest { .build() .post() .uri(sampleUrl) - .body(BodyInserters.fromObject(post)) - .exchange() + .body(BodyInserters.fromValue(post)) + .retrieve() + .bodyToMono(String.class) .block(); verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); @@ -141,9 +143,10 @@ public class WebClientLoggingIntegrationTest { .build() .post() .uri(sampleUrl) - .body(BodyInserters.fromObject(post)) - .exchange() - .block(); + .body(BodyInserters.fromValue(post)) + .retrieve() + .bodyToMono(String.class) + .block(); verify(mockAppender, atLeast(1)).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleUrl))); } diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java index c1c3d3e895..c8a7f05eb4 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java @@ -37,7 +37,7 @@ public class LogFilters { if (log.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Response: \n") .append("Status: ") - .append(clientResponse.rawStatusCode()); + .append(clientResponse.statusCode()); clientResponse .headers() .asHttpHeaders() diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/EmployeeServiceUnitTest.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/EmployeeServiceUnitTest.java index 1d1a8fd2e4..26ce3a1cec 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/EmployeeServiceUnitTest.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/EmployeeServiceUnitTest.java @@ -7,16 +7,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.exceptions.base.MockitoException; -import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) diff --git a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/ReactiveUploadServiceUnitTest.java b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/ReactiveUploadServiceUnitTest.java index 40c1e40d92..6baf2e8a61 100644 --- a/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/ReactiveUploadServiceUnitTest.java +++ b/spring-reactive-modules/spring-reactive-client/src/test/java/com/baeldung/reactive/service/ReactiveUploadServiceUnitTest.java @@ -3,6 +3,7 @@ package com.baeldung.reactive.service; import org.junit.jupiter.api.Test; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; @@ -28,8 +29,8 @@ class ReactiveUploadServiceUnitTest { void givenAPdf_whenUploadingWithWebClient_thenOK() { final Resource file = mock(Resource.class); - final Mono result = tested.uploadPdf(file); - final HttpStatus status = result.block(); + final Mono result = tested.uploadPdf(file); + final HttpStatusCode status = result.block(); assertThat(status).isEqualTo(HttpStatus.OK); } @@ -40,8 +41,8 @@ class ReactiveUploadServiceUnitTest { final MultipartFile multipartFile = mock(MultipartFile.class); when(multipartFile.getResource()).thenReturn(file); - final Mono result = tested.uploadMultipart(multipartFile); - final HttpStatus status = result.block(); + final Mono result = tested.uploadMultipart(multipartFile); + final HttpStatusCode status = result.block(); assertThat(status).isEqualTo(HttpStatus.OK); } diff --git a/spring-reactive-modules/spring-reactive-data-couchbase/pom.xml b/spring-reactive-modules/spring-reactive-data-couchbase/pom.xml index 7e09bf1770..d13706bbd5 100644 --- a/spring-reactive-modules/spring-reactive-data-couchbase/pom.xml +++ b/spring-reactive-modules/spring-reactive-data-couchbase/pom.xml @@ -65,6 +65,12 @@ ${couchbaseMock.version} test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + @@ -129,6 +135,7 @@ 11 11 11 + 1.14.13 \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-oauth/pom.xml b/spring-reactive-modules/spring-reactive-oauth/pom.xml index 9d2dbf6126..d4699acd6d 100644 --- a/spring-reactive-modules/spring-reactive-oauth/pom.xml +++ b/spring-reactive-modules/spring-reactive-oauth/pom.xml @@ -11,9 +11,10 @@ WebFlux and Spring Security OAuth - com.baeldung.spring.reactive - spring-reactive-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -62,4 +63,8 @@ + + com.baeldung.reactive.oauth.Spring5ReactiveOauthApplication + + \ No newline at end of file diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/SecurityConfig.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/SecurityConfig.java index 2fa1dd9380..c2069d3cdb 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/SecurityConfig.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/SecurityConfig.java @@ -1,6 +1,7 @@ package com.baeldung.reactive.oauth; import org.springframework.context.annotation.Bean; +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.web.server.SecurityWebFilterChain; @@ -10,10 +11,11 @@ public class SecurityConfig { @Bean public SecurityWebFilterChain configure(ServerHttpSecurity http) throws Exception { - return http.authorizeExchange() + return http.authorizeExchange(auth -> auth .pathMatchers("/about").permitAll() - .anyExchange().authenticated() - .and().oauth2Login() - .and().build(); + .anyExchange().authenticated()) + .oauth2Login(Customizer.withDefaults()) + .build(); } + } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java index b95517200e..7fe82404be 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java @@ -4,9 +4,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; +import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.web.reactive.function.client.WebClient; @PropertySource("classpath:default-application.yml") @@ -24,4 +27,13 @@ public class Spring5ReactiveOauthApplication { .filter(filter) .build(); } + + @Bean + public ReactiveClientRegistrationRepository clientRegistrations() { + ClientRegistration registration = ClientRegistration.withRegistrationId("bael").authorizationGrantType( + AuthorizationGrantType.CLIENT_CREDENTIALS).clientId("bael").tokenUri("default").build(); + + return new InMemoryReactiveClientRegistrationRepository(registration); + + } } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java index 4271ae96cf..325c322a73 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java @@ -2,6 +2,7 @@ package com.baeldung.webclient.authorizationcodeclient.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; @@ -9,13 +10,9 @@ import org.springframework.security.web.server.SecurityWebFilterChain; public class WebSecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http.authorizeExchange() - .anyExchange() - .authenticated() - .and() - .oauth2Client() - .and() - .formLogin(); + http.authorizeExchange(s-> s.anyExchange().authenticated()) + .oauth2Client(Customizer.withDefaults()) + .formLogin(Customizer.withDefaults()); return http.build(); } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java index f45fc09222..46e3828ec2 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java @@ -2,6 +2,7 @@ package com.baeldung.webclient.authorizationcodelogin.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; @@ -9,11 +10,8 @@ import org.springframework.security.web.server.SecurityWebFilterChain; public class WebSecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http.authorizeExchange() - .anyExchange() - .authenticated() - .and() - .oauth2Login(); + http.authorizeExchange(s-> s.anyExchange().authenticated()) + .oauth2Login(Customizer.withDefaults()); return http.build(); } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java index 8ffc92b4cd..1bf9ddd5be 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java @@ -1,22 +1,60 @@ package com.baeldung.webclient.clientcredentials.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; +import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; -import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository; +import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { @Bean - WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) { - ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository()); - oauth.setDefaultClientRegistrationId("bael"); - return WebClient.builder() - .filter(oauth) + ReactiveClientRegistrationRepository clientRegistrations( + @Value("${spring.security.oauth2.client.provider.bael.token-uri}") String token_uri, + @Value("${spring.security.oauth2.client.registration.bael.client-id}") String client_id, + @Value("${spring.security.oauth2.client.registration.bael.client-secret}") String client_secret, + @Value("${spring.security.oauth2.client.registration.bael.authorization-grant-type}") String authorizationGrantType + + ) { + ClientRegistration registration = ClientRegistration + .withRegistrationId("keycloak") + .tokenUri(token_uri) + .clientId(client_id) + .clientSecret(client_secret) + .authorizationGrantType(new AuthorizationGrantType(authorizationGrantType)) .build(); + return new InMemoryReactiveClientRegistrationRepository(registration); + } + @Bean + public AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager( + ReactiveClientRegistrationRepository clientRegistrationRepository) { + InMemoryReactiveOAuth2AuthorizedClientService clientService = + new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = + ReactiveOAuth2AuthorizedClientProviderBuilder.builder().clientCredentials().build(); + AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = + new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager( + clientRegistrationRepository, clientService); + authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + return authorizedClientManager; } + @Bean + WebClient webClient(AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager auth2AuthorizedClientManager) { + ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = + new ServerOAuth2AuthorizedClientExchangeFilterFunction(auth2AuthorizedClientManager); + oauth2Client.setDefaultClientRegistrationId("bael"); + return WebClient.builder() + .filter(oauth2Client) + .build(); + } } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java index 51fc60821a..33493be61d 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java @@ -11,6 +11,6 @@ public class WebClientConfig { public WebClient configureWebClient() { return WebClient.builder() .build(); - }; + } } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java index 1753681db8..0aa38d2a12 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java @@ -9,9 +9,7 @@ import org.springframework.security.web.server.SecurityWebFilterChain; public class WebSecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http.authorizeExchange() - .anyExchange() - .permitAll(); + http.authorizeExchange(s -> s.anyExchange().permitAll()); return http.build(); } } diff --git a/spring-reactive-modules/spring-reactive-oauth/src/test/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthIntegrationTest.java b/spring-reactive-modules/spring-reactive-oauth/src/test/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthIntegrationTest.java index db545d63de..fc2b540f4d 100644 --- a/spring-reactive-modules/spring-reactive-oauth/src/test/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthIntegrationTest.java +++ b/spring-reactive-modules/spring-reactive-oauth/src/test/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthIntegrationTest.java @@ -1,12 +1,13 @@ package com.baeldung.reactive.oauth; +import com.baeldung.webclient.clientcredentials.configuration.WebClientConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) -@SpringBootTest +@SpringBootTest(classes = WebClientConfig.class) public class Spring5ReactiveOauthIntegrationTest { @Test diff --git a/spring-remoting-modules/pom.xml b/spring-remoting-modules/pom.xml index f7f8abbf87..b5e288dd5f 100644 --- a/spring-remoting-modules/pom.xml +++ b/spring-remoting-modules/pom.xml @@ -21,7 +21,7 @@ - remoting-hessian-burlap + remoting-http remoting-amqp remoting-jms diff --git a/spring-scheduling-2/README.md b/spring-scheduling-2/README.md new file mode 100644 index 0000000000..7965a1c408 --- /dev/null +++ b/spring-scheduling-2/README.md @@ -0,0 +1,3 @@ +### Relevant articles: + +- [Disable @EnableScheduling on Spring Tests](https://www.baeldung.com/spring-test-disable-enablescheduling) diff --git a/spring-scheduling-2/pom.xml b/spring-scheduling-2/pom.xml new file mode 100644 index 0000000000..9c69758ed0 --- /dev/null +++ b/spring-scheduling-2/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + spring-scheduling-2 + 0.1-SNAPSHOT + spring-scheduling-2 + jar + + + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../parent-boot-3 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repackage + none + + + + + + + \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/DelayedNotificationScheduler.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/DelayedNotificationScheduler.java new file mode 100644 index 0000000000..91ed9beffc --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/DelayedNotificationScheduler.java @@ -0,0 +1,22 @@ +package com.baeldung.disablingscheduledtasks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; + +public class DelayedNotificationScheduler { + + private static final Logger logger = LoggerFactory.getLogger(DelayedNotificationScheduler.class); + + private NotificationService notificationService; + + public DelayedNotificationScheduler(NotificationService notificationService) { + this.notificationService = notificationService; + } + + @Scheduled(fixedDelayString = "${notification.send.out.delay}", initialDelayString = "${notification.send.out.initial.delay}") + public void attemptSendingOutDelayedNotifications() { + logger.info("Scheduled notifications send out attempt"); + notificationService.sendOutDelayedNotifications(); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/Notification.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/Notification.java new file mode 100644 index 0000000000..01ed80395e --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/Notification.java @@ -0,0 +1,31 @@ +package com.baeldung.disablingscheduledtasks; + +import java.time.Clock; +import java.time.ZonedDateTime; +import java.util.UUID; + +public class Notification { + + private UUID id = UUID.randomUUID(); + private boolean isSentOut = false; + private ZonedDateTime sendOutTime; + + public Notification(ZonedDateTime sendOutTime) { + this.sendOutTime = sendOutTime; + } + + public void sendOut(Clock clock) { + ZonedDateTime now = ZonedDateTime.now(clock); + if (now.isAfter(sendOutTime)) { + isSentOut = true; + } + } + + public UUID getId() { + return id; + } + + public boolean isSentOut() { + return isSentOut; + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/NotificationRepository.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/NotificationRepository.java new file mode 100644 index 0000000000..08fe8c830d --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/NotificationRepository.java @@ -0,0 +1,30 @@ +package com.baeldung.disablingscheduledtasks; + +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.stream.Collectors; + +public class NotificationRepository { + + private Collection notifications = new ConcurrentLinkedQueue<>(); + + public Notification findById(UUID notificationId) { + return notifications.stream() + .filter(n -> notificationId.equals(n.getId())) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } + + public List findAllAwaitingSendOut() { + return notifications.stream() + .filter(notification -> !notification.isSentOut()) + .collect(Collectors.toList()); + } + + public void save(Notification notification) { + notifications.add(notification); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/NotificationService.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/NotificationService.java new file mode 100644 index 0000000000..3451a05cbe --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/NotificationService.java @@ -0,0 +1,26 @@ +package com.baeldung.disablingscheduledtasks; + +import java.time.Clock; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NotificationService { + + private static final Logger logger = LoggerFactory.getLogger(NotificationService.class); + + private NotificationRepository notificationRepository; + private Clock clock; + + public NotificationService(NotificationRepository notificationRepository, Clock clock) { + this.notificationRepository = notificationRepository; + this.clock = clock; + } + + public void sendOutDelayedNotifications() { + logger.info("Sending out delayed notifications"); + List notifications = notificationRepository.findAllAwaitingSendOut(); + notifications.forEach(notification -> notification.sendOut(clock)); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithprofile/ApplicationConfig.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithprofile/ApplicationConfig.java new file mode 100644 index 0000000000..19a69840ff --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithprofile/ApplicationConfig.java @@ -0,0 +1,34 @@ +package com.baeldung.disablingscheduledtasks.config.disablewithprofile; + +import java.time.Clock; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.NotificationService; + +@Configuration +public class ApplicationConfig { + + @Bean + public Clock clock() { + return Clock.systemUTC(); + } + + @Bean + public NotificationRepository notificationRepository() { + return new NotificationRepository(); + } + + @Bean + public NotificationService notificationService(NotificationRepository notificationRepository, Clock clock) { + return new NotificationService(notificationRepository, clock); + } + + @Bean + public DelayedNotificationScheduler delayedNotificationScheduler(NotificationService notificationService) { + return new DelayedNotificationScheduler(notificationService); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithprofile/SchedulingConfig.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithprofile/SchedulingConfig.java new file mode 100644 index 0000000000..6461b9273d --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithprofile/SchedulingConfig.java @@ -0,0 +1,12 @@ +package com.baeldung.disablingscheduledtasks.config.disablewithprofile; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.EnableScheduling; + +@Configuration +@EnableScheduling +@Profile("!integrationTest") +public class SchedulingConfig { + +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithproperty/ApplicationConfig.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithproperty/ApplicationConfig.java new file mode 100644 index 0000000000..8b006428d2 --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithproperty/ApplicationConfig.java @@ -0,0 +1,34 @@ +package com.baeldung.disablingscheduledtasks.config.disablewithproperty; + +import java.time.Clock; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.NotificationService; + +@Configuration +public class ApplicationConfig { + + @Bean + public Clock clock() { + return Clock.systemUTC(); + } + + @Bean + public NotificationRepository notificationRepository() { + return new NotificationRepository(); + } + + @Bean + public NotificationService notificationService(NotificationRepository notificationRepository, Clock clock) { + return new NotificationService(notificationRepository, clock); + } + + @Bean + public DelayedNotificationScheduler delayedNotificationScheduler(NotificationService notificationService) { + return new DelayedNotificationScheduler(notificationService); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithproperty/SchedulingConfig.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithproperty/SchedulingConfig.java new file mode 100644 index 0000000000..2b85dbfcef --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/disablewithproperty/SchedulingConfig.java @@ -0,0 +1,12 @@ +package com.baeldung.disablingscheduledtasks.config.disablewithproperty; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +@Configuration +@EnableScheduling +@ConditionalOnProperty(value = "scheduling.enabled", havingValue = "true", matchIfMissing = true) +public class SchedulingConfig { + +} \ No newline at end of file diff --git a/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/schedulingon/ApplicationConfig.java b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/schedulingon/ApplicationConfig.java new file mode 100644 index 0000000000..e0db118831 --- /dev/null +++ b/spring-scheduling-2/src/main/java/com/baeldung/disablingscheduledtasks/config/schedulingon/ApplicationConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.disablingscheduledtasks.config.schedulingon; + +import java.time.Clock; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.NotificationService; + +@Configuration +@EnableScheduling +public class ApplicationConfig { + + @Bean + public Clock clock() { + return Clock.systemUTC(); + } + + @Bean + public NotificationRepository notificationRepository() { + return new NotificationRepository(); + } + + @Bean + public NotificationService notificationService(NotificationRepository notificationRepository, Clock clock) { + return new NotificationService(notificationRepository, clock); + } + + @Bean + public DelayedNotificationScheduler delayedNotificationScheduler(NotificationService notificationService) { + return new DelayedNotificationScheduler(notificationService); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/disablewithprofile/DelayedNotificationSchedulerIntegrationTest.java b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/disablewithprofile/DelayedNotificationSchedulerIntegrationTest.java new file mode 100644 index 0000000000..523950e48c --- /dev/null +++ b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/disablewithprofile/DelayedNotificationSchedulerIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.disablingscheduledtasks.disablewithprofile; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.Notification; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.config.disablewithprofile.ApplicationConfig; +import com.baeldung.disablingscheduledtasks.config.disablewithprofile.SchedulingConfig; + +@SpringBootTest( + classes = { ApplicationConfig.class, SchedulingConfig.class, SchedulerTestConfiguration.class }, + properties = { + "notification.send.out.delay: 10", + "notification.send.out.initial.delay: 0" + } +) +@ActiveProfiles("integrationTest") +public class DelayedNotificationSchedulerIntegrationTest { + + @Autowired + private Clock testClock; + + @Autowired + private NotificationRepository repository; + + @Autowired + private DelayedNotificationScheduler scheduler; + + @Test + public void whenTimeIsOverNotificationSendOutTime_thenItShouldBeSent() { + ZonedDateTime fiveMinutesAgo = ZonedDateTime.now(testClock).minusMinutes(5); + Notification notification = new Notification(fiveMinutesAgo); + repository.save(notification); + + scheduler.attemptSendingOutDelayedNotifications(); + + Notification processedNotification = repository.findById(notification.getId()); + assertTrue(processedNotification.isSentOut()); + } +} + +@TestConfiguration +class SchedulerTestConfiguration { + + @Bean + @Primary + public Clock testClock() { + return Clock.fixed(Instant.parse("2024-03-10T10:15:30.00Z"), ZoneId.systemDefault()); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/disablewithproperty/DelayedNotificationSchedulerIntegrationTest.java b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/disablewithproperty/DelayedNotificationSchedulerIntegrationTest.java new file mode 100644 index 0000000000..da3a061cfc --- /dev/null +++ b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/disablewithproperty/DelayedNotificationSchedulerIntegrationTest.java @@ -0,0 +1,63 @@ +package com.baeldung.disablingscheduledtasks.disablewithproperty; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.Notification; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.config.disablewithproperty.ApplicationConfig; +import com.baeldung.disablingscheduledtasks.config.disablewithproperty.SchedulingConfig; + +@SpringBootTest( + classes = { ApplicationConfig.class, SchedulingConfig.class, SchedulerTestConfiguration.class }, + properties = { + "notification.send.out.delay: 10", + "notification.send.out.initial.delay: 0", + "scheduling.enabled: false" + } +) +public class DelayedNotificationSchedulerIntegrationTest { + + @Autowired + private Clock testClock; + + @Autowired + private NotificationRepository repository; + + @Autowired + private DelayedNotificationScheduler scheduler; + + @Test + public void whenTimeIsOverNotificationSendOutTime_thenItShouldBeSent() { + ZonedDateTime fiveMinutesAgo = ZonedDateTime.now(testClock).minusMinutes(5); + Notification notification = new Notification(fiveMinutesAgo); + repository.save(notification); + + scheduler.attemptSendingOutDelayedNotifications(); + + Notification processedNotification = repository.findById(notification.getId()); + assertTrue(processedNotification.isSentOut()); + } +} + +@TestConfiguration +class SchedulerTestConfiguration { + + @Bean + @Primary + public Clock testClock() { + return Clock.fixed(Instant.parse("2024-03-10T10:15:30.00Z"), ZoneId.systemDefault()); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/longinitialdelay/DelayedNotificationSchedulerIntegrationTest.java b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/longinitialdelay/DelayedNotificationSchedulerIntegrationTest.java new file mode 100644 index 0000000000..d67af13b9d --- /dev/null +++ b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/longinitialdelay/DelayedNotificationSchedulerIntegrationTest.java @@ -0,0 +1,61 @@ +package com.baeldung.disablingscheduledtasks.longinitialdelay; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.Notification; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.config.schedulingon.ApplicationConfig; + +@SpringBootTest( + classes = { ApplicationConfig.class, SchedulerTestConfiguration.class }, + properties = { + "notification.send.out.delay: 10", + "notification.send.out.initial.delay: 60000" + } +) +public class DelayedNotificationSchedulerIntegrationTest { + + @Autowired + private Clock testClock; + + @Autowired + private NotificationRepository repository; + + @Autowired + private DelayedNotificationScheduler scheduler; + + @Test + public void whenTimeIsOverNotificationSendOutTime_thenItShouldBeSent() { + ZonedDateTime fiveMinutesAgo = ZonedDateTime.now(testClock).minusMinutes(5); + Notification notification = new Notification(fiveMinutesAgo); + repository.save(notification); + + scheduler.attemptSendingOutDelayedNotifications(); + + Notification processedNotification = repository.findById(notification.getId()); + assertTrue(processedNotification.isSentOut()); + } +} + +@TestConfiguration +class SchedulerTestConfiguration { + + @Bean + @Primary + public Clock testClock() { + return Clock.fixed(Instant.parse("2024-03-10T10:15:30.00Z"), ZoneId.systemDefault()); + } +} \ No newline at end of file diff --git a/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/schedulingon/DelayedNotificationSchedulerIntegrationTest.java b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/schedulingon/DelayedNotificationSchedulerIntegrationTest.java new file mode 100644 index 0000000000..eb351ee2d1 --- /dev/null +++ b/spring-scheduling-2/src/test/java/com/baeldung/disablingscheduledtasks/schedulingon/DelayedNotificationSchedulerIntegrationTest.java @@ -0,0 +1,61 @@ +package com.baeldung.disablingscheduledtasks.schedulingon; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import com.baeldung.disablingscheduledtasks.DelayedNotificationScheduler; +import com.baeldung.disablingscheduledtasks.Notification; +import com.baeldung.disablingscheduledtasks.NotificationRepository; +import com.baeldung.disablingscheduledtasks.config.schedulingon.ApplicationConfig; + +@SpringBootTest( + classes = { ApplicationConfig.class, SchedulerTestConfiguration.class }, + properties = { + "notification.send.out.delay: 10", + "notification.send.out.initial.delay: 0" + } +) +public class DelayedNotificationSchedulerIntegrationTest { + + @Autowired + private Clock testClock; + + @Autowired + private NotificationRepository repository; + + @Autowired + private DelayedNotificationScheduler scheduler; + + @Test + public void whenTimeIsOverNotificationSendOutTime_thenItShouldBeSent() { + ZonedDateTime fiveMinutesAgo = ZonedDateTime.now(testClock).minusMinutes(5); + Notification notification = new Notification(fiveMinutesAgo); + repository.save(notification); + + scheduler.attemptSendingOutDelayedNotifications(); + + Notification processedNotification = repository.findById(notification.getId()); + assertTrue(processedNotification.isSentOut()); + } +} + +@TestConfiguration +class SchedulerTestConfiguration { + + @Bean + @Primary + public Clock testClock() { + return Clock.fixed(Instant.parse("2024-03-10T10:15:30.00Z"), ZoneId.systemDefault()); + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/pom.xml b/spring-security-modules/spring-security-legacy-oidc/pom.xml index 10c6eb3389..0fb10c7e4f 100644 --- a/spring-security-modules/spring-security-legacy-oidc/pom.xml +++ b/spring-security-modules/spring-security-legacy-oidc/pom.xml @@ -42,6 +42,12 @@ jwks-rsa ${jwks-rsa.version} + + net.bytebuddy + byte-buddy + 1.14.13 + test + diff --git a/spring-security-modules/spring-security-web-springdoc/pom.xml b/spring-security-modules/spring-security-web-springdoc/pom.xml index 1df710394e..5ce51ed5b0 100644 --- a/spring-security-modules/spring-security-web-springdoc/pom.xml +++ b/spring-security-modules/spring-security-web-springdoc/pom.xml @@ -28,7 +28,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - ${springdoc.version} + ${springdoc-openapi-webmvc-ui.version} com.google.guava @@ -45,6 +45,7 @@ 2.4.0 com.baeldung.basicauth.SpringBootSpringdocBasicAuth + 2.5.0 \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml index d4fff21605..c1795b500c 100644 --- a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml +++ b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml @@ -77,7 +77,6 @@ true true 5.9.3 - 5.3.1 3.1.1.RELEASE 3.1.1 diff --git a/testing-modules/junit-5-basics-2/pom.xml b/testing-modules/junit-5-basics-2/pom.xml index d8bb2a6e79..27681d66eb 100644 --- a/testing-modules/junit-5-basics-2/pom.xml +++ b/testing-modules/junit-5-basics-2/pom.xml @@ -26,7 +26,7 @@ org.mockito mockito-core - ${mockito-core.version} + ${mockito.version} test @@ -42,7 +42,6 @@ 5.10.0 - 5.5.0 \ No newline at end of file diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index cdddf90855..63162e71e8 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -89,11 +89,6 @@ ${powermock.version} test - - org.mockito - mockito-core - test - @@ -135,7 +130,7 @@ 2.17.1 2.0.9 5.0.1.RELEASE - 3.3.0 + 3.3.0 \ No newline at end of file diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md index 4d93bbcb23..b3eeadd8f1 100644 --- a/testing-modules/mockito-2/README.md +++ b/testing-modules/mockito-2/README.md @@ -12,3 +12,5 @@ This module contains articles about Mockito - [Verify That Lambda Expression Was Called Using Mockito](https://www.baeldung.com/java-mockito-verify-lambda-expression) - [Injecting @Mock and @Captor in JUnit 5 Method Parameters](https://www.baeldung.com/junit-5-mock-captor-method-parameter-injection) - [Fix Ambiguous Method Call Error in Mockito](https://www.baeldung.com/mockito-fix-ambiguous-method-call-error) +- [Multiple-Level Mock Injection Into Mockito Spy Objects](https://www.baeldung.com/mockito-multiple-level-mock-injection) + diff --git a/testing-modules/mockito-2/pom.xml b/testing-modules/mockito-2/pom.xml index 79b8c86221..f4ff2da682 100644 --- a/testing-modules/mockito-2/pom.xml +++ b/testing-modules/mockito-2/pom.xml @@ -34,8 +34,8 @@ 4.8.1 - 5.10.0 1.18.30 + \ No newline at end of file diff --git a/testing-modules/mockito-simple/pom.xml b/testing-modules/mockito-simple/pom.xml index 6f50136de6..7a07ea73ee 100644 --- a/testing-modules/mockito-simple/pom.xml +++ b/testing-modules/mockito-simple/pom.xml @@ -60,7 +60,6 @@ 6.0.8 - 5.3.1 \ No newline at end of file diff --git a/testing-modules/powermock/pom.xml b/testing-modules/powermock/pom.xml index 8eedc818af..0c3b1c367f 100644 --- a/testing-modules/powermock/pom.xml +++ b/testing-modules/powermock/pom.xml @@ -41,7 +41,7 @@ - 2.21.0 + 2.21.0 2.0.9 diff --git a/web-modules/jakarta-ee/pom.xml b/web-modules/jakarta-ee/pom.xml index faad33338b..4caa67bf6f 100644 --- a/web-modules/jakarta-ee/pom.xml +++ b/web-modules/jakarta-ee/pom.xml @@ -48,7 +48,7 @@ org.mockito - mockito-all + mockito-core ${mockito.version} test @@ -100,11 +100,10 @@ 9.0.0 2.0.0 2.0.0 - 5.8.2 + 5.10.2 C:/glassfish6 admin mvn-domain - 1.10.19 ${local.glassfish.home}\\domains\\${local.glassfish.domain}\\config\\domain-passwords diff --git a/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java b/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java index 5e79924ed7..a116db3c65 100644 --- a/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java +++ b/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java @@ -1,25 +1,23 @@ package com.baeldung.eclipse.krazo; -import com.baeldung.eclipse.krazo.User; -import com.baeldung.eclipse.krazo.UserController; -import jakarta.mvc.Models; -import jakarta.mvc.binding.BindingResult; -import org.eclipse.krazo.core.ModelsImpl; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; +import org.eclipse.krazo.core.ModelsImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import jakarta.mvc.Models; +import jakarta.mvc.binding.BindingResult; + /** * The class contains unit tests. We do only unit tests. Most of the classes are mocked */ diff --git a/web-modules/javax-servlets-2/pom.xml b/web-modules/javax-servlets-2/pom.xml index a792f6eea2..8031786af4 100644 --- a/web-modules/javax-servlets-2/pom.xml +++ b/web-modules/javax-servlets-2/pom.xml @@ -112,7 +112,6 @@ 2.22.2 10.0.4 1.10.0 - 5.6.0 1.5.4 diff --git a/web-modules/jee-7/pom.xml b/web-modules/jee-7/pom.xml index 47d79f12ac..9bbfc33e62 100644 --- a/web-modules/jee-7/pom.xml +++ b/web-modules/jee-7/pom.xml @@ -312,7 +312,7 @@ test - org.wildfly + org.wildfly.arquillian wildfly-arquillian-container-managed ${wildfly.version} test @@ -345,7 +345,7 @@ org.wildfly wildfly-dist - ${wildfly.version} + ${wildfly-dist.version} zip false ${project.build.directory} @@ -395,7 +395,7 @@ test - org.wildfly + org.wildfly.arquillian wildfly-arquillian-container-remote ${wildfly.version} test @@ -520,7 +520,8 @@ 3.0.0 7.0 1.1.11.Final - 8.2.1.Final + 31.0.1.Final + 5.0.1.Final 1.7.0 1.4.6.Final 3.0.19.Final diff --git a/web-modules/jersey/src/main/java/com/baeldung/jersey/server/Greetings.java b/web-modules/jersey/src/main/java/com/baeldung/jersey/server/Greetings.java index e753d34901..e87bd100c8 100644 --- a/web-modules/jersey/src/main/java/com/baeldung/jersey/server/Greetings.java +++ b/web-modules/jersey/src/main/java/com/baeldung/jersey/server/Greetings.java @@ -5,6 +5,7 @@ import com.baeldung.jersey.server.config.HelloBinding; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Response; @Path("/greetings") @@ -17,6 +18,7 @@ public class Greetings { } @GET + @Produces("text/html") @Path("/hi") public String getHiGreeting() { return "hi"; diff --git a/web-modules/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java b/web-modules/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java index 47736f90d7..e01415b50a 100644 --- a/web-modules/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java +++ b/web-modules/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java @@ -1,18 +1,18 @@ package com.baeldung.jersey.server; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; -import org.junit.Test; +import org.junit.jupiter.api.Test; import jakarta.ws.rs.core.Application; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -public class GreetingsResourceIntegrationTest extends JerseyTest { +class GreetingsResourceIntegrationTest extends JerseyTest { @Override protected Application configure() { @@ -21,14 +21,14 @@ public class GreetingsResourceIntegrationTest extends JerseyTest { } @Test - public void givenGetHiGreeting_whenCorrectRequest_thenResponseIsOkAndContainsHi() { + void givenGetHiGreeting_whenCorrectRequest_thenResponseIsOkAndContainsHi() { Response response = target("/greetings/hi").request() .get(); - assertEquals("Http Response should be 200: ", Response.Status.OK.getStatusCode(), response.getStatus()); - assertEquals("Http Content-Type should be: ", MediaType.TEXT_HTML, response.getHeaderString(HttpHeaders.CONTENT_TYPE)); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + assertEquals(MediaType.TEXT_HTML, response.getHeaderString(HttpHeaders.CONTENT_TYPE)); String content = response.readEntity(String.class); - assertEquals("Content of ressponse is: ", "hi", content); + assertEquals("hi", content); } } diff --git a/web-modules/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java b/web-modules/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java index 4f73c9df5b..2eaeb94a00 100644 --- a/web-modules/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java +++ b/web-modules/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java @@ -2,12 +2,12 @@ package com.baeldung.jersey.server.rest; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.baeldung.jersey.server.config.ViewApplicationConfig; import com.baeldung.jersey.server.model.Fruit; @@ -19,7 +19,7 @@ import jakarta.ws.rs.core.Form; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -public class FruitResourceIntegrationTest extends JerseyTest { +class FruitResourceIntegrationTest extends JerseyTest { @Override protected Application configure() { @@ -33,80 +33,80 @@ public class FruitResourceIntegrationTest extends JerseyTest { } @Test - public void givenGetAllFruit_whenCorrectRequest_thenAllTemplateInvoked() { + void givenGetAllFruit_whenCorrectRequest_thenAllTemplateInvoked() { final String response = target("/fruit/all").request() .get(String.class); assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi"))); } @Test - public void givenGetFruit_whenCorrectRequest_thenIndexTemplateInvoked() { + void givenGetFruit_whenCorrectRequest_thenIndexTemplateInvoked() { final String response = target("/fruit").request() .get(String.class); assertThat(response, containsString("Welcome Fruit Index Page!")); } @Test - public void givenGetFruitByName_whenFruitUnknown_thenErrorTemplateInvoked() { + void givenGetFruitByName_whenFruitUnknown_thenErrorTemplateInvoked() { final String response = target("/fruit/orange").request() .get(String.class); assertThat(response, containsString("Error - Fruit not found: orange!")); } @Test - public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() { + void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() { Form form = new Form(); form.param("name", "apple"); form.param("colour", null); Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED) .post(Entity.form(form)); - assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertEquals(400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null")); } @Test - public void givenCreateFruit_whenJsonIsCorrect_thenResponseCodeIsCreated() { + void givenCreateFruit_whenJsonIsCorrect_thenResponseCodeIsCreated() { Response response = target("fruit/created").request() .post(Entity.json("{\"name\":\"strawberry\",\"weight\":20}")); - assertEquals("Http Response should be 201 ", Response.Status.CREATED.getStatusCode(), response.getStatus()); + assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit saved : Fruit [name: strawberry colour: null]")); } @Test - public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() { + void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() { Form form = new Form(); form.param("serial", "2345-2345"); Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED) .put(Entity.form(form)); - assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertEquals(400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid")); } @Test - public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() { + void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() { Fruit fruit = new Fruit("Blueberry", "purple"); fruit.setWeight(1); Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); - assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertEquals(400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater")); } @Test - public void givenFruitExists_whenSearching_thenResponseContainsFruit() { + void givenFruitExists_whenSearching_thenResponseContainsFruit() { Fruit fruit = new Fruit(); fruit.setName("strawberry"); fruit.setWeight(20); Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); - assertEquals("Http Response should be 204 ", 204, response.getStatus()); + assertEquals(204, response.getStatus()); final String json = target("fruit/search/strawberry").request() .get(String.class); @@ -114,28 +114,28 @@ public class FruitResourceIntegrationTest extends JerseyTest { } @Test - public void givenFruitExists_whenSearching_thenResponseContainsFruitEntity() { + void givenFruitExists_whenSearching_thenResponseContainsFruitEntity() { Fruit fruit = new Fruit(); fruit.setName("strawberry"); fruit.setWeight(20); Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); - assertEquals("Http Response should be 204 ", 204, response.getStatus()); + assertEquals(204, response.getStatus()); final Fruit entity = target("fruit/search/strawberry").request() .get(Fruit.class); - assertEquals("Fruit name: ", "strawberry", entity.getName()); - assertEquals("Fruit weight: ", Integer.valueOf(20), entity.getWeight()); + assertEquals("strawberry", entity.getName()); + assertEquals(Integer.valueOf(20), entity.getWeight()); } @Test - public void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() { + void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() { final Response response = target("fruit/exception").request() .get(); - assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertEquals(400, response.getStatus()); String responseString = response.readEntity(String.class); assertThat(responseString, containsString("exception..colour size must be between 5 and 200")); assertThat(responseString, containsString("exception..name size must be between 5 and 200")); diff --git a/web-modules/ratpack/pom.xml b/web-modules/ratpack/pom.xml index 3f93f25bef..c392788068 100644 --- a/web-modules/ratpack/pom.xml +++ b/web-modules/ratpack/pom.xml @@ -106,6 +106,8 @@ 1.5.12 2.4.15 1.6.1 + 1.7.32 + 1.2.7 \ No newline at end of file diff --git a/xml-2/src/test/java/com/baeldung/xml/invalidcharacters/InvalidCharactersUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/invalidcharacters/InvalidCharactersUnitTest.java new file mode 100644 index 0000000000..7878e72f97 --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/invalidcharacters/InvalidCharactersUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.xml.invalidcharacters; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXParseException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public class InvalidCharactersUnitTest { + + @Test + void givenXml_whenReservedCharacters_thenThrowException() { + String invalidXmlString = "John & Doe"; + assertThrowsExactly(SAXParseException.class, () -> parseXmlString(invalidXmlString)); + } + + @Test + void givenXml_whenReservedCharactersEscaped_thenSuccess() { + String validXmlString = "John & Doe"; + + assertDoesNotThrow(() -> { + Document document = parseXmlString(validXmlString); + + assertNotNull(document); + assertEquals("John & Doe", document.getElementsByTagName("name").item(0).getTextContent()); + }); + } + + @Test + void givenXml_whenUsingCdataForReservedCharacters_thenSuccess() { + String validXmlString = ""; + + assertDoesNotThrow(() -> { + Document document = parseXmlString(validXmlString); + + assertNotNull(document); + assertEquals("John & Doe", document.getElementsByTagName("name").item(0).getTextContent()); + }); + } + + @Test + void givenXml_whenUnicodeCharacters_thenThrowException() { + String invalidXmlString = "John \u001E Doe"; + assertThrowsExactly(SAXParseException.class, () -> parseXmlString(invalidXmlString)); + } + + @Test + void givenXml_whenUnicodeCharactersEscaped_thenSuccess() { + String validXmlString = "John  Doe"; + assertDoesNotThrow(() -> { + Document document = parseXmlString(validXmlString); + + assertNotNull(document); + assertEquals("John \u001E Doe", document.getElementsByTagName("name").item(0).getTextContent()); + }); + } + + private Document parseXmlString(String xmlString) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource inputSource = new InputSource(new StringReader(xmlString)); + return builder.parse(inputSource); + } +}