diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/primeundernumber/LargestPrimeFinder.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/primeundernumber/LargestPrimeFinder.java
new file mode 100644
index 0000000000..bf4e785f29
--- /dev/null
+++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/primeundernumber/LargestPrimeFinder.java
@@ -0,0 +1,43 @@
+package com.baeldung.algorithms.primeundernumber;
+
+import java.util.Arrays;
+
+public class LargestPrimeFinder {
+
+ public static int findByBruteForce(int n) {
+ for (int i = n - 1; i >= 2; i--) {
+ if (isPrime(i)) {
+ return i;
+ }
+ }
+ return -1; // Return -1 if no prime number is found
+ }
+
+ public static boolean isPrime(int number) {
+ for (int i = 2; i <= Math.sqrt(number); i++) {
+ if (number % i == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int findBySieveOfEratosthenes(int n) {
+ boolean[] isPrime = new boolean[n];
+ Arrays.fill(isPrime, true);
+ for (int p = 2; p*p < n; p++) {
+ if (isPrime[p]) {
+ for (int i = p * p; i < n; i += p) {
+ isPrime[i] = false;
+ }
+ }
+ }
+
+ for (int i = n - 1; i >= 2; i--) {
+ if (isPrime[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/primeundernumber/LargestPrimeFinderUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/primeundernumber/LargestPrimeFinderUnitTest.java
new file mode 100644
index 0000000000..f046431424
--- /dev/null
+++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/primeundernumber/LargestPrimeFinderUnitTest.java
@@ -0,0 +1,32 @@
+package com.baeldung.algorithms.primeundernumber;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class LargestPrimeFinderUnitTest {
+
+ @Test
+ public void givenNormalCases_whenFindPrime_ThenFoundResult() {
+ assertEquals(7, LargestPrimeFinder.findByBruteForce(10));
+ assertEquals(97, LargestPrimeFinder.findByBruteForce(100));
+ assertEquals(7, LargestPrimeFinder.findBySieveOfEratosthenes(10));
+ assertEquals(97, LargestPrimeFinder.findBySieveOfEratosthenes(100));
+ }
+
+ @Test
+ public void givenEdgeCases_whenFindPrime_ThenNotFoundResult() {
+ assertEquals(-1, LargestPrimeFinder.findByBruteForce(0));
+ assertEquals(-1, LargestPrimeFinder.findByBruteForce(1));
+ assertEquals(-1, LargestPrimeFinder.findByBruteForce(2));
+ assertEquals(-1, LargestPrimeFinder.findBySieveOfEratosthenes(0));
+ assertEquals(-1, LargestPrimeFinder.findBySieveOfEratosthenes(1));
+ assertEquals(-1, LargestPrimeFinder.findBySieveOfEratosthenes(2));
+ }
+
+ @Test
+ public void givenLargeInput_whenFindPrime_ThenFoundResult() {
+ assertEquals(99991, LargestPrimeFinder.findByBruteForce(100000));
+ assertEquals(99991, LargestPrimeFinder.findBySieveOfEratosthenes(100000));
+ }
+}
diff --git a/algorithms-modules/algorithms-searching/README.md b/algorithms-modules/algorithms-searching/README.md
index 7d10100832..394d14a06c 100644
--- a/algorithms-modules/algorithms-searching/README.md
+++ b/algorithms-modules/algorithms-searching/README.md
@@ -13,3 +13,4 @@ This module contains articles about searching algorithms.
- [Range Search Algorithm in Java](https://www.baeldung.com/java-range-search)
- [Fast Pattern Matching of Strings Using Suffix Tree in Java](https://www.baeldung.com/java-pattern-matching-suffix-tree)
- [Find the Kth Smallest Element in Two Sorted Arrays in Java](https://www.baeldung.com/java-kth-smallest-element-in-sorted-arrays)
+- [Find the First Non-repeating Element of a List](https://www.baeldung.com/java-list-find-first-non-repeating-element)
diff --git a/apache-libraries-2/pom.xml b/apache-libraries-2/pom.xml
index d188204208..2e7ef0344c 100644
--- a/apache-libraries-2/pom.xml
+++ b/apache-libraries-2/pom.xml
@@ -19,10 +19,29 @@
validation-api
${javax.validation.validation-api.version}
+
+ org.apache.camel
+ camel-core
+ ${camel.version}
+
+
+
+ org.apache.camel
+ camel-test-junit5
+ ${camel.version}
+ test
+
+
+
+ org.apache.camel
+ camel-main
+ ${camel.version}
+
2.0.1.Final
+ 4.3.0
\ No newline at end of file
diff --git a/apache-libraries-2/src/main/java/com/baeldung/dynamicrouter/DynamicRouterBean.java b/apache-libraries-2/src/main/java/com/baeldung/dynamicrouter/DynamicRouterBean.java
new file mode 100644
index 0000000000..a28c3959a4
--- /dev/null
+++ b/apache-libraries-2/src/main/java/com/baeldung/dynamicrouter/DynamicRouterBean.java
@@ -0,0 +1,29 @@
+package com.baeldung.dynamicrouter;
+
+import org.apache.camel.ExchangeProperties;
+
+import java.util.Map;
+
+public class DynamicRouterBean {
+ public String route(String body, @ExchangeProperties Map properties) {
+ int invoked = (int) properties.getOrDefault("invoked", 0) + 1;
+
+ properties.put("invoked", invoked);
+
+ if (invoked == 1) {
+ switch (body.toLowerCase()) {
+ case "mock":
+ return "mock:dynamicRouter";
+ case "direct":
+ return "mock:directDynamicRouter";
+ case "seda":
+ return "mock:sedaDynamicRouter";
+ case "file":
+ return "mock:fileDynamicRouter";
+ default:
+ break;
+ }
+ }
+ return null;
+ }
+}
diff --git a/apache-libraries-2/src/main/java/com/baeldung/dynamicrouter/DynamicRouterRoute.java b/apache-libraries-2/src/main/java/com/baeldung/dynamicrouter/DynamicRouterRoute.java
new file mode 100644
index 0000000000..875263f0b1
--- /dev/null
+++ b/apache-libraries-2/src/main/java/com/baeldung/dynamicrouter/DynamicRouterRoute.java
@@ -0,0 +1,13 @@
+package com.baeldung.dynamicrouter;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class DynamicRouterRoute extends RouteBuilder {
+
+ @Override
+ public void configure() {
+
+ from("direct:dynamicRouter").dynamicRouter(method(DynamicRouterBean.class, "route"));
+
+ }
+}
diff --git a/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java b/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java
new file mode 100644
index 0000000000..6401fa4be2
--- /dev/null
+++ b/apache-libraries-2/src/test/java/dynamicrouter/DynamicRouterRouteUnitTest.java
@@ -0,0 +1,61 @@
+package dynamicrouter;
+
+import com.baeldung.dynamicrouter.DynamicRouterRoute;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class DynamicRouterRouteUnitTest extends CamelTestSupport {
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() {
+ return new DynamicRouterRoute();
+ }
+
+ @Test
+ void givenDynamicRouter_whenMockEndpointExpectedMessageCountOneAndMockAsMessageBody_thenMessageSentToDynamicRouter() throws InterruptedException {
+
+ MockEndpoint mockDynamicEndpoint = getMockEndpoint("mock:dynamicRouter");
+ mockDynamicEndpoint.expectedMessageCount(1);
+
+ template.send("direct:dynamicRouter", exchange -> exchange.getIn()
+ .setBody("mock"));
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ void givenDynamicRouter_whenMockEndpointExpectedMessageCountOneAndDirectAsMessageBody_thenMessageSentToDynamicRouter() throws InterruptedException {
+
+ MockEndpoint mockDynamicEndpoint = context.getEndpoint("mock:directDynamicRouter", MockEndpoint.class);
+ mockDynamicEndpoint.expectedMessageCount(1);
+
+ template.send("direct:dynamicRouter", exchange -> exchange.getIn()
+ .setBody("direct"));
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ void givenDynamicRouter_whenMockEndpointExpectedMessageCountOneAndSedaAsMessageBody_thenMessageSentToDynamicRouter() throws InterruptedException {
+
+ MockEndpoint mockDynamicEndpoint = context.getEndpoint("mock:sedaDynamicRouter", MockEndpoint.class);
+ mockDynamicEndpoint.expectedMessageCount(1);
+
+ template.send("direct:dynamicRouter", exchange -> exchange.getIn()
+ .setBody("seda"));
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ void givenDynamicRouter_whenMockEndpointExpectedMessageCountOneAndBookAsMessageBody_thenMessageSentToDynamicRouter() throws InterruptedException {
+
+ MockEndpoint mockDynamicEndpoint = getMockEndpoint("mock:fileDynamicRouter");
+ mockDynamicEndpoint.expectedMessageCount(1);
+
+ template.send("direct:dynamicRouter", exchange -> exchange.getIn()
+ .setBody("file"));
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+}
\ No newline at end of file
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 17ffa2562d..88bda5c6d7 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
@@ -1,2 +1,4 @@
## Relevant Articles
- [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item)
+- [Find the Equilibrium Indexes of an Array in Java](https://www.baeldung.com/java-equilibrium-index-array)
+- [Moves Zeros to the End of an Array in Java](https://www.baeldung.com/java-array-sort-move-zeros-end)
diff --git a/core-java-modules/core-java-collections-maps-7/README.md b/core-java-modules/core-java-collections-maps-7/README.md
index 54668e13e5..4cecfdd580 100644
--- a/core-java-modules/core-java-collections-maps-7/README.md
+++ b/core-java-modules/core-java-collections-maps-7/README.md
@@ -7,4 +7,5 @@
- [Limiting the Max Size of a HashMap in Java](https://www.baeldung.com/java-hashmap-size-bound)
- [How to Sort LinkedHashMap by Values in Java](https://www.baeldung.com/java-sort-linkedhashmap-using-values)
- [How to Increment a Map Value in Java](https://www.baeldung.com/java-increment-map-value)
+- [Collect Stream of entrySet() to a LinkedHashMap](https://www.baeldung.com/java-linkedhashmap-entryset-stream)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-6)
diff --git a/core-java-modules/core-java-concurrency-2/README.md b/core-java-modules/core-java-concurrency-2/README.md
index 5d05c900b8..033e476b23 100644
--- a/core-java-modules/core-java-concurrency-2/README.md
+++ b/core-java-modules/core-java-concurrency-2/README.md
@@ -8,3 +8,4 @@
- [How to Check if All Runnables Are Done](https://www.baeldung.com/java-runnables-check-status)
- [Parallelize for Loop in Java](https://www.baeldung.com/java-for-loop-parallel)
- [How to Effectively Unit Test CompletableFuture](https://www.baeldung.com/java-completablefuture-unit-test)
+- [How to Collect All Results and Handle Exceptions With CompletableFuture in a Loop](https://www.baeldung.com/java-completablefuture-collect-results-handle-exceptions)
diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/completablefuture/CombiningCompletableFuturesUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/completablefuture/CombiningCompletableFuturesUnitTest.java
new file mode 100644
index 0000000000..2c157b3ab2
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/completablefuture/CombiningCompletableFuturesUnitTest.java
@@ -0,0 +1,90 @@
+package com.baeldung.concurrent.completablefuture;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class CombiningCompletableFuturesUnitTest {
+
+ private final Logger logger = mock(Logger.class);
+
+ private static Stream clientData() {
+ return Stream.of(
+ Arguments.of(List.of("Good Resource"), 1, 0),
+ Arguments.of(List.of("Bad Resource"), 0, 1),
+ Arguments.of(List.of("Good Resource", "Bad Resource"), 1, 1),
+ Arguments.of(List.of("Good Resource", "Bad Resource", "Good Resource", "Bad Resource", "Good Resource"), 3, 2)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("clientData")
+ public void givenMicroserviceClient_whenMultipleCreateResource_thenCombineResults(List inputs, int successCount, int errorCount) {
+ MicroserviceClient mockMicroservice = mock(MicroserviceClient.class);
+ // Return an identifier of 123 on "Good Resource"
+ when(mockMicroservice.createResource("Good Resource"))
+ .thenReturn(CompletableFuture.completedFuture(123L));
+ // Throw an exception on "Bad Resource"
+ when(mockMicroservice.createResource("Bad Resource"))
+ .thenReturn(CompletableFuture.failedFuture(new IllegalArgumentException("Bad Resource")));
+
+ // Given a list of CompletableFutures from our microservice calls...
+ List> clientCalls = new ArrayList<>();
+ for (String resource : inputs) {
+ clientCalls.add(mockMicroservice.createResource(resource));
+ }
+
+ // When all CompletableFutures are completed (exceptionally or otherwise)...
+ Map> resultsByValidity = clientCalls.stream()
+ .map(this::handleFuture)
+ .collect(Collectors.partitioningBy(resourceId -> resourceId != -1L));
+
+ // Then the returned resource identifiers should match what is expected...
+ List validResults = resultsByValidity.getOrDefault(true, List.of());
+ assertThat(validResults.size()).isEqualTo(successCount);
+
+ // And the logger mock should be called once for each exception with the expected error message
+ List invalidResults = resultsByValidity.getOrDefault(false, List.of());
+ assertThat(invalidResults.size()).isEqualTo(errorCount);
+ verify(logger, times(errorCount))
+ .error(eq("Encountered error: java.lang.IllegalArgumentException: Bad Resource"));
+ }
+
+ /**
+ * Completes the given CompletableFuture, handling any exceptions that are thrown.
+ * @param future the CompletableFuture to complete.
+ * @return the resource identifier (-1 if the request failed).
+ */
+ private Long handleFuture(CompletableFuture future) {
+ return future
+ .exceptionally(this::handleError)
+ .join();
+ }
+
+ private Long handleError(Throwable throwable) {
+ logger.error("Encountered error: " + throwable);
+ return -1L;
+ }
+
+ interface MicroserviceClient {
+ CompletableFuture createResource(String resourceName);
+ }
+
+ interface Logger {
+ void error(String message);
+ }
+}
diff --git a/core-java-modules/core-java-date-operations-4/README.md b/core-java-modules/core-java-date-operations-4/README.md
index 6f8bc6c4b8..0e9bc710c8 100644
--- a/core-java-modules/core-java-date-operations-4/README.md
+++ b/core-java-modules/core-java-date-operations-4/README.md
@@ -4,3 +4,4 @@ This module contains articles about date operations in Java.
### Relevant Articles:
- [Calculate Number of Weekdays Between Two Dates in Java](https://www.baeldung.com/java-count-weekdays-between-two-dates)
- [Convert Long to Date in Java](https://www.baeldung.com/java-long-date-conversion)
+- [Convert Date to Unix Timestamp in Java](https://www.baeldung.com/java-convert-date-unix-timestamp)
diff --git a/core-java-modules/core-java-datetime-conversion-2/pom.xml b/core-java-modules/core-java-datetime-conversion-2/pom.xml
index 079df86a72..13849bc563 100644
--- a/core-java-modules/core-java-datetime-conversion-2/pom.xml
+++ b/core-java-modules/core-java-datetime-conversion-2/pom.xml
@@ -4,7 +4,6 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
core-java-datetime-conversion-2
- ${project.parent.version}
core-java-datetime-conversion-2
jar
diff --git a/core-java-modules/core-java-datetime-conversion/pom.xml b/core-java-modules/core-java-datetime-conversion/pom.xml
index 17b5ff62ab..52ad29db5c 100644
--- a/core-java-modules/core-java-datetime-conversion/pom.xml
+++ b/core-java-modules/core-java-datetime-conversion/pom.xml
@@ -4,7 +4,6 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
core-java-datetime-conversion
- ${project.parent.version}
core-java-datetime-conversion
jar
diff --git a/core-java-modules/core-java-lang-math-3/src/main/java/com/baeldung/math/rodcutting/RodCuttingProblem.java b/core-java-modules/core-java-lang-math-3/src/main/java/com/baeldung/math/rodcutting/RodCuttingProblem.java
new file mode 100644
index 0000000000..ef10227edd
--- /dev/null
+++ b/core-java-modules/core-java-lang-math-3/src/main/java/com/baeldung/math/rodcutting/RodCuttingProblem.java
@@ -0,0 +1,72 @@
+package com.baeldung.math.rodcutting;
+
+import java.util.Arrays;
+
+public class RodCuttingProblem {
+ static int maxRevenueG;
+ public static int usingRecursion(int[] prices, int n) {
+ if (n <= 0) {
+ return 0;
+ }
+ int maxRevenue = Integer.MIN_VALUE;
+
+ for (int i = 1; i <= n; i++) {
+ maxRevenue = Math.max(maxRevenue, prices[i - 1] + usingRecursion(prices, n - i));
+ }
+ return maxRevenue;
+ }
+
+ public static int usingMemoizedRecursion(int[] prices, int n) {
+ int[] memo = new int[n + 1];
+ Arrays.fill(memo, -1);
+
+ return memoizedHelper(prices, n, memo);
+ }
+
+ private static int memoizedHelper(int[] prices, int n, int[] memo) {
+ if (n <= 0) {
+ return 0;
+ }
+
+ if (memo[n] != -1) {
+ return memo[n];
+ }
+
+ int maxRevenue = Integer.MIN_VALUE;
+
+ for (int i = 1; i <= n; i++) {
+ maxRevenue = Math.max(maxRevenue, prices[i - 1] + memoizedHelper(prices, n - i, memo));
+ }
+
+ memo[n] = maxRevenue;
+ return maxRevenue;
+ }
+
+ public static int usingDynamicProgramming(int[] prices, int n) {
+ int[] dp = new int[n + 1];
+ for (int i = 1; i <= n; i++) {
+ int maxRevenue = Integer.MIN_VALUE;
+
+ for (int j = 1; j <= i; j++) {
+ maxRevenue = Math.max(maxRevenue, prices[j - 1] + dp[i - j]);
+ }
+ dp[i] = maxRevenue;
+ }
+ return dp[n];
+ }
+
+ public static int usingUnboundedKnapsack(int[] prices, int n) {
+ int[] dp = new int[n + 1];
+
+ for (int i = 1; i <= n; i++) {
+ for (int j = 0; j < prices.length; j++) {
+ if (j + 1 <= i) {
+ dp[i] = Math.max(dp[i], dp[i - (j + 1)] + prices[j]);
+ }
+ }
+ }
+
+ return dp[n];
+ }
+
+}
diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/math/rodcutting/RodCuttingProblemUnitTest.java b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/math/rodcutting/RodCuttingProblemUnitTest.java
new file mode 100644
index 0000000000..6ad16d5a5f
--- /dev/null
+++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/math/rodcutting/RodCuttingProblemUnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.math.rodcutting;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class RodCuttingProblemUnitTest {
+ @Test
+ void givenARod_whenUsingRecursion_thenFindMaxRevenue() {
+ int[] prices = {1, 5, 8, 9};
+ int rodLength = 4;
+ int maxRevenue = RodCuttingProblem.usingRecursion(prices, rodLength);
+ assertEquals(10, maxRevenue);
+ }
+
+ @Test
+ void givenARod_whenUsingMemoizedRecursion_thenFindMaxRevenue() {
+ int[] prices = {1, 5, 8, 9};
+ int rodLength = 4;
+ int maxRevenue = RodCuttingProblem.usingMemoizedRecursion(prices, rodLength);
+ assertEquals(10, maxRevenue);
+ }
+
+ @Test
+ void givenARod_whenUsingDynamicProgramming_thenFindMaxRevenue() {
+ int[] prices = {1, 5, 8, 9};
+ int rodLength = 4;
+ int maxRevenue = RodCuttingProblem.usingDynamicProgramming(prices, rodLength);
+ assertEquals(10, maxRevenue);
+ }
+
+ @Test
+ void givenARod_whenUsingGreedy_thenFindMaxRevenue() {
+ int[] prices = {1, 5, 8, 9};
+ int rodLength = 4;
+ int maxRevenue = RodCuttingProblem.usingUnboundedKnapsack(prices, rodLength);
+ assertEquals(10, maxRevenue);
+ }
+}
diff --git a/core-java-modules/core-java-lang-oop-patterns/README.md b/core-java-modules/core-java-lang-oop-patterns/README.md
index 4e171483e6..7ea979435e 100644
--- a/core-java-modules/core-java-lang-oop-patterns/README.md
+++ b/core-java-modules/core-java-lang-oop-patterns/README.md
@@ -11,3 +11,4 @@ This module contains articles about Object-oriented programming (OOP) patterns i
- [Should We Create an Interface for Only One Implementation?](https://www.baeldung.com/java-interface-single-implementation)
- [How to Deep Copy an ArrayList in Java](https://www.baeldung.com/java-arraylist-deep-copy)
- [Stateless Object in Java](https://www.baeldung.com/java-stateless-object)
+- [Mutable vs. Immutable Objects in Java](https://www.baeldung.com/java-mutable-vs-immutable-objects)
diff --git a/core-java-modules/core-java-lang-operators-2/README.md b/core-java-modules/core-java-lang-operators-2/README.md
index 4b93f8d192..52b05e95a4 100644
--- a/core-java-modules/core-java-lang-operators-2/README.md
+++ b/core-java-modules/core-java-lang-operators-2/README.md
@@ -11,3 +11,4 @@ This module contains articles about Java operators
- [Alternatives for instanceof Operator in Java](https://www.baeldung.com/java-instanceof-alternatives)
- [What Does “––>” Mean in Java?](https://www.baeldung.com/java-minus-minus-greaterthan)
- [All the Ways Java Uses the Colon Character](https://www.baeldung.com/java-colon)
+- [Convert Infix to Postfix Expressions in Java](https://www.baeldung.com/java-convert-infix-to-postfix-expressions)
diff --git a/core-java-modules/core-java-networking-4/README.md b/core-java-modules/core-java-networking-4/README.md
index 9b7e1b0f55..e62cab7c6e 100644
--- a/core-java-modules/core-java-networking-4/README.md
+++ b/core-java-modules/core-java-networking-4/README.md
@@ -6,3 +6,5 @@
- [URL Query Manipulation in Java](https://www.baeldung.com/java-url-query-manipulation)
- [Understanding the java.net.SocketException Broken Pipe Error](https://www.baeldung.com/java-socketexception-broken-pipe-error)
- [Normalize a URL in Java](https://www.baeldung.com/java-url-normalization)
+- [Translating Space Characters in URLEncoder](https://www.baeldung.com/java-urlencoder-translate-space-characters)
+- [Creating a Custom URL Connection](https://www.baeldung.com/java-custom-url-connection)
diff --git a/core-java-modules/core-java-serialization/pom.xml b/core-java-modules/core-java-serialization/pom.xml
index aecc66060d..5989dbf870 100644
--- a/core-java-modules/core-java-serialization/pom.xml
+++ b/core-java-modules/core-java-serialization/pom.xml
@@ -31,11 +31,6 @@
jackson-databind
${jackson.version}
-
- org.springframework
- spring-core
- ${spring.core.version}
-
org.springframework
spring-core
diff --git a/core-java-modules/core-java-streams-6/src/test/java/com/baeldung/streams/range/StreamRangeUnitTest.java b/core-java-modules/core-java-streams-6/src/test/java/com/baeldung/streams/range/StreamRangeUnitTest.java
new file mode 100644
index 0000000000..2d0a2e8c12
--- /dev/null
+++ b/core-java-modules/core-java-streams-6/src/test/java/com/baeldung/streams/range/StreamRangeUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.streams.range;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class StreamRangeUnitTest {
+
+ @Test
+ public void whenRangeStreamUsingLimitSkip_thenPrintsRange() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ List expectedRange = Arrays.asList(3, 4, 5, 6, 7);
+
+ List range = numbers.stream()
+ .skip(2)
+ .limit(5)
+ .collect(Collectors.toList());
+
+ assertEquals(expectedRange, range);
+ }
+
+ @Test
+ public void whenRangeStreamUsingCollectingAndThen_thenPrintsRange() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ List expectedRange = Arrays.asList(3, 4, 5, 6, 7);
+
+ List range = numbers.stream()
+ .filter(n -> n >= 3 && n <= 7)
+ .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
+
+ assertEquals(expectedRange, range);
+ }
+}
diff --git a/core-java-modules/core-java-string-operations-7/README.md b/core-java-modules/core-java-string-operations-7/README.md
index a358c8fa57..7264c3d945 100644
--- a/core-java-modules/core-java-string-operations-7/README.md
+++ b/core-java-modules/core-java-string-operations-7/README.md
@@ -15,3 +15,4 @@
- [Simple Morse Code Translation in Java](https://www.baeldung.com/java-morse-code-english-translate)
- [How to Determine if a String Contains Invalid Encoded Characters](https://www.baeldung.com/java-check-string-contains-invalid-encoded-characters)
- [Regular Expression for Password Validation in Java](https://www.baeldung.com/java-regex-password-validation)
+- [Mask an Email Address and Phone Number in Java](https://www.baeldung.com/java-mask-email-address-phone-number)
diff --git a/core-java-modules/core-java-string-operations-8/README.md b/core-java-modules/core-java-string-operations-8/README.md
index 2dce44d217..7e961ed041 100644
--- a/core-java-modules/core-java-string-operations-8/README.md
+++ b/core-java-modules/core-java-string-operations-8/README.md
@@ -1,2 +1,2 @@
-
-### Relevant Articles:
+### Relevant Articles:
+- [Count Uppercase and Lowercase Letters in a String](https://www.baeldung.com/java-string-count-letters-uppercase-lowercase)
diff --git a/core-java-modules/core-java-string-operations-8/pom.xml b/core-java-modules/core-java-string-operations-8/pom.xml
index 2495abccf8..a2f97a93d9 100644
--- a/core-java-modules/core-java-string-operations-8/pom.xml
+++ b/core-java-modules/core-java-string-operations-8/pom.xml
@@ -1,72 +1,34 @@
-
-
- 4.0.0
- core-java-string-operations-8
- core-java-string-operations-8
- jar
-
-
- com.baeldung.core-java-modules
- core-java-modules
- 0.0.1-SNAPSHOT
-
-
-
-
- org.apache.commons
- commons-lang3
- ${apache.commons.lang3.version}
-
-
- org.apache.commons
- commons-text
- ${commons-text.version}
-
-
- org.liquibase
- liquibase-core
- 4.9.1
- test
-
-
- org.junit.jupiter
- junit-jupiter
- 5.8.1
- test
-
-
- org.liquibase
- liquibase-core
- 4.9.1
- test
-
-
- junit
- junit
- 4.13.2
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- ${maven.compiler.source}
- ${maven.compiler.target}
-
-
-
-
-
-
- 11
- 11
- 3.13.0
- 1.10.0
-
-
-
\ No newline at end of file
+
+
+ 4.0.0
+ core-java-string-operations-8
+ core-java-string-operations-8
+ jar
+
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+
+
+
+ 11
+ 11
+
+
+
diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/checkifstringisbased64/CheckIfStringIsBased64UnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/checkifstringisbased64/CheckIfStringIsBased64UnitTest.java
new file mode 100644
index 0000000000..fdb543b3f5
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/checkifstringisbased64/CheckIfStringIsBased64UnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.checkifstringisbased64;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Base64;
+import java.util.regex.Pattern;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class CheckIfStringIsBased64UnitTest {
+
+ @Test
+ public void givenBase64EncodedString_whenDecoding_thenNoException() {
+ try {
+ Base64.getDecoder().decode("SGVsbG8gd29ybGQ=");
+ assertTrue(true);
+ } catch (IllegalArgumentException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void givenNonBase64String_whenDecoding_thenCatchException() {
+ try {
+ Base64.getDecoder().decode("Hello world!");
+ fail("Expected IllegalArgumentException was not thrown");
+ } catch (IllegalArgumentException e) {
+ assertTrue(true);
+ }
+ }
+
+ @Test
+ public void givenString_whenOperatingRegex_thenCheckIfItIsBase64Encoded() {
+ Pattern BASE64_PATTERN = Pattern.compile(
+ "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
+ );
+
+ assertTrue(BASE64_PATTERN.matcher("SGVsbG8gd29ybGQ=").matches());
+ }
+}
diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/countupperandlowercasechars/CountUpperAndLowercaseCharsUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/countupperandlowercasechars/CountUpperAndLowercaseCharsUnitTest.java
new file mode 100644
index 0000000000..64e8b7ebbd
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/countupperandlowercasechars/CountUpperAndLowercaseCharsUnitTest.java
@@ -0,0 +1,90 @@
+package com.baeldung.countupperandlowercasechars;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class CountUpperAndLowercaseCharsUnitTest {
+ private static final String MY_STRING = "Hi, Welcome to Baeldung! Let's count letters!";
+
+ @Test
+ void whenUsingCountByCharacterRange_thenGetExpectedResult() {
+ LetterCount result = LetterCount.countByCharacterRange(MY_STRING);
+ assertEquals(4, result.getUppercaseCount());
+ assertEquals(31, result.getLowercaseCount());
+ }
+
+ @Test
+ void whenUsingCountByCharacterIsLowerOrUpperCase_thenGetExpectedResult() {
+ LetterCount result = LetterCount.countByCharacterIsUpperLower(MY_STRING);
+ assertEquals(4, result.getUppercaseCount());
+ assertEquals(31, result.getLowercaseCount());
+ }
+
+ @Test
+ void whenUsingCountByStreamApi_thenGetExpectedResult() {
+ LetterCount result = LetterCount.countByStreamAPI(MY_STRING);
+ assertEquals(4, result.getUppercaseCount());
+ assertEquals(31, result.getLowercaseCount());
+ }
+
+ @Test
+ void whenUsingIsUpperCaseAndIsLowerCase_thenUnicodeCharactersCanBeChecked() {
+ assertTrue(Character.isLowerCase('ä'));
+ assertTrue(Character.isUpperCase('Ä'));
+ }
+}
+
+class LetterCount {
+ private int uppercaseCount;
+ private int lowercaseCount;
+
+ private LetterCount(int uppercaseCount, int lowercaseCount) {
+ this.uppercaseCount = uppercaseCount;
+ this.lowercaseCount = lowercaseCount;
+ }
+
+ public static LetterCount countByCharacterRange(String input) {
+ int upperCount = 0;
+ int lowerCount = 0;
+ for (char c : input.toCharArray()) {
+ if (c >= 'A' && c <= 'Z') {
+ upperCount++;
+ }
+ if (c >= 'a' && c <= 'z') {
+ lowerCount++;
+ }
+ }
+ return new LetterCount(upperCount, lowerCount);
+ }
+
+ public static LetterCount countByCharacterIsUpperLower(String input) {
+ int upperCount = 0;
+ int lowerCount = 0;
+ for (char c : input.toCharArray()) {
+ if (Character.isUpperCase(c)) {
+ upperCount++;
+ }
+ if (Character.isLowerCase(c)) {
+ lowerCount++;
+ }
+ }
+ return new LetterCount(upperCount, lowerCount);
+ }
+
+ public static LetterCount countByStreamAPI(String input) {
+ return new LetterCount(
+ (int) input.chars().filter(Character::isUpperCase).count(),
+ (int) input.chars().filter(Character::isLowerCase).count()
+ );
+ }
+
+ public int getUppercaseCount() {
+ return uppercaseCount;
+ }
+
+ public int getLowercaseCount() {
+ return lowercaseCount;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/findlargestnuminstring/FindLargestNumInStringUnitTest.java b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/findlargestnuminstring/FindLargestNumInStringUnitTest.java
new file mode 100644
index 0000000000..634786704d
--- /dev/null
+++ b/core-java-modules/core-java-string-operations-8/src/test/java/com/baeldung/findlargestnuminstring/FindLargestNumInStringUnitTest.java
@@ -0,0 +1,59 @@
+package com.baeldung.findlargestnuminstring;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class FindLargestNumInStringUnitTest {
+ String inputString = "The numbers are 10, 20, and 5";
+ int expectedLargestNumber = 20;
+
+ @Test
+ public void givenInputString_whenUsingBasicApproach_thenFindingLargestNumber() {
+ String[] numbers = inputString.split("[^0-9]+");
+
+ int largestNumber = Integer.MIN_VALUE;
+ for (String number : numbers) {
+ if (!number.isEmpty()) {
+ int currentNumber = Integer.parseInt(number);
+ if (currentNumber > largestNumber) {
+ largestNumber = currentNumber;
+ }
+ }
+ }
+ assertEquals(expectedLargestNumber, largestNumber);
+
+ }
+
+ @Test
+ public void givenInputString_whenUsingRegularExpression_thenFindingLargestNumber() {
+ Pattern pattern = Pattern.compile("\\d+");
+ Matcher matcher = pattern.matcher(inputString);
+
+ int largestNumber = Integer.MIN_VALUE;
+ while (matcher.find()) {
+ int currentNumber = Integer.parseInt(matcher.group());
+ if (currentNumber > largestNumber) {
+ largestNumber = currentNumber;
+ }
+ }
+ assertEquals(expectedLargestNumber, largestNumber);
+
+ }
+
+ @Test
+ public void givenInputString_whenUsingStreamAndLambdaExpression_thenFindingLargestNumber() {
+ int largestNumber = Arrays.stream(inputString.split("[^0-9]+"))
+ .filter(s -> !s.isEmpty())
+ .mapToInt(Integer::parseInt)
+ .max()
+ .orElse(Integer.MIN_VALUE);
+
+ assertEquals(expectedLargestNumber, largestNumber);
+
+ }
+}
\ No newline at end of file
diff --git a/jackson-modules/jackson-jr/pom.xml b/jackson-modules/jackson-jr/pom.xml
index 7f806f0d89..868c3ee17f 100644
--- a/jackson-modules/jackson-jr/pom.xml
+++ b/jackson-modules/jackson-jr/pom.xml
@@ -18,18 +18,17 @@
com.fasterxml.jackson.jr
jackson-jr-all
- 2.15.2
+ ${jackson.version}
com.fasterxml.jackson.jr
jackson-jr-annotation-support
- 2.15.2
+ ${jackson.version}
org.projectlombok
lombok
- RELEASE
- compile
+ ${lombok.version}
@@ -44,4 +43,8 @@
+
+ 2.16.0
+
+
\ No newline at end of file
diff --git a/json-modules/json-2/pom.xml b/json-modules/json-2/pom.xml
index b9a75e8aff..2449d0ad62 100644
--- a/json-modules/json-2/pom.xml
+++ b/json-modules/json-2/pom.xml
@@ -112,12 +112,6 @@
commons-io
2.11.0
-
- org.junit.jupiter
- junit-jupiter
- RELEASE
- test
-
javax.annotation
javax.annotation-api
diff --git a/json-modules/json-conversion/README.md b/json-modules/json-conversion/README.md
index a1851d9b7a..49c150264c 100644
--- a/json-modules/json-conversion/README.md
+++ b/json-modules/json-conversion/README.md
@@ -6,3 +6,4 @@ This module contains articles about JSON Conversions
- [Convert JSON Array to Java List](https://www.baeldung.com/java-convert-json-array-to-list)
- [Reading JSON Documents as Maps and Comparing Them](https://www.baeldung.com/java-json-maps-comparison)
- [Convert Byte Array to JSON and Vice Versa in Java](https://www.baeldung.com/java-json-byte-array-conversion)
+- [Preventing Gson from Expressing Integers as Floats](https://www.baeldung.com/java-gson-prevent-expressing-integers-as-floats)
diff --git a/json-modules/json-conversion/src/main/java/com/baeldung/preventexpressingintasfloat/Main.java b/json-modules/json-conversion/src/main/java/com/baeldung/preventexpressingintasfloat/Main.java
deleted file mode 100644
index c0f14fa73d..0000000000
--- a/json-modules/json-conversion/src/main/java/com/baeldung/preventexpressingintasfloat/Main.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.baeldung.preventexpressingintasfloat;
-
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Hashtable;
-
-public class Main {
- public static String draft = "[{\"id\":4077395,\"field_id\":242566,\"body\":\"\"}, " +
- "{\"id\":4077398,\"field_id\":242569,\"body\":[[273019,0],[273020,1],[273021,0]]}, " +
- "{\"id\":4077399,\"field_id\":242570,\"body\":[[273022,0],[273023,1],[273024,0]]}]";
-
- public static void main(String[] args) {
- ArrayList> responses;
- Type ResponseList = new TypeToken>>() {
- }.getType();
- responses = new Gson().fromJson(draft, ResponseList);
- System.out.println(responses);
- }
-}
\ No newline at end of file
diff --git a/json-modules/json-conversion/src/test/java/com/baeldung/preventexpressingintasfloat/PreventExpressingIntAsFloatUnitTest.java b/json-modules/json-conversion/src/test/java/com/baeldung/preventexpressingintasfloat/PreventExpressingIntAsFloatUnitTest.java
index 6ada093ab3..558ee42e90 100644
--- a/json-modules/json-conversion/src/test/java/com/baeldung/preventexpressingintasfloat/PreventExpressingIntAsFloatUnitTest.java
+++ b/json-modules/json-conversion/src/test/java/com/baeldung/preventexpressingintasfloat/PreventExpressingIntAsFloatUnitTest.java
@@ -14,17 +14,24 @@ public class PreventExpressingIntAsFloatUnitTest {
public String jsonString = "[{\"id\":4077395,\"field_id\":242566,\"body\":\"\"}, " +
"{\"id\":4077398,\"field_id\":242569,\"body\":[[273019,0],[273020,1],[273021,0]]}, " +
"{\"id\":4077399,\"field_id\":242570,\"body\":[[273022,0],[273023,1],[273024,0]]}]";
-
public String expectedOutput = "[{body=, field_id=242566, id=4077395}, " +
"{body=[[273019, 0], [273020, 1], [273021, 0]], field_id=242569, id=4077398}, " +
"{body=[[273022, 0], [273023, 1], [273024, 0]], field_id=242570, id=4077399}]";
+ public String defaultOutput = "[{body=, field_id=242566.0, id=4077395.0}, " +
+ "{body=[[273019.0, 0.0], [273020.0, 1.0], [273021.0, 0.0]], field_id=242569.0, id=4077398.0}, " +
+ "{body=[[273022.0, 0.0], [273023.0, 1.0], [273024.0, 0.0]], field_id=242570.0, id=4077399.0}]";
@Test
- public void givenJsonString_whenUsingsetObjectToNumberStrategyMethod_thenValidateOutput() {
- Gson gson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create();
- ArrayList> responses = gson.fromJson(jsonString, new TypeToken>>() {
+ public void givenJsonString_whenUsingSetObjectToNumberStrategyMethod_thenValidateOutput() {
+ Gson defaultGson = new Gson();
+ ArrayList> defaultResponses = defaultGson.fromJson(jsonString, new TypeToken>>() {
}.getType());
- assertEquals(expectedOutput, responses.toString());
+ Gson customGson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create();
+ ArrayList> customResponses = customGson.fromJson(jsonString, new TypeToken>>() {
+ }.getType());
+
+ assertEquals(defaultOutput, defaultResponses.toString());
+ assertEquals(expectedOutput, customResponses.toString());
}
}
diff --git a/lightrun/lightrun-tasks-service/pom.xml b/lightrun/lightrun-tasks-service/pom.xml
index 773c81a9d5..c27ef103b9 100644
--- a/lightrun/lightrun-tasks-service/pom.xml
+++ b/lightrun/lightrun-tasks-service/pom.xml
@@ -48,6 +48,7 @@
org.apache.activemq
artemis-jms-server
+ ${activemq.version}
org.springframework.boot
@@ -65,4 +66,8 @@
+
+ 2.32.0
+
+
\ No newline at end of file
diff --git a/maven-modules/maven-simple/README.md b/maven-modules/maven-simple/README.md
index 783d58a3a0..150eefa3a8 100644
--- a/maven-modules/maven-simple/README.md
+++ b/maven-modules/maven-simple/README.md
@@ -10,3 +10,4 @@ Since this is a module tied to an e-book, it should **not** be moved or used to
### Relevant Articles
- [Apache Maven Tutorial](https://www.baeldung.com/maven)
+- [Run Maven From Java Code](https://www.baeldung.com/java-maven-run-program)
diff --git a/metrics/pom.xml b/metrics/pom.xml
index 40a1d95d0c..a8f5e113e8 100644
--- a/metrics/pom.xml
+++ b/metrics/pom.xml
@@ -88,7 +88,7 @@
1.11.0
3.1.0
1.2.0
- 1.5.4
+ 1.7.7
\ No newline at end of file
diff --git a/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasManualTest.java b/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasManualTest.java
index 8341befb83..7521aabdbb 100644
--- a/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasManualTest.java
+++ b/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasManualTest.java
@@ -282,7 +282,7 @@ public class MicrometerAtlasManualTest {
Map expectedMicrometer = new TreeMap<>();
expectedMicrometer.put(2.5E7,1D);
expectedMicrometer.put(3.0E8,1D);
- expectedMicrometer.put(6.0E8,4D);
+ expectedMicrometer.put(6.0E8,1D);
Map actualMicrometer = new TreeMap<>();
HistogramSnapshot snapshot = timer.takeSnapshot();
diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java
index 2f908531f6..c2c1f52365 100644
--- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java
+++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java
@@ -8,6 +8,7 @@ import com.netflix.servo.monitor.Monitors;
import com.netflix.servo.tag.BasicTag;
import com.netflix.servo.tag.BasicTagList;
import com.netflix.servo.tag.TagList;
+import org.junit.Before;
import org.junit.Test;
import java.util.Iterator;
@@ -24,6 +25,12 @@ import static org.junit.Assert.assertTrue;
public class MetricAnnotationManualTest extends MetricTestBase {
+ static {
+ System.setProperty(
+ "com.netflix.servo.DefaultMonitorRegistry.registryClass",
+ "com.netflix.servo.jmx.JmxMonitorRegistry");
+ }
+
@Monitor(name = "integerCounter", type = DataSourceType.COUNTER, description = "Total number of update operations.")
private final AtomicInteger updateCount = new AtomicInteger(0);
diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java
index 3bb421b3ef..af60623841 100644
--- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java
+++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java
@@ -24,6 +24,12 @@ import static org.junit.Assert.assertThat;
public class MetricObserverManualTest extends MetricTestBase {
+ static {
+ System.setProperty(
+ "com.netflix.servo.DefaultMonitorRegistry.registryClass",
+ "com.netflix.servo.jmx.JmxMonitorRegistry");
+ }
+
@Test
public void givenMetrics_whenRegister_thenMonitored() throws InterruptedException {
Gauge gauge = new BasicGauge<>(MonitorConfig
diff --git a/parent-boot-3/pom.xml b/parent-boot-3/pom.xml
index d4ca41291d..f45e108f02 100644
--- a/parent-boot-3/pom.xml
+++ b/parent-boot-3/pom.xml
@@ -229,8 +229,8 @@
3.3.0
3.3.0
2.22.2
- 3.1.5
- 5.8.2
+ 3.2.2
+ 5.10.2
0.9.17
1.4.4
2.0.3
diff --git a/persistence-modules/core-java-persistence-3/README.md b/persistence-modules/core-java-persistence-3/README.md
index 6ca158560b..c3cc8d0713 100644
--- a/persistence-modules/core-java-persistence-3/README.md
+++ b/persistence-modules/core-java-persistence-3/README.md
@@ -1,2 +1,3 @@
## Relevant Articles
- [Convert ResultSet Into Map](https://www.baeldung.com/java-resultset-map)
+- [Pagination With JDBC](https://www.baeldung.com/java-jdbc-pagination)
diff --git a/persistence-modules/hibernate-annotations/README.md b/persistence-modules/hibernate-annotations/README.md
index dad29edc32..663c39ea33 100644
--- a/persistence-modules/hibernate-annotations/README.md
+++ b/persistence-modules/hibernate-annotations/README.md
@@ -12,3 +12,4 @@ This module contains articles about Annotations used in Hibernate.
- [@Immutable in Hibernate](https://www.baeldung.com/hibernate-immutable)
- [Hibernate @CreationTimestamp and @UpdateTimestamp](https://www.baeldung.com/hibernate-creationtimestamp-updatetimestamp)
- [Difference Between @JoinColumn and @PrimaryKeyJoinColumn in JPA](https://www.baeldung.com/java-jpa-join-vs-primarykeyjoin)
+- [A Guide to the @SoftDelete Annotation in Hibernate](https://www.baeldung.com/java-hibernate-softdelete-annotation)
diff --git a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CodeGenerationIntegrationTest.java b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CodeGenerationIntegrationTest.java
index 3ca0919eaa..72b6ab710a 100644
--- a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CodeGenerationIntegrationTest.java
+++ b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CodeGenerationIntegrationTest.java
@@ -34,7 +34,7 @@ public class CodeGenerationIntegrationTest {
Connection conn = DriverManager.getConnection("jdbc:h2:mem:tes;INIT=CREATE SCHEMA IF NOT EXISTS \"public\"");
context = DSL.using(conn, SQLDialect.H2);
- context.createTable(Author.AUTHOR)
+ context.createTableIfNotExists(Author.AUTHOR)
.columns(
Author.AUTHOR.ID,
Author.AUTHOR.FIRST_NAME,
@@ -42,7 +42,7 @@ public class CodeGenerationIntegrationTest {
Author.AUTHOR.AGE
)
.execute();
- context.createTable(Article.ARTICLE)
+ context.createTableIfNotExists(Article.ARTICLE)
.columns(
Article.ARTICLE.ID,
Article.ARTICLE.TITLE,
diff --git a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudIntegrationTest.java b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudIntegrationTest.java
index 0d8df27ccc..74c75dfeea 100644
--- a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudIntegrationTest.java
+++ b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudIntegrationTest.java
@@ -37,7 +37,7 @@ public class CrudIntegrationTest {
Connection conn = DriverManager.getConnection("jdbc:h2:mem:tes;INIT=CREATE SCHEMA IF NOT EXISTS \"public\"");
context = DSL.using(conn, SQLDialect.H2);
- context.createTable(Author.AUTHOR)
+ context.createTableIfNotExists(Author.AUTHOR)
.columns(
Author.AUTHOR.ID,
Author.AUTHOR.FIRST_NAME,
@@ -45,7 +45,7 @@ public class CrudIntegrationTest {
Author.AUTHOR.AGE
)
.execute();
- context.createTable(Article.ARTICLE)
+ context.createTableIfNotExists(Article.ARTICLE)
.columns(
Article.ARTICLE.ID,
Article.ARTICLE.TITLE,
diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/Account.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/Account.java
new file mode 100644
index 0000000000..e70e699303
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/Account.java
@@ -0,0 +1,69 @@
+package com.baeldung.findby;
+
+import jakarta.persistence.*;
+
+import java.sql.Timestamp;
+
+@Entity
+@Table(name = "ACCOUNTS")
+public class Account {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accounts_seq")
+ @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1)
+ @Column(name = "user_id")
+ private int userId;
+ private String username;
+ private String password;
+ private String email;
+ private Timestamp createdOn;
+ private Timestamp lastLogin;
+
+ @OneToOne
+ @JoinColumn(name = "permissions_id")
+ private Permission permission;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public Timestamp getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(Timestamp createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public void setLastLogin(Timestamp lastLogin) {
+ this.lastLogin = lastLogin;
+ }
+
+ public Permission getPermission() {
+ return permission;
+ }
+
+ public void setPermission(Permission permission) {
+ this.permission = permission;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ @Override
+ public String toString() {
+ return "Account{" + "userId=" + userId + ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + ", createdOn=" + createdOn + ", lastLogin=" + lastLogin + ", permission=" + permission + '}';
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/AccountApplication.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/AccountApplication.java
new file mode 100644
index 0000000000..45d0560529
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/AccountApplication.java
@@ -0,0 +1,11 @@
+package com.baeldung.findby;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class AccountApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(AccountApplication.class, args);
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/AccountRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/AccountRepository.java
new file mode 100644
index 0000000000..b6504bff3c
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/AccountRepository.java
@@ -0,0 +1,18 @@
+package com.baeldung.findby;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface AccountRepository extends JpaRepository {
+
+ Account findByEmail(String email);
+
+ Account findByUsernameAndEmail(String username, String email);
+
+ Account findByUsernameOrEmail(String username, String email);
+
+ List findByUsernameInOrEmailIn(List usernames, List emails);
+}
diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/Permission.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/Permission.java
new file mode 100644
index 0000000000..06c9d3d213
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/Permission.java
@@ -0,0 +1,24 @@
+package com.baeldung.findby;
+
+import jakarta.persistence.*;
+
+@Entity
+@Table(name = "PERMISSIONS")
+public class Permission {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "permissions_id_sq")
+ @SequenceGenerator(name = "permissions_id_sq", sequenceName = "permissions_id_sq", allocationSize = 1)
+ private int id;
+
+ private String type;
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ @Override
+ public String toString() {
+ return "Permission{" + "id=" + id + ", type='" + type + '\'' + '}';
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/PermissionRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/PermissionRepository.java
new file mode 100644
index 0000000000..294b81bd15
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/findby/PermissionRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.findby;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PermissionRepository extends JpaRepository {
+ Permission findByType(String type);
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/findby/AccountRepositoryUnitTest.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/findby/AccountRepositoryUnitTest.java
new file mode 100644
index 0000000000..ce0a7d8f3e
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/findby/AccountRepositoryUnitTest.java
@@ -0,0 +1,105 @@
+package com.baeldung.boot.findby;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import com.baeldung.findby.Account;
+import com.baeldung.findby.AccountApplication;
+import com.baeldung.findby.AccountRepository;
+import com.baeldung.findby.Permission;
+import com.baeldung.findby.PermissionRepository;
+
+@SpringBootTest(classes = AccountApplication.class)
+public class AccountRepositoryUnitTest {
+
+ @Autowired
+ private AccountRepository accountRepository;
+
+ @Autowired
+ private PermissionRepository permissionRepository;
+
+ @BeforeEach
+ void setup() {
+ saveAccount();
+ }
+
+ @AfterEach
+ void tearDown() {
+ accountRepository.deleteAll();
+ permissionRepository.deleteAll();
+ }
+
+ @Test
+ void givenAccountInDb_whenPerformFindByEmail_thenReturnsAccount() {
+ String email = "test@test.com";
+ Account account = accountRepository.findByEmail(email);
+ assertThat(account.getEmail()).isEqualTo(email);
+ }
+
+ @Test
+ void givenAccountInDb_whenPerformFindByUsernameAndEmail_thenReturnsAccount() {
+ String email = "test@test.com";
+ String username = "user_admin";
+ Account account = accountRepository.findByUsernameAndEmail(username, email);
+ assertThat(account.getUsername()).isEqualTo(username);
+ assertThat(account.getEmail()).isEqualTo(email);
+ }
+
+ @Test
+ void givenAccountInDb_whenPerformFindByUsernameOrEmail_thenReturnsAccount() {
+ String email = "test@test.com";
+ String username = "user_editor";
+ Account account = accountRepository.findByUsernameOrEmail(username, email);
+ assertThat(account.getUsername()).isNotEqualTo(username);
+ assertThat(account.getEmail()).isEqualTo(email);
+ }
+
+ @Test
+ void givenAccountInDb_whenPerformFindByUsernameInOrEmailIn_thenReturnsAccounts() {
+ List emails = Arrays.asList("test@test.com", "abc@abc.com", "pqr@pqr.com");
+ List usernames = Arrays.asList("user_editor", "user_admin");
+ List byUsernameInOrEmailIn = accountRepository.findByUsernameInOrEmailIn(usernames, emails);
+ assertThat(byUsernameInOrEmailIn.size()).isEqualTo(1);
+ assertThat(byUsernameInOrEmailIn.get(0)
+ .getEmail()).isEqualTo("test@test.com");
+ }
+
+ private Permission getPermissions() {
+ Permission editor = new Permission();
+ editor.setType("editor");
+ permissionRepository.save(editor);
+ return editor;
+ }
+
+ private void saveAccount() {
+ List> sampleRecords = Arrays.asList(
+ Arrays.asList("test@test.com", "user_admin"),
+ Arrays.asList("test1@test.com", "user_admin_1"),
+ Arrays.asList("test2@test.com", "user_admin_2")
+ );
+
+ sampleRecords.forEach(sampleRecord -> {
+ Account account = new Account();
+ account.setEmail(sampleRecord.get(0));
+ account.setUsername(sampleRecord.get(1));
+ account.setPermission(getPermissions());
+ account.setPassword(UUID.randomUUID()
+ .toString());
+ account.setCreatedOn(Timestamp.from(Instant.now()));
+ account.setLastLogin(Timestamp.from(Instant.now()));
+ accountRepository.save(account);
+ System.out.println(account.toString());
+ });
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-4/README.md b/persistence-modules/spring-boot-persistence-4/README.md
index 7011f492ca..746df92a0b 100644
--- a/persistence-modules/spring-boot-persistence-4/README.md
+++ b/persistence-modules/spring-boot-persistence-4/README.md
@@ -2,3 +2,4 @@
- [Scroll API in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-scroll-api)
- [List vs. Set in @OneToMany JPA](https://www.baeldung.com/spring-jpa-onetomany-list-vs-set)
- [N+1 Problem in Hibernate and Spring Data JPA](https://www.baeldung.com/spring-hibernate-n1-problem)
+- [Get All Results at Once in a Spring Boot Paged Query Method](https://www.baeldung.com/spring-boot-paged-query-all-results)
diff --git a/persistence-modules/spring-jooq/pom.xml b/persistence-modules/spring-jooq/pom.xml
index 5f8ab7231c..1387635afe 100644
--- a/persistence-modules/spring-jooq/pom.xml
+++ b/persistence-modules/spring-jooq/pom.xml
@@ -194,6 +194,7 @@
1.0.0
1.5
1.0.0
+ 3.1.5
\ No newline at end of file
diff --git a/persistence-modules/spring-mybatis/pom.xml b/persistence-modules/spring-mybatis/pom.xml
index 6de7cef347..d179881710 100644
--- a/persistence-modules/spring-mybatis/pom.xml
+++ b/persistence-modules/spring-mybatis/pom.xml
@@ -84,6 +84,7 @@
3.5.2
3.0.3
true
+ 3.1.5
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index dc2156faf8..6de6042906 100644
--- a/pom.xml
+++ b/pom.xml
@@ -328,12 +328,6 @@
- parent-boot-1
- parent-boot-2
- parent-spring-4
- parent-spring-5
- parent-spring-6
-
core-java-modules/core-java-8
@@ -404,12 +398,6 @@
- parent-boot-1
- parent-boot-2
- parent-spring-4
- parent-spring-5
- parent-spring-6
-
spring-4
spring-6
@@ -460,12 +448,6 @@
- parent-boot-1
- parent-boot-2
- parent-spring-4
- parent-spring-5
- parent-spring-6
-
apache-spark
jhipster-modules
web-modules/restx
@@ -498,12 +480,6 @@
- parent-boot-1
- parent-boot-2
- parent-spring-4
- parent-spring-5
- parent-spring-6
-
core-java-modules/core-java-8
@@ -683,6 +659,11 @@
+ parent-boot-1
+ parent-boot-2
+ parent-spring-4
+ parent-spring-5
+ parent-spring-6
akka-modules
algorithms-modules
apache-cxf-modules
@@ -924,6 +905,11 @@
+ parent-boot-1
+ parent-boot-2
+ parent-spring-4
+ parent-spring-5
+ parent-spring-6
akka-modules
algorithms-modules
apache-cxf-modules
diff --git a/quarkus-modules/quarkus-virtual-threads/README.md b/quarkus-modules/quarkus-virtual-threads/README.md
index e69de29bb2..4db48675bb 100644
--- a/quarkus-modules/quarkus-virtual-threads/README.md
+++ b/quarkus-modules/quarkus-virtual-threads/README.md
@@ -0,0 +1,2 @@
+### Relevant Articles
+- [Quarkus and Virtual Threads](https://www.baeldung.com/java-quarkus-virtual-threads)
diff --git a/spring-aop-2/README.md b/spring-aop-2/README.md
index 0aa20d32f0..3553ed7888 100644
--- a/spring-aop-2/README.md
+++ b/spring-aop-2/README.md
@@ -8,4 +8,5 @@ This module contains articles about Spring aspect oriented programming (AOP)
- [When Does Java Throw UndeclaredThrowableException?](https://www.baeldung.com/java-undeclaredthrowableexception)
- [Get Advised Method Info in Spring AOP](https://www.baeldung.com/spring-aop-get-advised-method-info)
- [Invoke Spring @Cacheable from Another Method of Same Bean](https://www.baeldung.com/spring-invoke-cacheable-other-method-same-bean)
+- [Logging With AOP in Spring](https://www.baeldung.com/spring-aspect-oriented-programming-logging)
- More articles: [[<-- prev]](/spring-aop)
diff --git a/spring-aop-2/src/main/java/com/baeldung/logging/GreetingService.java b/spring-aop-2/src/main/java/com/baeldung/logging/GreetingService.java
new file mode 100644
index 0000000000..1bdf3dc9d8
--- /dev/null
+++ b/spring-aop-2/src/main/java/com/baeldung/logging/GreetingService.java
@@ -0,0 +1,11 @@
+package com.baeldung.logging;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class GreetingService {
+
+ public String greet(String name) {
+ return String.format("Hello %s", name);
+ }
+}
diff --git a/spring-aop-2/src/main/java/com/baeldung/logging/GreetingServiceWithoutAOP.java b/spring-aop-2/src/main/java/com/baeldung/logging/GreetingServiceWithoutAOP.java
new file mode 100644
index 0000000000..eee90af669
--- /dev/null
+++ b/spring-aop-2/src/main/java/com/baeldung/logging/GreetingServiceWithoutAOP.java
@@ -0,0 +1,18 @@
+package com.baeldung.logging;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class GreetingServiceWithoutAOP {
+
+ private static final Logger logger = LoggerFactory.getLogger(GreetingServiceWithoutAOP.class);
+
+ public String greet(String name) {
+ logger.info(">> greet() - {}", name);
+ String result = String.format("Hello %s", name);
+ logger.info("<< greet() - {}", result);
+ return result;
+ }
+}
diff --git a/spring-aop-2/src/main/java/com/baeldung/logging/LoggingAspect.java b/spring-aop-2/src/main/java/com/baeldung/logging/LoggingAspect.java
new file mode 100644
index 0000000000..6641b70eec
--- /dev/null
+++ b/spring-aop-2/src/main/java/com/baeldung/logging/LoggingAspect.java
@@ -0,0 +1,55 @@
+package com.baeldung.logging;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+
+@Aspect
+@Component
+public class LoggingAspect {
+
+ private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
+
+ @Pointcut("execution(public * com.baeldung.logging.*.*(..))")
+ private void publicMethodsFromLoggingPackage() {
+ }
+
+ @Before(value = "publicMethodsFromLoggingPackage()")
+ public void logBefore(JoinPoint joinPoint) {
+ Object[] args = joinPoint.getArgs();
+ String methodName = joinPoint.getSignature().getName();
+ logger.info(">> {}() - {}", methodName, Arrays.toString(args));
+ }
+
+ @AfterReturning(value = "publicMethodsFromLoggingPackage()", returning = "result")
+ public void logAfter(JoinPoint joinPoint, Object result) {
+ String methodName = joinPoint.getSignature().getName();
+ logger.info("<< {}() - {}", methodName, result);
+ }
+
+ @AfterThrowing(pointcut = "publicMethodsFromLoggingPackage()", throwing = "exception")
+ public void logException(JoinPoint joinPoint, Throwable exception) {
+ String methodName = joinPoint.getSignature().getName();
+ logger.error("<< {}() - {}", methodName, exception.getMessage());
+ }
+
+ @Around(value = "publicMethodsFromLoggingPackage()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ Object[] args = joinPoint.getArgs();
+ String methodName = joinPoint.getSignature().getName();
+ logger.info(">> {}() - {}", methodName, Arrays.toString(args));
+ Object result = joinPoint.proceed();
+ logger.info("<< {}() - {}", methodName, result);
+ return result;
+ }
+}
diff --git a/spring-aop-2/src/test/java/com/baeldung/logging/GreetingServiceUnitTest.java b/spring-aop-2/src/test/java/com/baeldung/logging/GreetingServiceUnitTest.java
new file mode 100644
index 0000000000..6a6c1c8a70
--- /dev/null
+++ b/spring-aop-2/src/test/java/com/baeldung/logging/GreetingServiceUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.logging;
+
+import com.baeldung.Application;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@SpringBootTest(classes = Application.class)
+class GreetingServiceUnitTest {
+
+ @Autowired
+ private GreetingService greetingService;
+
+ @Test
+ void givenName_whenGreet_thenReturnCorrectResult() {
+ String result = greetingService.greet("Baeldung");
+ assertNotNull(result);
+ assertEquals("Hello Baeldung", result);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-properties/pom.xml b/spring-boot-modules/spring-boot-properties/pom.xml
index dc1ab067a9..7614941f2d 100644
--- a/spring-boot-modules/spring-boot-properties/pom.xml
+++ b/spring-boot-modules/spring-boot-properties/pom.xml
@@ -147,6 +147,7 @@
@
com.baeldung.yaml.MyApplication
+ 3.1.5
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-ssl-bundles/pom.xml b/spring-boot-modules/spring-boot-ssl-bundles/pom.xml
index 1f4e58f21f..8edbd9c79e 100644
--- a/spring-boot-modules/spring-boot-ssl-bundles/pom.xml
+++ b/spring-boot-modules/spring-boot-ssl-bundles/pom.xml
@@ -53,6 +53,7 @@
5.0.3
+ 3.1.5
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-eureka/pom.xml b/spring-cloud-modules/spring-cloud-eureka/pom.xml
index 9966459a5c..686ca4f0e9 100644
--- a/spring-cloud-modules/spring-cloud-eureka/pom.xml
+++ b/spring-cloud-modules/spring-cloud-eureka/pom.xml
@@ -10,9 +10,10 @@
Spring Cloud Eureka Server and Sample Clients
- com.baeldung.spring.cloud
- spring-cloud-modules
- 1.0.0-SNAPSHOT
+ com.baeldung
+ parent-boot-3
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-3
@@ -23,6 +24,10 @@
spring-cloud-eureka-server
+
+ 2023.0.0
+
+
org.springframework.boot
diff --git a/spring-jinq/pom.xml b/spring-jinq/pom.xml
index ebac1c3112..4ba2028bc6 100644
--- a/spring-jinq/pom.xml
+++ b/spring-jinq/pom.xml
@@ -65,6 +65,7 @@
2.0.1
6.4.2.Final
+ 3.1.5
\ No newline at end of file
diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/HandleInstanceAlreadyExistsException.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/HandleInstanceAlreadyExistsException.java
new file mode 100644
index 0000000000..1de39987b8
--- /dev/null
+++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/HandleInstanceAlreadyExistsException.java
@@ -0,0 +1,56 @@
+package com.baeldung.spring.kafka.kafkaexception;
+
+import java.lang.management.ManagementFactory;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.common.serialization.StringSerializer;
+
+public class HandleInstanceAlreadyExistsException {
+
+ public static void generateUniqueClientIDUsingUUIDRandom() {
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "localhost:9092");
+ props.put("key.serializer", StringSerializer.class);
+ props.put("value.serializer", StringSerializer.class);
+
+ String clientId = "my-producer-" + UUID.randomUUID();
+ props.setProperty("client.id", clientId);
+ KafkaProducer producer1 = new KafkaProducer<>(props);
+
+ clientId = "my-producer-" + UUID.randomUUID();
+ props.setProperty("client.id", clientId);
+ KafkaProducer producer2 = new KafkaProducer<>(props);
+ }
+
+ public static void closeProducerProperlyBeforeReinstantiate() {
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "localhost:9092");
+ props.put("client.id", "my-producer");
+ props.put("key.serializer", StringSerializer.class);
+ props.put("value.serializer", StringSerializer.class);
+
+ KafkaProducer producer1 = new KafkaProducer<>(props);
+ producer1.close();
+
+ producer1 = new KafkaProducer<>(props);
+ }
+
+ public static void useUniqueObjectName() throws Exception {
+ MBeanServer mBeanServer1 = ManagementFactory.getPlatformMBeanServer();
+ MBeanServer mBeanServer2 = ManagementFactory.getPlatformMBeanServer();
+
+ ObjectName objectName1 = new ObjectName("kafka.server:type=KafkaMetrics,id=metric1");
+ ObjectName objectName2 = new ObjectName("kafka.server:type=KafkaMetrics,id=metric2");
+
+ MyMBean mBean1 = new MyMBean();
+ mBeanServer1.registerMBean(mBean1, objectName1);
+
+ MyMBean mBean2 = new MyMBean();
+ mBeanServer2.registerMBean(mBean2, objectName2);
+ }
+}
diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/KafkaAppMain.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/KafkaAppMain.java
new file mode 100644
index 0000000000..14d6b71b10
--- /dev/null
+++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/KafkaAppMain.java
@@ -0,0 +1,12 @@
+package com.baeldung.spring.kafka.kafkaexception;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class KafkaAppMain {
+
+ public static void main(String[] args) {
+ SpringApplication.run(KafkaAppMain.class, args);
+ }
+}
diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/SimulateInstanceAlreadyExistsException.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/SimulateInstanceAlreadyExistsException.java
new file mode 100644
index 0000000000..d454d317f2
--- /dev/null
+++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/kafkaexception/SimulateInstanceAlreadyExistsException.java
@@ -0,0 +1,123 @@
+package com.baeldung.spring.kafka.kafkaexception;
+
+import java.lang.management.ManagementFactory;
+import java.util.Properties;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SimulateInstanceAlreadyExistsException {
+
+ public static void jmxRegistrationConflicts() throws Exception {
+ // Create two instances of MBeanServer
+ MBeanServer mBeanServer1 = ManagementFactory.getPlatformMBeanServer();
+ MBeanServer mBeanServer2 = ManagementFactory.getPlatformMBeanServer();
+
+ // Define the same ObjectName for both MBeans
+ ObjectName objectName = new ObjectName("kafka.server:type=KafkaMetrics");
+
+ // Create and register the first MBean
+ MyMBean mBean1 = new MyMBean();
+ mBeanServer1.registerMBean(mBean1, objectName);
+
+ // Attempt to register the second MBean with the same ObjectName
+ MyMBean mBean2 = new MyMBean();
+ mBeanServer2.registerMBean(mBean2, objectName);
+ }
+
+ public static void duplicateConsumerClientID() {
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "localhost:9092");
+ props.put("client.id", "my-consumer");
+ props.put("group.id", "test-group");
+ props.put("key.deserializer", StringDeserializer.class);
+ props.put("value.deserializer", StringDeserializer.class);
+
+ // Simulating concurrent client creation by multiple threads
+ for (int i = 0; i < 3; i++) {
+ new Thread(() -> {
+ KafkaConsumer consumer = new KafkaConsumer<>(props);
+ }).start();
+ }
+ }
+
+ public void duplicateProducerClientID() throws Exception {
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "localhost:9092");
+ props.put("client.id", "my-producer");
+ props.put("key.serializer", StringSerializer.class);
+ props.put("value.serializer", StringSerializer.class);
+
+ KafkaProducer producer1 = new KafkaProducer<>(props);
+ // Attempting to create another producer using same client.id
+ KafkaProducer producer2 = new KafkaProducer<>(props);
+ }
+
+ public static void unclosedProducerAndReinitialize() {
+ Properties props = new Properties();
+ props.put("bootstrap.servers", "localhost:9092");
+ props.put("client.id", "my-producer");
+ props.put("key.serializer", StringSerializer.class);
+ props.put("value.serializer", StringSerializer.class);
+
+ KafkaProducer producer1 = new KafkaProducer<>(props);
+ // Attempting to reinitialize without proper close
+ producer1 = new KafkaProducer<>(props);
+ }
+}
+
+class MyMBean implements DynamicMBean {
+
+ @Override
+ public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
+ return null;
+ }
+
+ @Override
+ public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+
+ }
+
+ @Override
+ public AttributeList getAttributes(String[] attributes) {
+ return null;
+ }
+
+ @Override
+ public AttributeList setAttributes(AttributeList attributes) {
+ return null;
+ }
+
+ @Override
+ public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+ return null;
+ }
+
+ @Override
+ public MBeanInfo getMBeanInfo() {
+ MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[0];
+ MBeanConstructorInfo[] constructors = new MBeanConstructorInfo[0];
+ MBeanOperationInfo[] operations = new MBeanOperationInfo[0];
+ MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[0];
+ return new MBeanInfo(MyMBean.class.getName(), "My MBean", attributes, constructors, operations, notifications);
+ }
+}
diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/viewheaders/KafkaMessageConsumer.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/viewheaders/KafkaMessageConsumer.java
new file mode 100644
index 0000000000..3bdc13d968
--- /dev/null
+++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/viewheaders/KafkaMessageConsumer.java
@@ -0,0 +1,33 @@
+package com.baeldung.spring.kafka.viewheaders;
+
+import java.util.Map;
+
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.support.KafkaHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.messaging.handler.annotation.Headers;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Service;
+
+@Service
+public class KafkaMessageConsumer {
+
+ @KafkaListener(topics = { "my-topic" }, groupId = "my-consumer-group")
+ public void listen(@Payload String message, @Headers Map headers) {
+ System.out.println("Received message: " + message);
+ System.out.println("Headers:");
+ headers.forEach((key, value) -> System.out.println(key + ": " + value));
+
+ String topicName = (String) headers.get(KafkaHeaders.TOPIC);
+ System.out.println("Topic: " + topicName);
+ int partitionID = (int) headers.get(KafkaHeaders.RECEIVED_PARTITION_ID);
+ System.out.println("Partition ID: " + partitionID);
+ }
+
+ @KafkaListener(topics = { "my-topic" }, groupId = "my-consumer-group")
+ public void listen(@Payload String message, @Header(KafkaHeaders.RECEIVED_TOPIC) String topicName,
+ @Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition) {
+ System.out.println("Topic: " + topicName);
+ System.out.println("Partition ID: " + partition);
+ }
+}
\ No newline at end of file
diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/viewheaders/Main.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/viewheaders/Main.java
new file mode 100644
index 0000000000..fdd28e9044
--- /dev/null
+++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/viewheaders/Main.java
@@ -0,0 +1,63 @@
+package com.baeldung.spring.kafka.viewheaders;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.kafka.core.DefaultKafkaProducerFactory;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.core.ProducerFactory;
+
+@SpringBootApplication
+public class Main {
+
+ @Autowired
+ static KafkaMessageConsumer kafkaMessageConsumer;
+
+ @Bean
+ public KafkaTemplate kafkaTemplate() {
+ return new KafkaTemplate<>(producerFactory());
+ }
+
+ @Bean
+ public ProducerFactory producerFactory() {
+ Map configProps = new HashMap<>();
+ configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+ configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+ return new DefaultKafkaProducerFactory<>(configProps);
+ }
+
+ @Bean
+ public KafkaConsumer kafkaConsumer() {
+ Map configProps = new HashMap<>();
+ configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+ configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+ configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "my-consumer-group");
+ return new KafkaConsumer<>(configProps);
+ }
+
+ public static void main(String[] args) {
+ ConfigurableApplicationContext context = SpringApplication.run(Main.class, args);
+
+ // Get the KafkaTemplate bean from the application context
+ KafkaTemplate kafkaTemplate = context.getBean(KafkaTemplate.class);
+
+ // Send a message to the "my-topic" Kafka topic
+ String message = "Hello Baeldung!";
+ kafkaTemplate.send("my-topic", message);
+
+ // Close the application context
+ context.close();
+ }
+}
diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java
index e8aa63a88d..6d3ba2b4d9 100644
--- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java
+++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java
@@ -116,7 +116,7 @@ public class KafkaConsumerConfig {
public ConcurrentKafkaListenerContainerFactory multiTypeKafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(multiTypeConsumerFactory());
- factory.setMessageConverter(multiTypeConverter());
+ factory.setRecordMessageConverter(multiTypeConverter());
return factory;
}
diff --git a/spring-reactive-modules/spring-reactive-exceptions/pom.xml b/spring-reactive-modules/spring-reactive-exceptions/pom.xml
index a9fdb675f5..e9208c8b20 100644
--- a/spring-reactive-modules/spring-reactive-exceptions/pom.xml
+++ b/spring-reactive-modules/spring-reactive-exceptions/pom.xml
@@ -54,4 +54,8 @@
+
+ 3.1.5
+
+
diff --git a/spring-security-modules/spring-security-web-angular/pom.xml b/spring-security-modules/spring-security-web-angular/pom.xml
index 15dc4d007c..67b6d233e6 100644
--- a/spring-security-modules/spring-security-web-angular/pom.xml
+++ b/spring-security-modules/spring-security-web-angular/pom.xml
@@ -10,7 +10,8 @@
com.baeldung
- spring-security-modules
+ parent-boot-3
+ ../../parent-boot-3
0.0.1-SNAPSHOT
diff --git a/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/pom.xml b/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/pom.xml
index b33e0925a3..bf9fed6898 100644
--- a/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/pom.xml
+++ b/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/pom.xml
@@ -15,10 +15,6 @@
-
-
-
-
org.springframework.boot
spring-boot-starter-security
diff --git a/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/basicauth/config/BasicAuthConfiguration.java b/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/basicauth/config/BasicAuthConfiguration.java
index 5f4b82a191..37b63d95b4 100644
--- a/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/basicauth/config/BasicAuthConfiguration.java
+++ b/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/basicauth/config/BasicAuthConfiguration.java
@@ -7,6 +7,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@@ -27,18 +28,13 @@ public class BasicAuthConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http.csrf()
- .disable()
+ http.csrf(AbstractHttpConfigurer::disable)
.cors(withDefaults())
- .authorizeRequests()
- .antMatchers(HttpMethod.OPTIONS, "/**")
- .permitAll()
- .antMatchers("/login")
- .permitAll()
- .anyRequest()
- .authenticated()
- .and()
- .httpBasic();
+ .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
+ .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
+ .requestMatchers("/login").permitAll()
+ .anyRequest().authenticated())
+ .httpBasic(withDefaults());
return http.build();
}
}
diff --git a/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/controller/UserController.java b/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/controller/UserController.java
index 0eef4198a1..3413eaf69b 100644
--- a/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/controller/UserController.java
+++ b/spring-security-modules/spring-security-web-angular/spring-security-web-angular-server/src/main/java/com/baeldung/springbootsecurityrest/controller/UserController.java
@@ -3,7 +3,7 @@ package com.baeldung.springbootsecurityrest.controller;
import java.security.Principal;
import java.util.Base64;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
index 136f5b8907..59e07ece69 100644
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/pom.xml
@@ -29,17 +29,23 @@
org.openapitools
openapi-generator
${openapi-generator.version}
-
-
- com.fasterxml.jackson.core
- jackson-databind
- ${jackson-databind.version}
+
+
+ org.slf4j
+ slf4j-simple
+
+
org.springdoc
springdoc-openapi-ui
${springdoc.version}
+
+ org.openapitools
+ jackson-databind-nullable
+ ${jackson-databind-nullable.version}
+
@@ -85,9 +91,9 @@
3.0.0
2.17.1
1.7.0
- 3.3.4
- 2.16.0
- 5.1.0
+ 7.2.0
+ 7.2.0
+ 0.2.6
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache
index ed806c6282..34f9f0a65c 100644
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/api.mustache
@@ -1,14 +1,29 @@
/**
- * NOTE: This class is auto generated by OpenAPI Generator (https://com.baeldung.openapi-generator.tech) ({{{generatorVersion}}}).
- * https://com.baeldung.openapi-generator.tech
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) ({{{generatorVersion}}}).
+ * https://openapi-generator.tech
* Do not edit the class manually.
*/
package {{package}};
{{#imports}}import {{import}};
{{/imports}}
-import io.swagger.annotations.*;
import com.baeldung.openapi.petstore.validation.Capitalized;
+{{#swagger2AnnotationLibrary}}
+import io.swagger.v3.oas.annotations.ExternalDocumentation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+{{/swagger2AnnotationLibrary}}
+{{#swagger1AnnotationLibrary}}
+import io.swagger.annotations.*;
+{{/swagger1AnnotationLibrary}}
{{#jdk8-no-delegate}}
{{#virtualService}}
import io.virtualan.annotation.ApiVirtual;
@@ -17,18 +32,28 @@ import io.virtualan.annotation.VirtualService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
{{/jdk8-no-delegate}}
+{{^useResponseEntity}}
+import org.springframework.http.HttpStatus;
+{{/useResponseEntity}}
+{{#useResponseEntity}}
import org.springframework.http.ResponseEntity;
+{{/useResponseEntity}}
{{#useBeanValidation}}
import org.springframework.validation.annotation.Validated;
{{/useBeanValidation}}
-{{#vendorExtensions.x-spring-paginated}}
-import org.springframework.data.domain.Pageable;
-{{/vendorExtensions.x-spring-paginated}}
+{{#useSpringController}}
+{{#useResponseEntity}}
+import org.springframework.stereotype.Controller;
+{{/useResponseEntity}}
+{{^useResponseEntity}}
+import org.springframework.web.bind.annotation.RestController;
+{{/useResponseEntity}}
+{{/useSpringController}}
import org.springframework.web.bind.annotation.*;
{{#jdk8-no-delegate}}
- {{^reactive}}
+{{^reactive}}
import org.springframework.web.context.request.NativeWebRequest;
- {{/reactive}}
+{{/reactive}}
{{/jdk8-no-delegate}}
import org.springframework.web.multipart.MultipartFile;
{{#reactive}}
@@ -39,8 +64,8 @@ import org.springframework.http.codec.multipart.Part;
{{/reactive}}
{{#useBeanValidation}}
-import javax.validation.Valid;
-import javax.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+import {{javaxPackage}}.validation.constraints.*;
{{/useBeanValidation}}
import java.util.List;
import java.util.Map;
@@ -48,22 +73,42 @@ import java.util.Map;
import java.util.Optional;
{{/jdk8-no-delegate}}
{{^jdk8-no-delegate}}
- {{#useOptional}}
+{{#useOptional}}
import java.util.Optional;
- {{/useOptional}}
+{{/useOptional}}
{{/jdk8-no-delegate}}
{{#async}}
-import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}};
+import java.util.concurrent.CompletableFuture;
{{/async}}
+import {{javaxPackage}}.annotation.Generated;
+
{{>generatedAnnotation}}
{{#useBeanValidation}}
@Validated
{{/useBeanValidation}}
-@Api(value = "{{{baseName}}}", tags = "All")
+{{#useSpringController}}
+{{#useResponseEntity}}
+@Controller
+{{/useResponseEntity}}
+{{^useResponseEntity}}
+@RestController
+{{/useResponseEntity}}
+{{/useSpringController}}
+{{#swagger2AnnotationLibrary}}
+@Tag(name = "{{{tagName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{tagName}}} API"{{/tagDescription}})
+{{/swagger2AnnotationLibrary}}
+{{#swagger1AnnotationLibrary}}
+@Api(value = "{{{tagName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{tagName}}} API"{{/tagDescription}})
+{{/swagger1AnnotationLibrary}}
{{#operations}}
{{#virtualService}}
@VirtualService
{{/virtualService}}
+{{#useRequestMappingOnInterface}}
+{{=<% %>=}}
+@RequestMapping("${openapi.<%title%>.base-path:<%>defaultBasePath%>}")
+<%={{ }}=%>
+{{/useRequestMappingOnInterface}}
public interface {{classname}} {
{{#jdk8-default-interface}}
{{^isDelegate}}
@@ -102,45 +147,127 @@ public interface {{classname}} {
* @see {{summary}} Documentation
{{/externalDocs}}
*/
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
{{#virtualService}}
@ApiVirtual
{{/virtualService}}
- @ApiOperation(value = "{{{summary}}}", nickname = "{{{operationId}}}", notes = "{{{notes}}}"{{#returnBaseType}}, response = {{{returnBaseType}}}.class{{/returnBaseType}}{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = {
- {{#authMethods}}{{#isOAuth}}@Authorization(value = "{{name}}", scopes = {
- {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}},
- {{/-last}}{{/scopes}} }){{^-last}},{{/-last}}{{/isOAuth}}
- {{^isOAuth}}@Authorization(value = "{{name}}"){{^-last}},{{/-last}}
- {{/isOAuth}}{{/authMethods}} }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} })
- @ApiResponses(value = { {{#responses}}
- @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}} })
- {{#implicitHeaders}}
- @ApiImplicitParams({
- {{#headerParams}}
- {{>implicitHeader}}
- {{/headerParams}}
+ {{#swagger2AnnotationLibrary}}
+ @Operation(
+ operationId = "{{{operationId}}}",
+ {{#summary}}
+ summary = "{{{.}}}",
+ {{/summary}}
+ {{#notes}}
+ description = "{{{.}}}",
+ {{/notes}}
+ {{#isDeprecated}}
+ deprecated = true,
+ {{/isDeprecated}}
+ {{#vendorExtensions.x-tags.size}}
+ tags = { {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} },
+ {{/vendorExtensions.x-tags.size}}
+ responses = {
+ {{#responses}}
+ @ApiResponse(responseCode = {{#isDefault}}"default"{{/isDefault}}{{^isDefault}}"{{{code}}}"{{/isDefault}}, description = "{{{message}}}"{{#baseType}}, content = {
+ {{#produces}}
+ @Content(mediaType = "{{{mediaType}}}", {{#isArray}}array = @ArraySchema({{/isArray}}schema = @Schema(implementation = {{{baseType}}}.class){{#isArray}}){{/isArray}}){{^-last}},{{/-last}}
+ {{/produces}}
+ }{{/baseType}}){{^-last}},{{/-last}}
+ {{/responses}}
+ }{{#hasAuthMethods}},
+ security = {
+ {{#authMethods}}
+ @SecurityRequirement(name = "{{name}}"{{#scopes.0}}, scopes={ {{#scopes}}"{{scope}}"{{^-last}}, {{/-last}}{{/scopes}} }{{/scopes.0}}){{^-last}},{{/-last}}
+ {{/authMethods}}
+ }{{/hasAuthMethods}}{{#externalDocs}},
+ externalDocs = @ExternalDocumentation(description = "{{externalDocs.description}}", url = "{{externalDocs.url}}"){{/externalDocs}}
+ )
+ {{/swagger2AnnotationLibrary}}
+ {{#swagger1AnnotationLibrary}}
+ @ApiOperation(
+ {{#vendorExtensions.x-tags.size}}
+ tags = { {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} },
+ {{/vendorExtensions.x-tags.size}}
+ value = "{{{summary}}}",
+ nickname = "{{{operationId}}}",
+ notes = "{{{notes}}}"{{#returnBaseType}},
+ response = {{{.}}}.class{{/returnBaseType}}{{#returnContainer}},
+ responseContainer = "{{{.}}}"{{/returnContainer}}{{#hasAuthMethods}},
+ authorizations = {
+ {{#authMethods}}
+ {{#scopes.0}}
+ @Authorization(value = "{{name}}", scopes = {
+ {{#scopes}}
+ @AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}},{{/-last}}
+ {{/scopes}}
+ }){{^-last}},{{/-last}}
+ {{/scopes.0}}
+ {{^scopes.0}}
+ @Authorization(value = "{{name}}"){{^-last}},{{/-last}}
+ {{/scopes.0}}
+ {{/authMethods}} }{{/hasAuthMethods}}
+ )
+ @ApiResponses({
+ {{#responses}}
+ @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}}
+ {{/responses}}
})
- {{/implicitHeaders}}
+ {{/swagger1AnnotationLibrary}}
+ {{#implicitHeadersParams.0}}
+ {{#swagger2AnnotationLibrary}}
+ @Parameters({
+ {{#implicitHeadersParams}}
+ {{>paramDoc}}{{^-last}},{{/-last}}
+ {{/implicitHeadersParams}}
+ })
+ {{/swagger2AnnotationLibrary}}
+ {{#swagger1AnnotationLibrary}}
+ @ApiImplicitParams({
+ {{#implicitHeadersParams}}
+ {{>implicitHeader}}{{^-last}},{{/-last}}
+ {{/implicitHeadersParams}}
+ })
+ {{/swagger1AnnotationLibrary}}
+ {{/implicitHeadersParams.0}}
@RequestMapping(
method = RequestMethod.{{httpMethod}},
value = "{{{path}}}"{{#singleContentTypes}}{{#hasProduces}},
produces = "{{{vendorExtensions.x-accepts}}}"{{/hasProduces}}{{#hasConsumes}},
- consumes = "{{{vendorExtensions.x-contentType}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}},
+ consumes = "{{{vendorExtensions.x-content-type}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}},
produces = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }{{/hasProduces}}{{#hasConsumes}},
- consumes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }{{/hasConsumes}}{{/singleContentTypes}}
+ consumes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }{{/hasConsumes}}{{/singleContentTypes}}{{#hasVersionHeaders}},
+ headers = { {{#vendorExtensions.versionHeaderParamsList}}"{{baseName}}{{#defaultValue}}={{{.}}}{{/defaultValue}}"{{^-last}}, {{/-last}}{{/vendorExtensions.versionHeaderParamsList}} } {{/hasVersionHeaders}}{{#hasVersionQueryParams}},
+ params = { {{#vendorExtensions.versionQueryParamsList}}"{{baseName}}{{#defaultValue}}={{{.}}}{{/defaultValue}}"{{^-last}}, {{/-last}}{{/vendorExtensions.versionQueryParamsList}} } {{/hasVersionQueryParams}}
)
- {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}},{{/-last}}{{#-last}}{{#reactive}}, {{/reactive}}{{/-last}}{{/allParams}}{{#reactive}}final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}}{{#unhandledException}} throws Exception{{/unhandledException}} {
+ {{^useResponseEntity}}
+ @ResponseStatus({{#springHttpStatus}}{{#responses.0}}{{{code}}}{{/responses.0}}{{/springHttpStatus}})
+ {{/useResponseEntity}}
+ {{#vendorExtensions.x-operation-extra-annotation}}
+ {{{.}}}
+ {{/vendorExtensions.x-operation-extra-annotation}}
+ {{#vendorExtensions.x-sse}}@ResponseBody{{/vendorExtensions.x-sse}}
+ {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{>responseType}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}(
+ {{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}},
+ {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}},
+ {{/hasParams}}{{#swagger2AnnotationLibrary}}@Parameter(hidden = true){{/swagger2AnnotationLibrary}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}},
+ {{/hasParams}}{{^hasParams}}{{#reactive}},{{/reactive}}{{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore {{/springFoxDocumentationProvider}}{{#springDocDocumentationProvider}}@ParameterObject {{/springDocDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}{{#vendorExtensions.x-spring-provide-args}}{{#hasParams}},
+ {{/hasParams}}{{^hasParams}}{{#reactive}},{{/reactive}}{{/hasParams}}{{#swagger2AnnotationLibrary}}@Parameter(hidden = true){{/swagger2AnnotationLibrary}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} {{{.}}}{{^hasParams}}{{^-last}}{{^reactive}},{{/reactive}}
+ {{/-last}}{{/hasParams}}{{/vendorExtensions.x-spring-provide-args}}
+ ){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} {
{{#delegate-method}}
- return {{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
+ {{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}pageable{{/vendorExtensions.x-spring-paginated}});
}
// Override this method
- {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
+ {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{>responseType}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
{{/delegate-method}}
{{^isDelegate}}
{{>methodBody}}
{{/isDelegate}}
{{#isDelegate}}
- return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
+ {{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}pageable{{/vendorExtensions.x-spring-paginated}});
{{/isDelegate}}
}{{/jdk8-default-interface}}
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache
index e3c19c6474..45d963d889 100644
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/beanValidationCore.mustache
@@ -1,26 +1,25 @@
{{{ vendorExtensions.x-constraints }}}
-{{#errorMessage}}@Mandatory(errorMessage="{{{pattern}}}") {{/errorMessage}}
-{{#pattern}}@Pattern(regexp="{{{pattern}}}") {{/pattern}}{{!
+{{#pattern}}{{^isByteArray}}@Pattern(regexp = "{{{pattern}}}"{{#vendorExtensions.x-pattern-message}}, message="{{vendorExtensions.x-pattern-message}}"{{/vendorExtensions.x-pattern-message}}) {{/isByteArray}}{{/pattern}}{{!
minLength && maxLength set
-}}{{#minLength}}{{#maxLength}}@Size(min={{minLength}},max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
+}}{{#minLength}}{{#maxLength}}@Size(min = {{minLength}}, max = {{maxLength}}) {{/maxLength}}{{/minLength}}{{!
minLength set, maxLength not
-}}{{#minLength}}{{^maxLength}}@Size(min={{minLength}}) {{/maxLength}}{{/minLength}}{{!
+}}{{#minLength}}{{^maxLength}}@Size(min = {{minLength}}) {{/maxLength}}{{/minLength}}{{!
minLength not set, maxLength set
-}}{{^minLength}}{{#maxLength}}@Size(max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
+}}{{^minLength}}{{#maxLength}}@Size(max = {{.}}) {{/maxLength}}{{/minLength}}{{!
@Size: minItems && maxItems set
-}}{{#minItems}}{{#maxItems}}@Size(min={{minItems}},max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
+}}{{#minItems}}{{#maxItems}}@Size(min = {{minItems}}, max = {{maxItems}}) {{/maxItems}}{{/minItems}}{{!
@Size: minItems set, maxItems not
-}}{{#minItems}}{{^maxItems}}@Size(min={{minItems}}) {{/maxItems}}{{/minItems}}{{!
+}}{{#minItems}}{{^maxItems}}@Size(min = {{minItems}}) {{/maxItems}}{{/minItems}}{{!
@Size: minItems not set && maxItems set
-}}{{^minItems}}{{#maxItems}}@Size(max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
-@Email: useBeanValidation set && isEmail && java8 set
-}}{{#useBeanValidation}}{{#isEmail}}{{#java8}}@javax.validation.constraints.Email{{/java8}}{{/isEmail}}{{/useBeanValidation}}{{!
-@Email: performBeanValidation set && isEmail && not java8 set
-}}{{#performBeanValidation}}{{#isEmail}}{{^java8}}@org.hibernate.validator.constraints.Email{{/java8}}{{/isEmail}}{{/performBeanValidation}}{{!
+}}{{^minItems}}{{#maxItems}}@Size(max = {{.}}) {{/maxItems}}{{/minItems}}{{!
+@Email: useBeanValidation
+}}{{#isEmail}}{{#useBeanValidation}}@{{javaxPackage}}.validation.constraints.Email {{/useBeanValidation}}{{!
+@Email: performBeanValidation exclusive
+}}{{^useBeanValidation}}{{#performBeanValidation}}@org.hibernate.validator.constraints.Email {{/performBeanValidation}}{{/useBeanValidation}}{{/isEmail}}{{!
check for integer or long / all others=decimal type with @Decimal*
isInteger set
-}}{{#isInteger}}{{#minimum}}@Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}) {{/maximum}}{{/isInteger}}{{!
+}}{{#isInteger}}{{#minimum}}@Min({{.}}) {{/minimum}}{{#maximum}}@Max({{.}}) {{/maximum}}{{/isInteger}}{{!
isLong set
-}}{{#isLong}}{{#minimum}}@Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L) {{/maximum}}{{/isLong}}{{!
+}}{{#isLong}}{{#minimum}}@Min({{.}}L) {{/minimum}}{{#maximum}}@Max({{.}}L) {{/maximum}}{{/isLong}}{{!
Not Integer, not Long => we have a decimal value!
-}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}}
\ No newline at end of file
+}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}) {{/minimum}}{{#maximum}}@DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache
index e21bd9ff4b..74a837988f 100644
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/cookieParams.mustache
@@ -1 +1 @@
-{{#isCookieParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues = "{{#enumVars}}{{#lambdaEscapeDoubleQuote}}{{{value}}}{{/lambdaEscapeDoubleQuote}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/enumVars}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}) @CookieValue("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isCookieParam}}
\ No newline at end of file
+{{#isCookieParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{>paramDoc}} @CookieValue(name = "{{baseName}}"{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{>dateTimeParam}} {{>optionalDataType}} {{paramName}}{{/isCookieParam}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache
deleted file mode 100644
index 3cdae7f3cc..0000000000
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enum.mustache
+++ /dev/null
@@ -1,31 +0,0 @@
-class {{classname}} {
- /// The underlying value of this enum member.
- {{dataType}} value;
-
- {{classname}}._internal(this.value);
- {{ vendorExtensions.x-enum-varnames }}
- {{ vendorExtensions.x-enum-descriptions }}
- {{#allowableValues}}
- {{#enumVars}}
- {{#description}}
- /// {{description}}
- {{/description}}
- static {{classname}} {{name}} = {{classname}}._internal({{{value}}});
- {{/enumVars}}
- {{/allowableValues}}
-
- {{classname}}.fromJson(dynamic data) {
- switch (data) {
- {{#allowableValues}}
- {{#enumVars}}
- case {{{value}}}: value = data; break;
- {{/enumVars}}
- {{/allowableValues}}
- default: throw('Unknown enum value to decode: $data');
- }
- }
-
- static dynamic encode({{classname}} data) {
- return data.value;
- }
-}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enumClass.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enumClass.mustache
new file mode 100644
index 0000000000..14aff87c60
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enumClass.mustache
@@ -0,0 +1,60 @@
+/**
+ * {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}}
+ */
+ {{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} {
+ {{#gson}}
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{#enumDescription}}
+ /**
+ * {{.}}
+ */
+ {{/enumDescription}}
+ @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}
+ {{/enumVars}}
+ {{/allowableValues}}
+ {{/gson}}
+ {{^gson}}
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{#enumDescription}}
+ /**
+ * {{.}}
+ */
+ {{/enumDescription}}
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}
+ {{/enumVars}}
+ {{/allowableValues}}
+ {{/gson}}
+
+ private {{{dataType}}} value;
+
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) {
+ this.value = value;
+ }
+
+ {{#jackson}}
+ @JsonValue
+ {{/jackson}}
+ public {{{dataType}}} getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ @JsonCreator
+ public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
+ for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
+ if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
+ return b;
+ }
+ }
+ {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}}
+ }
+ }
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enumOuterClass.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enumOuterClass.mustache
new file mode 100644
index 0000000000..4c6b2e6329
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/enumOuterClass.mustache
@@ -0,0 +1,61 @@
+{{#jackson}}
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+{{/jackson}}
+
+/**
+ * {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}}
+ */
+{{>additionalEnumTypeAnnotations}}
+{{>generatedAnnotation}}
+public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
+ {{#gson}}
+ {{#allowableValues}}{{#enumVars}}
+ {{#enumDescription}}
+ /**
+ * {{.}}
+ */
+ {{/enumDescription}}
+ @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
+ {{/gson}}
+ {{^gson}}
+ {{#allowableValues}}{{#enumVars}}
+ {{#enumDescription}}
+ /**
+ * {{.}}
+ */
+ {{/enumDescription}}
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
+ {{/gson}}
+
+ private {{{dataType}}} value;
+
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
+ this.value = value;
+ }
+
+ {{#jackson}}
+ @JsonValue
+ {{/jackson}}
+ public {{{dataType}}} getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ @JsonCreator
+ public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
+ for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
+ if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
+ return b;
+ }
+ }
+ {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}}
+ }
+}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache
index 4546a811ef..3b6b12fda4 100644
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/model.mustache
@@ -1,42 +1,62 @@
package {{package}};
+import java.net.URI;
+import java.util.Objects;
{{#imports}}import {{import}};
{{/imports}}
-import com.fasterxml.jackson.databind.annotation.*;
-import com.fasterxml.jackson.annotation.*;
import com.baeldung.openapi.petstore.validation.Capitalized;
-{{^supportJava6}}
-import java.util.Objects;
-import java.util.Arrays;
-{{/supportJava6}}
-{{#supportJava6}}
-import org.apache.commons.lang3.ObjectUtils;
-{{/supportJava6}}
-{{#imports}}
-import {{import}};
-{{/imports}}
+{{#openApiNullable}}
+import org.openapitools.jackson.nullable.JsonNullable;
+{{/openApiNullable}}
{{#serializableModel}}
import java.io.Serializable;
{{/serializableModel}}
+import java.time.OffsetDateTime;
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.Valid;
+import {{javaxPackage}}.validation.constraints.*;
+{{/useBeanValidation}}
+{{^useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.NotNull;
+{{/useBeanValidation}}
+{{#performBeanValidation}}
+import org.hibernate.validator.constraints.*;
+{{/performBeanValidation}}
{{#jackson}}
{{#withXml}}
-import com.fasterxml.jackson.dataformat.xml.annotation.*;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
{{/withXml}}
{{/jackson}}
+{{#swagger2AnnotationLibrary}}
+import io.swagger.v3.oas.annotations.media.Schema;
+{{/swagger2AnnotationLibrary}}
+
{{#withXml}}
-import javax.xml.bind.annotation.*;
+import {{javaxPackage}}.xml.bind.annotation.*;
{{/withXml}}
-{{#parcelableModel}}
-import android.os.Parcelable;
-import android.os.Parcel;
-{{/parcelableModel}}
-{{#useBeanValidation}}
-import javax.validation.constraints.*;
-import javax.validation.Valid;
-{{/useBeanValidation}}
+{{^parent}}
+{{#hateoas}}
+import org.springframework.hateoas.RepresentationModel;
+{{/hateoas}}
+{{/parent}}
+
+import java.util.*;
+import {{javaxPackage}}.annotation.Generated;
{{#models}}
{{#model}}
-{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}}
+{{#additionalPropertiesType}}
+import java.util.Map;
+import java.util.HashMap;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+{{/additionalPropertiesType}}
+{{#isEnum}}
+{{>enumOuterClass}}
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}
+{{/isEnum}}
{{/model}}
{{/models}}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache
deleted file mode 100644
index 29f27bd851..0000000000
--- a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapi/templates/modelEnum.mustache
+++ /dev/null
@@ -1,68 +0,0 @@
-{{#jackson}}
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-{{/jackson}}
-{{#gson}}
-import java.io.IOException;
-import com.google.gson.TypeAdapter;
-import com.google.gson.annotations.JsonAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-{{/gson}}
-
-/**
- * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
- */
-{{#gson}}
-@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class)
-{{/gson}}
-public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
- {{#allowableValues}}{{#enumVars}}
- {{{name}}}({{{value}}}){{^-last}},
- {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
-
- private {{{dataType}}} value;
-
- {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
- this.value = value;
- }
-
-{{#jackson}}
- @JsonValue
-{{/jackson}}
- public {{{dataType}}} getValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
-
-{{#jackson}}
- @JsonCreator
-{{/jackson}}
- public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue{{#jackson}}({{{dataType}}} value){{/jackson}}{{^jackson}}(String text){{/jackson}} {
- for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
- if ({{#jackson}}b.value.equals(value){{/jackson}}{{^jackson}}String.valueOf(b.value).equals(text){{/jackson}}) {
- return b;
- }
- }
- throw new UlpValidationException(UlpBundleKey.{{vendorExtensions.x-enum-invalidtag}});
- }
-{{#gson}}
-
- public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
- @Override
- public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
- jsonWriter.value(enumeration.getValue());
- }
-
- @Override
- public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
- {{#isNumber}}BigDecimal value = new BigDecimal(jsonReader.nextDouble()){{/isNumber}}{{^isNumber}}{{#isInteger}}Integer value {{/isInteger}}{{^isInteger}}String value {{/isInteger}}= jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}nextString(){{/isInteger}}{{/isNumber}};
- return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#jackson}}value{{/jackson}}{{^jackson}}String.valueOf(value){{/jackson}});
- }
- }
-{{/gson}}
-}
\ No newline at end of file
diff --git a/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapitools.json b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapitools.json
new file mode 100644
index 0000000000..e73b975830
--- /dev/null
+++ b/spring-swagger-codegen/custom-validations-opeanpi-codegen/src/main/resources/openapitools.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
+ "spaces": 2,
+ "generator-cli": {
+ "version": "7.2.0"
+ }
+}
diff --git a/spring-web-modules/spring-thymeleaf-5/README.md b/spring-web-modules/spring-thymeleaf-5/README.md
index dcf5dd91b3..31796e251f 100644
--- a/spring-web-modules/spring-thymeleaf-5/README.md
+++ b/spring-web-modules/spring-thymeleaf-5/README.md
@@ -8,4 +8,5 @@ This module contains articles about Spring with Thymeleaf
- [Iteration in Thymeleaf](https://www.baeldung.com/thymeleaf-iteration)
- [Spring with Thymeleaf Pagination for a List](https://www.baeldung.com/spring-thymeleaf-pagination)
- [Display Image With Thymeleaf](https://www.baeldung.com/spring-thymeleaf-image)
+- [How to Check if a Variable Is Defined in Thymeleaf](https://www.baeldung.com/spring-thymeleaf-variable-defined)
- More articles: [[<-- prev]](../spring-thymeleaf-4)
diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml
index b2ef0a59ad..c4c929b7aa 100644
--- a/testing-modules/spring-testing/pom.xml
+++ b/testing-modules/spring-testing/pom.xml
@@ -75,6 +75,16 @@
spring-testing
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 15
+ 15
+
+
+
src/main/resources
@@ -87,7 +97,7 @@
2.0.0.0
3.1.6
- 5.3.4
+ 6.1.3
2.1.1
diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/testpropertysource/ClassUsingProperty.java b/testing-modules/spring-testing/src/main/java/com/baeldung/testpropertysource/ClassUsingProperty.java
index d545daf0df..88f2f89b4c 100644
--- a/testing-modules/spring-testing/src/main/java/com/baeldung/testpropertysource/ClassUsingProperty.java
+++ b/testing-modules/spring-testing/src/main/java/com/baeldung/testpropertysource/ClassUsingProperty.java
@@ -8,8 +8,15 @@ public class ClassUsingProperty {
@Value("${baeldung.testpropertysource.one}")
private String propertyOne;
-
+
+ @Value("${baeldung.testpropertysource.two}")
+ private String propertyTwo;
+
public String retrievePropertyOne() {
return propertyOne;
}
+
+ public String retrievePropertyTwo() {
+ return propertyTwo;
+ }
}
diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/MultiplePropertiesInPropertySourceListIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/MultiplePropertiesInPropertySourceListIntegrationTest.java
new file mode 100644
index 0000000000..e882d5c7cd
--- /dev/null
+++ b/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/MultiplePropertiesInPropertySourceListIntegrationTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.testpropertysource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = ClassUsingProperty.class)
+@TestPropertySource(
+ locations = "/other-location.properties",
+ properties = {
+ "baeldung.testpropertysource.one=one",
+ "baeldung.testpropertysource.two=two",
+ })
+public class MultiplePropertiesInPropertySourceListIntegrationTest {
+
+ @Autowired
+ ClassUsingProperty classUsingProperty;
+
+ @Test
+ public void givenAMultilinePropertySource_whenVariableOneRetrieved_thenValueInPropertyAnnotationIsReturned() {
+ String output = classUsingProperty.retrievePropertyOne();
+
+ assertThat(output).isEqualTo("one");
+ }
+
+ @Test
+ public void givenAMultilinePropertySource_whenVariableTwoRetrieved_thenValueInPropertyAnnotationIsReturned() {
+ String output = classUsingProperty.retrievePropertyTwo();
+
+ assertThat(output).isEqualTo("two");
+ }
+}
diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/MultiplePropertiesInPropertySourceTextBlockIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/MultiplePropertiesInPropertySourceTextBlockIntegrationTest.java
new file mode 100644
index 0000000000..e31055a4c6
--- /dev/null
+++ b/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/MultiplePropertiesInPropertySourceTextBlockIntegrationTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.testpropertysource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = ClassUsingProperty.class)
+@TestPropertySource(
+ locations = "/other-location.properties",
+ properties = """
+ baeldung.testpropertysource.one=one
+ baeldung.testpropertysource.two=two
+ """)
+public class MultiplePropertiesInPropertySourceTextBlockIntegrationTest {
+
+ @Autowired
+ ClassUsingProperty classUsingProperty;
+
+ @Test
+ public void givenAMultilinePropertySource_whenVariableOneRetrieved_thenValueInPropertyAnnotationIsReturned() {
+ String output = classUsingProperty.retrievePropertyOne();
+
+ assertThat(output).isEqualTo("one");
+ }
+
+ @Test
+ public void givenAMultilinePropertySource_whenVariableTwoRetrieved_thenValueInPropertyAnnotationIsReturned() {
+ String output = classUsingProperty.retrievePropertyTwo();
+
+ assertThat(output).isEqualTo("two");
+ }
+}
diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/PropertiesTestPropertySourceIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/PropertiesTestPropertySourceIntegrationTest.java
index d98e2b9f98..5100d3a3bb 100644
--- a/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/PropertiesTestPropertySourceIntegrationTest.java
+++ b/testing-modules/spring-testing/src/test/java/com/baeldung/testpropertysource/PropertiesTestPropertySourceIntegrationTest.java
@@ -18,7 +18,7 @@ public class PropertiesTestPropertySourceIntegrationTest {
ClassUsingProperty classUsingProperty;
@Test
- public void givenDefaultTestPropertySource_whenVariableOneRetrieved_thenValueInDefaultFileReturned() {
+ public void givenACustomPropertySource_whenVariableOneRetrieved_thenValueInPropertyAnnotationIsReturned() {
String output = classUsingProperty.retrievePropertyOne();
assertThat(output).isEqualTo("other-properties-value");