diff --git a/.gitignore b/.gitignore
index 7b448f6cb0..7f1bab3751 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,6 +67,8 @@ ethereum/logs/
jmeter/src/main/resources/*-JMeter.csv
jmeter/src/main/resources/*-Basic*.csv
jmeter/src/main/resources/*-JMeter*.csv
+jmeter/src/main/resources/*ReportsDashboard*.csv
+jmeter/src/main/resources/dashboard/*ReportsDashboard*.csv
ninja/devDb.mv.db
@@ -105,4 +107,11 @@ spring-boot-modules/spring-boot-properties-3/*.log
.sdkmanrc
# Localstack
-**/.localstack
\ No newline at end of file
+**/.localstack
+
+#libraries-2
+libraries-2/employee*
+libraries-2/src/test/resources/crawler4j/**
+
+#web-modules/ninja
+devDb*.db
\ No newline at end of file
diff --git a/README.md b/README.md
index 1ae225b1f3..b354a8f819 100644
--- a/README.md
+++ b/README.md
@@ -31,9 +31,11 @@ The projects are broadly divided into 3 lists: first, second and heavy.
Next, they are segregated further on the basis of the tests that we want to execute.
-Additionally, there are 2 profiles dedicated for JDK9 and above builds.
+Additionally, there are 2 profiles dedicated for JDK9 and above builds - **which require JDK 17**.
-Therefore, we have a total of 8 profiles:
+We also have a parents profile to build only parent modules.
+
+Therefore, we have a total of 9 profiles:
| Profile | Includes | Type of test enabled |
| -------------------------- | --------------------------- | -------------------- |
@@ -45,6 +47,7 @@ Therefore, we have a total of 8 profiles:
| integration-heavy | Heavy/long running projects | *IntegrationTest |
| default-jdk9-and-above | JDK9 and above projects | *UnitTest |
| integration-jdk9-and-above | JDK9 and above projects | *IntegrationTest |
+| parents | Set of parent modules | None |
Building the project
====================
@@ -71,6 +74,17 @@ Building a single module
====================
To build a specific module, run the command: `mvn clean install` in the module directory.
+It can happen that your module is part of a parent module e.g. `parent-boot-1`,`parent-spring-5` etc, then you will need to build the parent module first so that you can build your module.
+We have created a `parents` profile that you can use to build just the parent modules, just run the profile as:
+`mvn clean install -Pparents`
+
+
+Building modules from the root of the repository
+====================
+To build specific modules from the root of the repository, run the command: `mvn clean install --pl asm,atomikos -Pdefault-first` in the root directory.
+
+Here `asm` and `atomikos` are the modules that we want to build and `default-first` is the maven profile in which these modules are present.
+
Running a Spring Boot module
====================
diff --git a/akka-modules/akka-http/pom.xml b/akka-modules/akka-http/pom.xml
index 9372107fc9..3af7c492ca 100644
--- a/akka-modules/akka-http/pom.xml
+++ b/akka-modules/akka-http/pom.xml
@@ -36,6 +36,7 @@
+
10.0.11
2.5.11
diff --git a/akka-modules/spring-akka/pom.xml b/akka-modules/spring-akka/pom.xml
index 7451a40b86..2201181435 100644
--- a/akka-modules/spring-akka/pom.xml
+++ b/akka-modules/spring-akka/pom.xml
@@ -43,7 +43,7 @@
- 4.3.4.RELEASE
+ 5.3.25
2.4.14
diff --git a/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/AntColonyOptimizationLongRunningUnitTest.java b/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/AntColonyOptimizationLongRunningUnitTest.java
index 2ac7adc3aa..f828d148ba 100644
--- a/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/AntColonyOptimizationLongRunningUnitTest.java
+++ b/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/AntColonyOptimizationLongRunningUnitTest.java
@@ -1,22 +1,24 @@
package com.baeldung.algorithms;
-import org.junit.Assert;
-import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
-public class AntColonyOptimizationLongRunningUnitTest {
+class AntColonyOptimizationLongRunningUnitTest {
@Test
- public void testGenerateRandomMatrix() {
+ void testGenerateRandomMatrix() {
AntColonyOptimization antTSP = new AntColonyOptimization(5);
- Assert.assertNotNull(antTSP.generateRandomMatrix(5));
+ assertNotNull(antTSP.generateRandomMatrix(5));
}
@Test
- public void testStartAntOptimization() {
+ void testStartAntOptimization() {
AntColonyOptimization antTSP = new AntColonyOptimization(5);
- Assert.assertNotNull(antTSP.solve());
+ assertNotNull(antTSP.solve());
}
}
diff --git a/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java b/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java
index e819da4b36..a2f869e171 100644
--- a/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java
+++ b/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmLongRunningUnitTest.java
@@ -1,16 +1,19 @@
package com.baeldung.algorithms;
-import org.junit.Assert;
-import org.junit.Test;
+
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm;
-public class BinaryGeneticAlgorithmLongRunningUnitTest {
+class BinaryGeneticAlgorithmLongRunningUnitTest {
@Test
- public void testGA() {
+ void testGA() {
SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm();
- Assert.assertTrue(ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111"));
+ assertTrue(ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111"));
}
}
diff --git a/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/SimulatedAnnealingLongRunningUnitTest.java b/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/SimulatedAnnealingLongRunningUnitTest.java
index 2ce7d75e43..461e3e9128 100644
--- a/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/SimulatedAnnealingLongRunningUnitTest.java
+++ b/algorithms-modules/algorithms-genetic/src/test/java/com/baeldung/algorithms/SimulatedAnnealingLongRunningUnitTest.java
@@ -1,15 +1,17 @@
package com.baeldung.algorithms;
-import org.junit.Assert;
-import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing;
-public class SimulatedAnnealingLongRunningUnitTest {
+class SimulatedAnnealingLongRunningUnitTest {
@Test
- public void testSimulateAnnealing() {
- Assert.assertTrue(SimulatedAnnealing.simulateAnnealing(10, 1000, 0.9) > 0);
+ void testSimulateAnnealing() {
+ assertTrue(SimulatedAnnealing.simulateAnnealing(10, 1000, 0.9) > 0);
}
}
diff --git a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/HillClimbingAlgorithmUnitTest.java b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/HillClimbingAlgorithmUnitTest.java
index e817d195b3..4e8f927750 100644
--- a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/HillClimbingAlgorithmUnitTest.java
+++ b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/HillClimbingAlgorithmUnitTest.java
@@ -1,23 +1,25 @@
package com.baeldung.algorithms;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
import com.baeldung.algorithms.hillclimbing.HillClimbing;
import com.baeldung.algorithms.hillclimbing.State;
-import org.junit.Before;
-import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-public class HillClimbingAlgorithmUnitTest {
+class HillClimbingAlgorithmUnitTest {
private Stack initStack;
private Stack goalStack;
- @Before
+ @BeforeEach
public void initStacks() {
String blockArr[] = { "B", "C", "D", "A" };
String goalBlockArr[] = { "A", "B", "C", "D" };
@@ -30,7 +32,7 @@ public class HillClimbingAlgorithmUnitTest {
}
@Test
- public void givenInitAndGoalState_whenGetPathWithHillClimbing_thenPathFound() {
+ void givenInitAndGoalState_whenGetPathWithHillClimbing_thenPathFound() {
HillClimbing hillClimbing = new HillClimbing();
List path;
@@ -46,7 +48,7 @@ public class HillClimbingAlgorithmUnitTest {
}
@Test
- public void givenCurrentState_whenFindNextState_thenBetterHeuristics() {
+ void givenCurrentState_whenFindNextState_thenBetterHeuristics() {
HillClimbing hillClimbing = new HillClimbing();
List> initList = new ArrayList<>();
initList.add(initStack);
diff --git a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/RtFiniteStateMachineLongRunningUnitTest.java b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/RtFiniteStateMachineLongRunningUnitTest.java
index fddccfcd9f..f3e896541d 100644
--- a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/RtFiniteStateMachineLongRunningUnitTest.java
+++ b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/RtFiniteStateMachineLongRunningUnitTest.java
@@ -1,14 +1,16 @@
package com.baeldung.algorithms;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
import com.baeldung.algorithms.automata.*;
-import org.junit.Test;
-import static org.junit.Assert.assertTrue;
-
-public final class RtFiniteStateMachineLongRunningUnitTest {
+class RtFiniteStateMachineLongRunningUnitTest {
@Test
- public void acceptsSimplePair() {
+ void acceptsSimplePair() {
String json = "{\"key\":\"value\"}";
FiniteStateMachine machine = this.buildJsonStateMachine();
for (int i = 0; i < json.length(); i++) {
@@ -18,7 +20,7 @@ public final class RtFiniteStateMachineLongRunningUnitTest {
}
@Test
- public void acceptsMorePairs() {
+ void acceptsMorePairs() {
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
FiniteStateMachine machine = this.buildJsonStateMachine();
for (int i = 0; i < json.length(); i++) {
@@ -27,13 +29,15 @@ public final class RtFiniteStateMachineLongRunningUnitTest {
assertTrue(machine.canStop());
}
- @Test(expected = IllegalArgumentException.class)
- public void missingColon() {
+ @Test
+ void missingColon() {
String json = "{\"key\"\"value\"}";
- FiniteStateMachine machine = this.buildJsonStateMachine();
- for (int i = 0; i < json.length(); i++) {
- machine = machine.switchState(String.valueOf(json.charAt(i)));
- }
+ assertThrows(IllegalArgumentException.class, () -> {
+ FiniteStateMachine machine = this.buildJsonStateMachine();
+ for (int i = 0; i < json.length(); i++) {
+ machine = machine.switchState(String.valueOf(json.charAt(i)));
+ }
+ });
}
/**
diff --git a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java
index 6fbb7c163a..e877d9945a 100644
--- a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java
+++ b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java
@@ -1,54 +1,54 @@
package com.baeldung.algorithms.kthlargest;
-import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.api.Assertions.assertThat;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
-public class FindKthLargestUnitTest {
+class FindKthLargestUnitTest {
private FindKthLargest findKthLargest;
private Integer[] arr = { 3, 7, 1, 2, 8, 10, 4, 5, 6, 9 };
- @Before
+ @BeforeEach
public void setup() {
findKthLargest = new FindKthLargest();
}
@Test
- public void givenIntArray_whenFindKthLargestBySorting_thenGetResult() {
+ void givenIntArray_whenFindKthLargestBySorting_thenGetResult() {
int k = 3;
assertThat(findKthLargest.findKthLargestBySorting(arr, k)).isEqualTo(8);
}
@Test
- public void givenIntArray_whenFindKthLargestBySortingDesc_thenGetResult() {
+ void givenIntArray_whenFindKthLargestBySortingDesc_thenGetResult() {
int k = 3;
assertThat(findKthLargest.findKthLargestBySortingDesc(arr, k)).isEqualTo(8);
}
@Test
- public void givenIntArray_whenFindKthLargestByQuickSelect_thenGetResult() {
+ void givenIntArray_whenFindKthLargestByQuickSelect_thenGetResult() {
int k = 3;
int kthLargest = arr.length - k;
assertThat(findKthLargest.findKthElementByQuickSelect(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8);
}
@Test
- public void givenIntArray_whenFindKthElementByQuickSelectIterative_thenGetResult() {
+ void givenIntArray_whenFindKthElementByQuickSelectIterative_thenGetResult() {
int k = 3;
int kthLargest = arr.length - k;
assertThat(findKthLargest.findKthElementByQuickSelectWithIterativePartition(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8);
}
@Test
- public void givenIntArray_whenFindKthSmallestByQuickSelect_thenGetResult() {
+ void givenIntArray_whenFindKthSmallestByQuickSelect_thenGetResult() {
int k = 3;
assertThat(findKthLargest.findKthElementByQuickSelect(arr, 0, arr.length - 1, k - 1)).isEqualTo(3);
}
@Test
- public void givenIntArray_whenFindKthLargestByRandomizedQuickSelect_thenGetResult() {
+ void givenIntArray_whenFindKthLargestByRandomizedQuickSelect_thenGetResult() {
int k = 3;
int kthLargest = arr.length - k;
assertThat(findKthLargest.findKthElementByRandomizedQuickSelect(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8);
diff --git a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/minimax/MinimaxUnitTest.java b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/minimax/MinimaxUnitTest.java
index 59f0fcf053..e36e3651de 100644
--- a/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/minimax/MinimaxUnitTest.java
+++ b/algorithms-modules/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/minimax/MinimaxUnitTest.java
@@ -1,23 +1,24 @@
package com.baeldung.algorithms.minimax;
-import org.junit.Before;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.Assert.*;
-import com.baeldung.algorithms.minimax.MiniMax;
-import com.baeldung.algorithms.minimax.Tree;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
-public class MinimaxUnitTest {
+class MinimaxUnitTest {
private Tree gameTree;
private MiniMax miniMax;
- @Before
+ @BeforeEach
public void initMiniMaxUtility() {
miniMax = new MiniMax();
}
@Test
- public void givenMiniMax_whenConstructTree_thenNotNullTree() {
+ void givenMiniMax_whenConstructTree_thenNotNullTree() {
assertNull(gameTree);
miniMax.constructTree(6);
gameTree = miniMax.getTree();
@@ -25,7 +26,7 @@ public class MinimaxUnitTest {
}
@Test
- public void givenMiniMax_whenCheckWin_thenComputeOptimal() {
+ void givenMiniMax_whenCheckWin_thenComputeOptimal() {
miniMax.constructTree(6);
boolean result = miniMax.checkWin();
assertTrue(result);
diff --git a/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/DijkstraAlgorithmLongRunningUnitTest.java b/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/DijkstraAlgorithmLongRunningUnitTest.java
index bbc4d4f398..7e80d335be 100644
--- a/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/DijkstraAlgorithmLongRunningUnitTest.java
+++ b/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/DijkstraAlgorithmLongRunningUnitTest.java
@@ -1,6 +1,6 @@
package com.baeldung.algorithms;
-import org.junit.Test;
+
import com.baeldung.algorithms.ga.dijkstra.Dijkstra;
import com.baeldung.algorithms.ga.dijkstra.Graph;
@@ -11,7 +11,9 @@ import java.util.List;
import static org.junit.Assert.assertTrue;
-public class DijkstraAlgorithmLongRunningUnitTest {
+import org.junit.jupiter.api.Test;
+
+class DijkstraAlgorithmLongRunningUnitTest {
@Test
public void whenSPPSolved_thenCorrect() {
diff --git a/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/astar/underground/RouteFinderIntegrationTest.java b/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/astar/underground/RouteFinderIntegrationTest.java
index aba7f149da..ba492b33cf 100644
--- a/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/astar/underground/RouteFinderIntegrationTest.java
+++ b/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/astar/underground/RouteFinderIntegrationTest.java
@@ -1,5 +1,6 @@
package com.baeldung.algorithms.astar.underground;
+
import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
@@ -10,22 +11,22 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
import com.baeldung.algorithms.astar.Graph;
import com.baeldung.algorithms.astar.RouteFinder;
import lombok.extern.slf4j.Slf4j;
-import org.junit.Before;
-import org.junit.Test;
-
@Slf4j
-public class RouteFinderIntegrationTest {
+class RouteFinderIntegrationTest {
private Graph underground;
private RouteFinder routeFinder;
- @Before
+ @BeforeEach
public void setUp() throws Exception {
Set stations = new HashSet<>();
Map> connections = new HashMap<>();
@@ -641,7 +642,7 @@ public class RouteFinderIntegrationTest {
}
@Test
- public void findRoute() {
+ void findRoute() {
List route = routeFinder.findRoute(underground.getNode("74"), underground.getNode("7"));
assertThat(route).size().isPositive();
diff --git a/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/editdistance/EditDistanceDataProvider.java b/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/editdistance/EditDistanceDataProvider.java
deleted file mode 100644
index d11da61191..0000000000
--- a/algorithms-modules/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/editdistance/EditDistanceDataProvider.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.baeldung.algorithms.editdistance;
-
-import org.junit.runners.Parameterized.Parameters;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-public class EditDistanceDataProvider {
-
- @Parameters
- public static Collection
\ No newline at end of file
diff --git a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/AppConfig.java b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/AppConfig.java
index 058d19f045..fdd1af632c 100644
--- a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/AppConfig.java
+++ b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/AppConfig.java
@@ -1,7 +1,7 @@
package com.baeldung.sse.jaxrs;
-import javax.ws.rs.ApplicationPath;
-import javax.ws.rs.core.Application;
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Application;
@ApplicationPath("sse")
public class AppConfig extends Application {
diff --git a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/SseResource.java b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/SseResource.java
index 1f60168a1b..3e211f109b 100644
--- a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/SseResource.java
+++ b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/SseResource.java
@@ -1,15 +1,15 @@
package com.baeldung.sse.jaxrs;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-import javax.ws.rs.*;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.sse.OutboundSseEvent;
-import javax.ws.rs.sse.Sse;
-import javax.ws.rs.sse.SseBroadcaster;
-import javax.ws.rs.sse.SseEventSink;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.sse.OutboundSseEvent;
+import jakarta.ws.rs.sse.Sse;
+import jakarta.ws.rs.sse.SseBroadcaster;
+import jakarta.ws.rs.sse.SseEventSink;
@ApplicationScoped
@Path("stock")
diff --git a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/StockService.java b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/StockService.java
index 15818ead5d..721ef35678 100644
--- a/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/StockService.java
+++ b/apache-cxf-modules/sse-jaxrs/sse-jaxrs-server/src/main/java/com/baeldung/sse/jaxrs/StockService.java
@@ -1,11 +1,11 @@
package com.baeldung.sse.jaxrs;
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.context.Initialized;
-import javax.enterprise.event.Event;
-import javax.enterprise.event.Observes;
-import javax.inject.Inject;
-import javax.inject.Named;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.context.Initialized;
+import jakarta.enterprise.event.Event;
+import jakarta.enterprise.event.Observes;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
diff --git a/apache-httpclient-2/pom.xml b/apache-httpclient-2/pom.xml
index c5b8195472..91c4c718c0 100644
--- a/apache-httpclient-2/pom.xml
+++ b/apache-httpclient-2/pom.xml
@@ -98,7 +98,7 @@
3.22.0
5.11.2
4.5.8
- 5.1.3
+ 5.2
11
11
2.1.7.RELEASE
diff --git a/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java b/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java
index 404acb3098..265fa39816 100644
--- a/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java
+++ b/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java
@@ -1,46 +1,50 @@
package com.baeldung.httpclient.cookies;
-import org.apache.http.client.CookieStore;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.cookie.ClientCookie;
-import org.apache.http.cookie.Cookie;
-import org.apache.http.impl.client.BasicCookieStore;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.impl.cookie.BasicClientCookie;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.cookie.BasicCookieStore;
+import org.apache.hc.client5.http.cookie.Cookie;
+import org.apache.hc.client5.http.cookie.CookieStore;
+
+import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+
+import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import static org.junit.Assert.assertEquals;
-
-
-public class HttpClientGettingCookieValueUnitTest {
+class HttpClientGettingCookieValueUnitTest {
private static Logger log = LoggerFactory.getLogger(HttpClientGettingCookieValueUnitTest.class);
private static final String SAMPLE_URL = "http://www.baeldung.com/";
@Test
- public final void whenSettingCustomCookieOnTheRequest_thenGettingTheSameCookieFromTheResponse() throws IOException {
+ void whenSettingCustomCookieOnTheRequest_thenGettingTheSameCookieFromTheResponse() throws IOException {
+
HttpClientContext context = HttpClientContext.create();
context.setAttribute(HttpClientContext.COOKIE_STORE, createCustomCookieStore());
- try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
- try (CloseableHttpResponse response = httpClient.execute(new HttpGet(SAMPLE_URL), context)) {
- CookieStore cookieStore = context.getCookieStore();
- Cookie customCookie = cookieStore.getCookies()
- .stream()
- .peek(cookie -> log.info("cookie name:{}", cookie.getName()))
- .filter(cookie -> "custom_cookie".equals(cookie.getName()))
- .findFirst()
- .orElseThrow(IllegalStateException::new);
+ final HttpGet request = new HttpGet(SAMPLE_URL);
- assertEquals("test_value", customCookie.getValue());
- }
+ try (CloseableHttpClient client = HttpClientBuilder.create()
+ .build()) {
+ client.execute(request, context, new BasicHttpClientResponseHandler());
+ CookieStore cookieStore = context.getCookieStore();
+ Cookie customCookie = cookieStore.getCookies()
+ .stream()
+ .peek(cookie -> log.info("cookie name:{}", cookie.getName()))
+ .filter(cookie -> "custom_cookie".equals(cookie.getName()))
+ .findFirst()
+ .orElseThrow(IllegalStateException::new);
+
+ assertEquals("test_value", customCookie.getValue());
}
}
@@ -48,7 +52,7 @@ public class HttpClientGettingCookieValueUnitTest {
BasicCookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("custom_cookie", "test_value");
cookie.setDomain("baeldung.com");
- cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true");
+ cookie.setAttribute("domain", "true");
cookie.setPath("/");
cookieStore.addCookie(cookie);
return cookieStore;
diff --git a/apache-httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java b/apache-httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java
index 35b21789ef..9a79cbf491 100644
--- a/apache-httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java
+++ b/apache-httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClient5UnitTest.java
@@ -1,29 +1,27 @@
package com.baeldung.httpclient.readresponsebodystring;
import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
-import org.apache.hc.core5.http.HttpEntity;
-import org.apache.hc.core5.http.ParseException;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+
public class ApacheHttpClient5UnitTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public static final String DUMMY_URL = "https://postman-echo.com/get";
@Test
- public void whenUseApacheHttpClient_thenCorrect() throws IOException, ParseException {
+ public void whenUseApacheHttpClient_thenCorrect() throws IOException {
HttpGet request = new HttpGet(DUMMY_URL);
- try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) {
- HttpEntity entity = response.getEntity();
- logger.debug("Response -> {}", EntityUtils.toString(entity));
+ try (CloseableHttpClient client = HttpClients.createDefault()) {
+ String response = client.execute(request, new BasicHttpClientResponseHandler());
+ logger.debug("Response -> {}", response);
}
}
}
\ No newline at end of file
diff --git a/apache-httpclient/pom.xml b/apache-httpclient/pom.xml
index 26eb319ac0..c371d1fc06 100644
--- a/apache-httpclient/pom.xml
+++ b/apache-httpclient/pom.xml
@@ -54,6 +54,42 @@
+
+ org.apache.httpcomponents.core5
+ httpcore5
+ ${httpcore5.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+ org.apache.httpcomponents.client5
+ httpclient5-fluent
+ ${httpclient5-fluent.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ ${httpclient5.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
com.github.tomakehurst
wiremock
@@ -78,6 +114,10 @@
2.5.1
4.5.8
+
+ 5.2
+ 5.2
+ 5.2
-
\ No newline at end of file
+
diff --git a/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpClientMultipartLiveTest.java b/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpClientMultipartLiveTest.java
index 7576e49034..720049378b 100644
--- a/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpClientMultipartLiveTest.java
+++ b/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpClientMultipartLiveTest.java
@@ -1,19 +1,24 @@
package com.baeldung.httpclient;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.ContentType;
-import org.apache.http.entity.mime.HttpMultipartMode;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
-import org.apache.http.entity.mime.content.FileBody;
-import org.apache.http.entity.mime.content.StringBody;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.entity.mime.FileBody;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.entity.mime.StringBody;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpStatus;
import java.io.BufferedReader;
import java.io.File;
@@ -22,14 +27,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import com.baeldung.httpclient.handler.CustomHttpClientResponseHandler;
-public class HttpClientMultipartLiveTest {
+class HttpClientMultipartLiveTest {
// No longer available
// private static final String SERVER = "http://echo.200please.com";
@@ -38,41 +39,16 @@ public class HttpClientMultipartLiveTest {
private static final String TEXTFILENAME = "temp.txt";
private static final String IMAGEFILENAME = "image.jpg";
private static final String ZIPFILENAME = "zipFile.zip";
- private static final Logger LOGGER = Logger.getLogger("com.baeldung.httpclient.HttpClientMultipartLiveTest");
- private CloseableHttpClient client;
private HttpPost post;
private BufferedReader rd;
- private CloseableHttpResponse response;
- @Before
- public final void before() {
- client = HttpClientBuilder.create()
- .build();
+ @BeforeEach
+ public void before() {
post = new HttpPost(SERVER);
}
- @After
- public final void after() throws IllegalStateException, IOException {
- post.completed();
- try {
- client.close();
- } catch (final IOException e1) {
- LOGGER.log(Level.SEVERE, e1.getMessage(), e1);
- throw e1;
- }
- try {
- rd.close();
- } catch (final IOException e) {
- LOGGER.log(Level.SEVERE, e.getMessage(), e);
- throw e;
- }
- ResponseUtil.closeResponse(response);
- }
-
- // tests
-
@Test
- public final void givenFileandMultipleTextParts_whenUploadwithAddPart_thenNoExceptions() throws IOException {
+ void givenFileandMultipleTextParts_whenUploadwithAddPart_thenNoExceptions() throws IOException {
final URL url = Thread.currentThread()
.getContextClassLoader()
.getResource("uploads/" + TEXTFILENAME);
@@ -83,53 +59,61 @@ public class HttpClientMultipartLiveTest {
final StringBody stringBody2 = new StringBody("This is message 2", ContentType.MULTIPART_FORM_DATA);
//
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
+ builder.setMode(HttpMultipartMode.LEGACY);
builder.addPart("file", fileBody);
builder.addPart("text1", stringBody1);
builder.addPart("text2", stringBody2);
final HttpEntity entity = builder.build();
- //
- post.setEntity(entity);
- response = client.execute(post);
- final int statusCode = response.getStatusLine()
- .getStatusCode();
- final String responseString = getContent();
- final String contentTypeInHeader = getContentTypeHeader();
- assertThat(statusCode, equalTo(HttpStatus.SC_OK));
- // assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
- assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
- System.out.println(responseString);
- System.out.println("POST Content Type: " + contentTypeInHeader);
+ post.setEntity(entity);
+ try(CloseableHttpClient client = HttpClientBuilder.create()
+ .build();
+
+ CloseableHttpResponse response = (CloseableHttpResponse) client
+ .execute(post, new CustomHttpClientResponseHandler())){
+ final int statusCode = response.getCode();
+ final String responseString = getContent(response.getEntity());
+ final String contentTypeInHeader = getContentTypeHeader();
+
+ assertThat(statusCode, equalTo(HttpStatus.SC_OK));
+ assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
+ System.out.println(responseString);
+ System.out.println("POST Content Type: " + contentTypeInHeader);
+ }
}
@Test
- public final void givenFileandTextPart_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoExeption() throws IOException {
+ void givenFileandTextPart_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoExeption() throws IOException {
final URL url = Thread.currentThread()
.getContextClassLoader()
.getResource("uploads/" + TEXTFILENAME);
final File file = new File(url.getPath());
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
+ builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
final HttpEntity entity = builder.build();
post.setEntity(entity);
- response = client.execute(post);
- final int statusCode = response.getStatusLine()
- .getStatusCode();
- final String responseString = getContent();
- final String contentTypeInHeader = getContentTypeHeader();
- assertThat(statusCode, equalTo(HttpStatus.SC_OK));
- // assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
- assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
- System.out.println(responseString);
- System.out.println("POST Content Type: " + contentTypeInHeader);
+
+ try(CloseableHttpClient client = HttpClientBuilder.create()
+ .build();
+
+ CloseableHttpResponse response = (CloseableHttpResponse) client
+ .execute(post, new CustomHttpClientResponseHandler())){
+
+ final int statusCode = response.getCode();
+ final String responseString = getContent(response.getEntity());
+ final String contentTypeInHeader = getContentTypeHeader();
+ assertThat(statusCode, equalTo(HttpStatus.SC_OK));
+ assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
+ System.out.println(responseString);
+ System.out.println("POST Content Type: " + contentTypeInHeader);
+ }
}
@Test
- public final void givenFileAndInputStreamandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException {
+ void givenFileAndInputStreamandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException {
final URL url = Thread.currentThread()
.getContextClassLoader()
.getResource("uploads/" + ZIPFILENAME);
@@ -140,64 +124,75 @@ public class HttpClientMultipartLiveTest {
final File file = new File(url2.getPath());
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
+ builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME);
builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);
- response = client.execute(post);
- final int statusCode = response.getStatusLine()
- .getStatusCode();
- final String responseString = getContent();
- final String contentTypeInHeader = getContentTypeHeader();
- assertThat(statusCode, equalTo(HttpStatus.SC_OK));
- // assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
- assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
- System.out.println(responseString);
- System.out.println("POST Content Type: " + contentTypeInHeader);
- inputStream.close();
+
+ try(CloseableHttpClient client = HttpClientBuilder.create()
+ .build();
+
+ CloseableHttpResponse response = (CloseableHttpResponse) client
+ .execute(post, new CustomHttpClientResponseHandler())){
+
+ final int statusCode = response.getCode();
+ final String responseString = getContent(response.getEntity());
+ final String contentTypeInHeader = getContentTypeHeader();
+ assertThat(statusCode, equalTo(HttpStatus.SC_OK));
+ assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
+ System.out.println(responseString);
+ System.out.println("POST Content Type: " + contentTypeInHeader);
+ inputStream.close();
+ }
}
@Test
- public final void givenCharArrayandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException {
+ void givenCharArrayandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws IOException {
final String message = "This is a multipart post";
final byte[] bytes = "binary code".getBytes();
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
+ builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);
- response = client.execute(post);
- final int statusCode = response.getStatusLine()
- .getStatusCode();
- final String responseString = getContent();
- final String contentTypeInHeader = getContentTypeHeader();
- assertThat(statusCode, equalTo(HttpStatus.SC_OK));
- // assertTrue(responseString.contains("Content-Type: multipart/form-data;"));
- assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
- System.out.println(responseString);
- System.out.println("POST Content Type: " + contentTypeInHeader);
+
+ try(CloseableHttpClient client = HttpClientBuilder.create()
+ .build();
+
+ CloseableHttpResponse response = (CloseableHttpResponse) client
+ .execute(post, new CustomHttpClientResponseHandler())){
+
+ final int statusCode = response.getCode();
+ final String responseString = getContent(response.getEntity());
+ final String contentTypeInHeader = getContentTypeHeader();
+ assertThat(statusCode, equalTo(HttpStatus.SC_OK));
+ assertTrue(contentTypeInHeader.contains("Content-Type: multipart/form-data;"));
+ System.out.println(responseString);
+ System.out.println("POST Content Type: " + contentTypeInHeader);
+ }
+
}
// UTIL
- private String getContent() throws IOException {
- rd = new BufferedReader(new InputStreamReader(response.getEntity()
- .getContent()));
+ private String getContent(HttpEntity httpEntity) throws IOException {
+ rd = new BufferedReader(new InputStreamReader(httpEntity.getContent()));
String body = "";
StringBuilder content = new StringBuilder();
while ((body = rd.readLine()) != null) {
- content.append(body).append("\n");
+ content.append(body)
+ .append("\n");
}
- return content.toString().trim();
+ return content.toString()
+ .trim();
}
- private String getContentTypeHeader() throws IOException {
+ private String getContentTypeHeader() {
return post.getEntity()
- .getContentType()
- .toString();
+ .getContentType();
}
}
diff --git a/apache-httpclient/src/test/java/com/baeldung/httpclient/handler/CustomHttpClientResponseHandler.java b/apache-httpclient/src/test/java/com/baeldung/httpclient/handler/CustomHttpClientResponseHandler.java
new file mode 100644
index 0000000000..0559854b35
--- /dev/null
+++ b/apache-httpclient/src/test/java/com/baeldung/httpclient/handler/CustomHttpClientResponseHandler.java
@@ -0,0 +1,11 @@
+package com.baeldung.httpclient.handler;
+
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+
+public class CustomHttpClientResponseHandler implements HttpClientResponseHandler {
+ @Override
+ public ClassicHttpResponse handleResponse(ClassicHttpResponse response) {
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/apache-httpclient4/.gitignore b/apache-httpclient4/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/apache-httpclient4/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/apache-httpclient4/README.md b/apache-httpclient4/README.md
new file mode 100644
index 0000000000..25791d05e6
--- /dev/null
+++ b/apache-httpclient4/README.md
@@ -0,0 +1,14 @@
+## Apache HttpClient 4
+
+This module contains articles about Apache HttpClient 4.5
+
+### Relevant Articles
+
+- [Apache HttpClient with SSL](https://www.baeldung.com/httpclient-ssl)
+- [Apache HttpClient Timeout](https://www.baeldung.com/httpclient-timeout)
+- [Custom HTTP Header with the Apache HttpClient](https://www.baeldung.com/httpclient-custom-http-header)
+
+### Running the Tests
+To run the live tests, use the command: mvn clean install -Plive
+This will start an embedded Jetty server on port 8082 using the Cargo plugin configured in the pom.xml file,
+for the live Maven profile
diff --git a/apache-httpclient4/pom.xml b/apache-httpclient4/pom.xml
new file mode 100644
index 0000000000..6b449e3be1
--- /dev/null
+++ b/apache-httpclient4/pom.xml
@@ -0,0 +1,291 @@
+
+
+ 4.0.0
+ apache-httpclient4
+ 0.1-SNAPSHOT
+ apache-httpclient4
+ war
+
+
+ com.baeldung
+ parent-spring-5
+ 0.0.1-SNAPSHOT
+ ../parent-spring-5
+
+
+
+
+
+ org.springframework.security
+ spring-security-web
+ ${spring-security.version}
+
+
+ org.springframework.security
+ spring-security-config
+ ${spring-security.version}
+
+
+
+ org.springframework
+ spring-core
+ ${spring.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+
+
+ org.springframework
+ spring-jdbc
+ ${spring.version}
+
+
+ org.springframework
+ spring-beans
+ ${spring.version}
+
+
+ org.springframework
+ spring-aop
+ ${spring.version}
+
+
+ org.springframework
+ spring-tx
+ ${spring.version}
+
+
+ org.springframework
+ spring-expression
+ ${spring.version}
+
+
+ org.springframework
+ spring-web
+ ${spring.version}
+
+
+ org.springframework
+ spring-webmvc
+ ${spring.version}
+
+
+ org.springframework
+ spring-oxm
+ ${spring.version}
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+ org.apache.httpcomponents
+ httpcore
+ ${httpcore.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${httpclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.apache.httpcomponents
+ fluent-hc
+ ${httpclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.apache.httpcomponents
+ httpmime
+ ${httpclient.version}
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+ org.apache.httpcomponents
+ httpasyncclient
+ ${httpasyncclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ com.github.tomakehurst
+ wiremock
+ ${wiremock.version}
+ test
+
+
+
+ javax.servlet
+ javax.servlet-api
+ ${javax.servlet-api.version}
+ provided
+
+
+ javax.servlet
+ jstl
+ ${jstl.version}
+ runtime
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
+
+
+
+ httpclient-simple
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ ${maven-war-plugin.version}
+
+
+ org.codehaus.cargo
+ cargo-maven2-plugin
+ ${cargo-maven2-plugin.version}
+
+ true
+
+ jetty8x
+ embedded
+
+
+
+
+
+
+ 8082
+
+
+
+
+
+
+
+
+
+ live
+
+
+
+ org.codehaus.cargo
+ cargo-maven2-plugin
+
+
+ start-server
+ pre-integration-test
+
+ start
+
+
+
+ stop-server
+ post-integration-test
+
+ stop
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ none
+
+
+ **/*LiveTest.java
+
+
+ cargo
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.10
+ 4.1.5
+
+ 2.5.1
+ 4.4.16
+ 4.5.14
+
+ 1.6.1
+
+
+
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/java/com/baeldung/basic/MyBasicAuthenticationEntryPoint.java b/apache-httpclient4/src/main/java/com/baeldung/basic/MyBasicAuthenticationEntryPoint.java
new file mode 100644
index 0000000000..cafd8cfb7b
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/basic/MyBasicAuthenticationEntryPoint.java
@@ -0,0 +1,30 @@
+package com.baeldung.basic;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
+
+ @Override
+ public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException {
+ response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ final PrintWriter writer = response.getWriter();
+ writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage());
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ setRealmName("Baeldung");
+ super.afterPropertiesSet();
+ }
+
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java b/apache-httpclient4/src/main/java/com/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java
new file mode 100644
index 0000000000..81f82a2c1c
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java
@@ -0,0 +1,39 @@
+package com.baeldung.client;
+
+import java.net.URI;
+
+import org.apache.http.HttpHost;
+import org.apache.http.client.AuthCache;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+
+public class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory {
+
+ HttpHost host;
+
+ public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) {
+ super();
+ this.host = host;
+ }
+
+ protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
+ return createHttpContext();
+ }
+
+ private HttpContext createHttpContext() {
+
+ AuthCache authCache = new BasicAuthCache();
+
+ BasicScheme basicAuth = new BasicScheme();
+ authCache.put(host, basicAuth);
+
+ BasicHttpContext localcontext = new BasicHttpContext();
+ localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
+ return localcontext;
+ }
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/java/com/baeldung/client/RestTemplateFactory.java b/apache-httpclient4/src/main/java/com/baeldung/client/RestTemplateFactory.java
new file mode 100644
index 0000000000..aac4f8cebd
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/client/RestTemplateFactory.java
@@ -0,0 +1,44 @@
+package com.baeldung.client;
+
+import org.apache.http.HttpHost;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.support.BasicAuthenticationInterceptor;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class RestTemplateFactory implements FactoryBean, InitializingBean {
+ private RestTemplate restTemplate;
+
+ public RestTemplateFactory() {
+ super();
+ }
+
+ // API
+
+ @Override
+ public RestTemplate getObject() {
+ return restTemplate;
+ }
+
+ @Override
+ public Class getObjectType() {
+ return RestTemplate.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ HttpHost host = new HttpHost("localhost", 8082, "http");
+ final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host);
+ restTemplate = new RestTemplate(requestFactory);
+ restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("user1", "user1Pass"));
+ }
+
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/java/com/baeldung/client/spring/ClientConfig.java b/apache-httpclient4/src/main/java/com/baeldung/client/spring/ClientConfig.java
new file mode 100644
index 0000000000..03994b55a5
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/client/spring/ClientConfig.java
@@ -0,0 +1,16 @@
+package com.baeldung.client.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan("com.baeldung.client")
+public class ClientConfig {
+
+ public ClientConfig() {
+ super();
+ }
+
+ // beans
+
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/java/com/baeldung/filter/CustomFilter.java b/apache-httpclient4/src/main/java/com/baeldung/filter/CustomFilter.java
new file mode 100644
index 0000000000..6bb12610fa
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/filter/CustomFilter.java
@@ -0,0 +1,18 @@
+package com.baeldung.filter;
+
+import org.springframework.web.filter.GenericFilterBean;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+public class CustomFilter extends GenericFilterBean {
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ chain.doFilter(request, response);
+ }
+
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/filter/CustomWebSecurityConfigurerAdapter.java b/apache-httpclient4/src/main/java/com/baeldung/filter/CustomWebSecurityConfigurerAdapter.java
new file mode 100644
index 0000000000..fb597e46c8
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/filter/CustomWebSecurityConfigurerAdapter.java
@@ -0,0 +1,49 @@
+package com.baeldung.filter;
+
+import com.baeldung.security.RestAuthenticationEntryPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+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.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+@Configuration
+@EnableWebSecurity
+public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+
+ @Autowired private RestAuthenticationEntryPoint authenticationEntryPoint;
+
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ auth
+ .inMemoryAuthentication()
+ .withUser("user1")
+ .password(passwordEncoder().encode("user1Pass"))
+ .authorities("ROLE_USER");
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ .antMatchers("/securityNone")
+ .permitAll()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .httpBasic()
+ .authenticationEntryPoint(authenticationEntryPoint);
+
+ http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class);
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java b/apache-httpclient4/src/main/java/com/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java
new file mode 100644
index 0000000000..7dc53e3e1e
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java
@@ -0,0 +1,48 @@
+package com.baeldung.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
+import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
+import org.springframework.security.web.savedrequest.RequestCache;
+import org.springframework.security.web.savedrequest.SavedRequest;
+import org.springframework.util.StringUtils;
+
+public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
+
+ private RequestCache requestCache = new HttpSessionRequestCache();
+
+ @Override
+ public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws ServletException, IOException {
+ final SavedRequest savedRequest = requestCache.getRequest(request, response);
+
+ if (savedRequest == null) {
+ super.onAuthenticationSuccess(request, response, authentication);
+
+ return;
+ }
+ final String targetUrlParameter = getTargetUrlParameter();
+ if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
+ requestCache.removeRequest(request, response);
+ super.onAuthenticationSuccess(request, response, authentication);
+
+ return;
+ }
+
+ clearAuthenticationAttributes(request);
+
+ // Use the DefaultSavedRequest URL
+ // final String targetUrl = savedRequest.getRedirectUrl();
+ // logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
+ // getRedirectStrategy().sendRedirect(request, response, targetUrl);
+ }
+
+ public void setRequestCache(final RequestCache requestCache) {
+ this.requestCache = requestCache;
+ }
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/security/RestAuthenticationEntryPoint.java b/apache-httpclient4/src/main/java/com/baeldung/security/RestAuthenticationEntryPoint.java
new file mode 100644
index 0000000000..1ae89adb89
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/security/RestAuthenticationEntryPoint.java
@@ -0,0 +1,23 @@
+package com.baeldung.security;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+/**
+ * The Entry Point will not redirect to any sort of Login - it will return the 401
+ */
+@Component
+public final class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException {
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
+ }
+
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/java/com/baeldung/spring/SecSecurityConfig.java b/apache-httpclient4/src/main/java/com/baeldung/spring/SecSecurityConfig.java
new file mode 100644
index 0000000000..4ba9d47f8d
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/spring/SecSecurityConfig.java
@@ -0,0 +1,16 @@
+package com.baeldung.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+
+@Configuration
+@ImportResource({ "classpath:webSecurityConfig.xml" })
+@ComponentScan("com.baeldung.security")
+public class SecSecurityConfig {
+
+ public SecSecurityConfig() {
+ super();
+ }
+
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/spring/WebConfig.java b/apache-httpclient4/src/main/java/com/baeldung/spring/WebConfig.java
new file mode 100644
index 0000000000..8d5c1dc7f1
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/spring/WebConfig.java
@@ -0,0 +1,30 @@
+package com.baeldung.spring;
+
+import java.util.List;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@EnableWebMvc
+@ComponentScan("com.baeldung.web")
+public class WebConfig implements WebMvcConfigurer {
+
+ public WebConfig() {
+ super();
+ }
+
+ // beans
+
+ @Override
+ public void configureMessageConverters(final List> converters) {
+ converters.add(new MappingJackson2HttpMessageConverter());
+ }
+
+ //
+
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/java/com/baeldung/web/controller/BarController.java b/apache-httpclient4/src/main/java/com/baeldung/web/controller/BarController.java
new file mode 100644
index 0000000000..02e6af03af
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/web/controller/BarController.java
@@ -0,0 +1,31 @@
+package com.baeldung.web.controller;
+
+import com.baeldung.web.dto.Bar;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping(value = "/bars")
+public class BarController {
+
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
+ public BarController() {
+ super();
+ }
+
+ // API
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+ @ResponseBody
+ public Bar findOne(@PathVariable("id") final Long id) {
+ return new Bar();
+ }
+
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/web/controller/FooController.java b/apache-httpclient4/src/main/java/com/baeldung/web/controller/FooController.java
new file mode 100644
index 0000000000..461a5e351a
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/web/controller/FooController.java
@@ -0,0 +1,33 @@
+package com.baeldung.web.controller;
+
+import com.baeldung.web.dto.Foo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping(value = "/foos")
+public class FooController {
+
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
+ public FooController() {
+ super();
+ }
+
+ // API
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+ @ResponseBody
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public Foo findOne(@PathVariable("id") final Long id) {
+ return new Foo();
+ }
+
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/web/dto/Bar.java b/apache-httpclient4/src/main/java/com/baeldung/web/dto/Bar.java
new file mode 100644
index 0000000000..eb139b0ec1
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/web/dto/Bar.java
@@ -0,0 +1,14 @@
+package com.baeldung.web.dto;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Bar implements Serializable {
+
+ public Bar() {
+ super();
+ }
+
+}
diff --git a/apache-httpclient4/src/main/java/com/baeldung/web/dto/Foo.java b/apache-httpclient4/src/main/java/com/baeldung/web/dto/Foo.java
new file mode 100644
index 0000000000..23cfab132d
--- /dev/null
+++ b/apache-httpclient4/src/main/java/com/baeldung/web/dto/Foo.java
@@ -0,0 +1,14 @@
+package com.baeldung.web.dto;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Foo implements Serializable {
+
+ public Foo() {
+ super();
+ }
+
+}
diff --git a/apache-httpclient4/src/main/resources/logback.xml b/apache-httpclient4/src/main/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/apache-httpclient4/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/resources/webSecurityConfig.xml b/apache-httpclient4/src/main/resources/webSecurityConfig.xml
new file mode 100644
index 0000000000..2ff9a1de15
--- /dev/null
+++ b/apache-httpclient4/src/main/resources/webSecurityConfig.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/webapp/WEB-INF/api-servlet.xml b/apache-httpclient4/src/main/webapp/WEB-INF/api-servlet.xml
new file mode 100644
index 0000000000..1dbff70b83
--- /dev/null
+++ b/apache-httpclient4/src/main/webapp/WEB-INF/api-servlet.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/apache-httpclient4/src/main/webapp/WEB-INF/web.xml b/apache-httpclient4/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..4b2dd54266
--- /dev/null
+++ b/apache-httpclient4/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,43 @@
+
+
+
+ Spring Security Custom Application
+
+
+
+ contextClass
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+ contextConfigLocation
+ com.baeldung.spring
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ api
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ api
+ /api/*
+
+
+
+
+ springSecurityFilterChain
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+ springSecurityFilterChain
+ /*
+
+
+
\ No newline at end of file
diff --git a/apache-httpclient4/src/test/java/com/baeldung/client/ClientLiveTest.java b/apache-httpclient4/src/test/java/com/baeldung/client/ClientLiveTest.java
new file mode 100644
index 0000000000..2785bc5d08
--- /dev/null
+++ b/apache-httpclient4/src/test/java/com/baeldung/client/ClientLiveTest.java
@@ -0,0 +1,99 @@
+package com.baeldung.client;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContexts;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+
+class ClientLiveTest {
+
+ final String urlOverHttps = "http://localhost:8082/httpclient-simple/api/bars/1";
+
+ @Test
+ void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk_2() throws GeneralSecurityException {
+
+ final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
+ final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+ final Registry socketFactoryRegistry = RegistryBuilder. create()
+ .register("https", sslsf)
+ .register("http", new PlainConnectionSocketFactory())
+ .build();
+
+ final BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry);
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .setConnectionManager(connectionManager)
+ .build();
+
+ final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+ final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class);
+ assertThat(response.getStatusCode().value(), equalTo(200));
+ }
+
+ @Test
+ void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenCorrect() throws IOException {
+ final HttpGet getMethod = new HttpGet(urlOverHttps);
+
+ try (final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLHostnameVerifier(new NoopHostnameVerifier())
+ .build()) {
+
+ final HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine()
+ .getStatusCode(), equalTo(200));
+ }
+ }
+
+ @Test
+ void givenAcceptingAllCertificates_whenUsingRestTemplate_thenCorrect() {
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLHostnameVerifier(new NoopHostnameVerifier())
+ .build();
+ final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
+ requestFactory.setHttpClient(httpClient);
+
+ final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class);
+ assertThat(response.getStatusCode().value(), equalTo(200));
+ }
+
+ @Test
+ void whenHttpsUrlIsConsumed_thenException() {
+ String urlOverHttps = "https://localhost:8082/httpclient-simple";
+ HttpGet getMethod = new HttpGet(urlOverHttps);
+
+ assertThrows(SSLPeerUnverifiedException.class, () -> {
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine()
+ .getStatusCode(), equalTo(200));
+ });
+ }
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/test/java/com/baeldung/client/RestClientV4LiveManualTest.java b/apache-httpclient4/src/test/java/com/baeldung/client/RestClientV4LiveManualTest.java
new file mode 100644
index 0000000000..c336e6a068
--- /dev/null
+++ b/apache-httpclient4/src/test/java/com/baeldung/client/RestClientV4LiveManualTest.java
@@ -0,0 +1,92 @@
+package com.baeldung.client;
+
+import static org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import javax.net.ssl.SSLContext;
+
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContexts;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * This test requires a localhost server over HTTPS
+ * It should only be manually run, not part of the automated build
+ * */
+public class RestClientV4LiveManualTest {
+
+ final String urlOverHttps = "http://localhost:8082/httpclient-simple/api/bars/1";
+
+ @Test
+ void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk_2() throws GeneralSecurityException {
+
+ final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
+ final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+ final Registry socketFactoryRegistry = RegistryBuilder. create()
+ .register("https", sslsf)
+ .register("http", new PlainConnectionSocketFactory())
+ .build();
+
+ final BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry);
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .setConnectionManager(connectionManager)
+ .build();
+
+ final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+ final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class);
+ assertThat(response.getStatusCode().value(), equalTo(200));
+ }
+
+ @Test
+ void givenAcceptingAllCertificatesUsing4_4_whenHttpsUrlIsConsumed_thenCorrect() throws IOException {
+ final CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
+
+ final HttpGet getMethod = new HttpGet(urlOverHttps);
+ final HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
+ }
+
+ @Test
+ void givenAcceptingAllCertificatesUsing4_4_whenUsingRestTemplate_thenCorrect(){
+ final CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
+ final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
+ requestFactory.setHttpClient(httpClient);
+
+ final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class);
+ assertThat(response.getStatusCode().value(), equalTo(200));
+ }
+
+ @Test
+ public void whenHttpsUrlIsConsumed_thenException() throws ClientProtocolException, IOException {
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ String urlOverHttps = "https://localhost:8082/httpclient-simple";
+ HttpGet getMethod = new HttpGet(urlOverHttps);
+ HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
+ }
+}
diff --git a/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpClientHeaderV4LiveTest.java b/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpClientHeaderV4LiveTest.java
new file mode 100644
index 0000000000..eef813b3ff
--- /dev/null
+++ b/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpClientHeaderV4LiveTest.java
@@ -0,0 +1,24 @@
+package com.baeldung.httpclient;
+
+import java.io.IOException;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.junit.jupiter.api.Test;
+
+class HttpClientHeaderV4LiveTest {
+
+ private static final String SAMPLE_URL = "http://www.github.com";
+
+ @Test
+ void givenRequestBuildWithBuilder_whenRequestHasCustomContentType_thenCorrect() throws IOException {
+ HttpClient client = HttpClients.custom().build();
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(SAMPLE_URL)
+ .setHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+ .build();
+ client.execute(request);
+ }
+}
\ No newline at end of file
diff --git a/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpClientTimeoutV4LiveTest.java b/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpClientTimeoutV4LiveTest.java
new file mode 100644
index 0000000000..4d4dd7be15
--- /dev/null
+++ b/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpClientTimeoutV4LiveTest.java
@@ -0,0 +1,116 @@
+package com.baeldung.httpclient;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.config.SocketConfig;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+class HttpClientTimeoutV4LiveTest {
+
+ private CloseableHttpResponse response;
+
+ @AfterEach
+ public final void after() throws IllegalStateException, IOException {
+ ResponseUtil.closeResponse(response);
+ }
+
+
+ @Test
+ void givenUsingNewApi_whenSettingTimeoutViaRequestConfig_thenCorrect() throws IOException {
+ final int timeout = 2;
+ final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
+ final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
+ final HttpGet request = new HttpGet("http://www.github.com");
+
+ response = client.execute(request);
+
+ assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
+ }
+
+ @Test
+ void givenUsingNewApi_whenSettingTimeoutViaSocketConfig_thenCorrect() throws IOException {
+ final int timeout = 2;
+
+ final SocketConfig config = SocketConfig.custom().setSoTimeout(timeout * 1000).build();
+ final CloseableHttpClient client = HttpClientBuilder.create().setDefaultSocketConfig(config).build();
+
+ final HttpGet request = new HttpGet("http://www.github.com");
+
+ response = client.execute(request);
+
+ assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
+ }
+
+ @Test
+ void givenUsingNewApi_whenSettingTimeoutViaHighLevelApi_thenCorrect() throws IOException {
+ final int timeout = 5;
+
+ final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
+ final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
+
+ final HttpGet request = new HttpGet("http://www.github.com");
+
+ response = client.execute(request);
+
+ assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
+ }
+
+ /**
+ * This simulates a timeout against a domain with multiple routes/IPs to it (not a single raw IP)
+ */
+ @Test
+ @Disabled
+ void givenTimeoutIsConfigured_whenTimingOut_thenTimeoutException() throws IOException {
+ final int timeout = 3;
+
+ final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
+ final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
+
+ final HttpGet request = new HttpGet("http://www.google.com:81");
+
+ assertThrows(ConnectTimeoutException.class, () -> {
+ client.execute(request);
+ });
+
+ }
+
+ @Test
+ void whenSecuredRestApiIsConsumed_then200OK() throws IOException {
+ CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+
+ int timeout = 20; // seconds
+ RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout * 1000)
+ .setConnectTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
+ HttpGet getMethod = new HttpGet("http://localhost:8082/httpclient-simple/api/bars/1");
+ getMethod.setConfig(requestConfig);
+
+ int hardTimeout = 5; // seconds
+ TimerTask task = new TimerTask() {
+ @Override
+ public void run() {
+ getMethod.abort();
+ }
+ };
+ new Timer(true).schedule(task, hardTimeout * 1000);
+
+ HttpResponse response = httpClient.execute(getMethod);
+ System.out.println("HTTP Status of response: " + response.getStatusLine().getStatusCode());
+ }
+
+}
diff --git a/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpsClientV4SslLiveTest.java b/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpsClientV4SslLiveTest.java
new file mode 100644
index 0000000000..6c7bcf9b08
--- /dev/null
+++ b/apache-httpclient4/src/test/java/com/baeldung/httpclient/HttpsClientV4SslLiveTest.java
@@ -0,0 +1,111 @@
+package com.baeldung.httpclient;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
+import org.junit.jupiter.api.Test;
+
+class HttpsClientV4SslLiveTest {
+
+
+ // "https://localhost:8443/spring-security-rest-basic-auth/api/bars/1" // local
+ // "https://mms.nw.ru/" // hosted
+ private static final String HOST_WITH_SSL = "https://mms.nw.ru/";
+
+ // tests
+
+ @Test
+ void whenHttpsUrlIsConsumed_thenException() {
+ final HttpGet getMethod = new HttpGet(HOST_WITH_SSL);
+
+ assertThrows(SSLHandshakeException.class, () -> {
+ final CloseableHttpClient httpClient = HttpClientBuilder
+ .create()
+ .build();
+ final HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine()
+ .getStatusCode(), equalTo(200));
+ });
+ }
+
+
+ @Test
+ void whenAcceptingAllCertificates_thenCanConsumeHttpsUriWithSelfSignedCertificate() throws IOException, GeneralSecurityException {
+ final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
+ final SSLContext sslContext = SSLContexts.custom()
+ .loadTrustMaterial(null, acceptingTrustStrategy)
+ .build();
+
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .build();
+
+ final HttpGet getMethod = new HttpGet(HOST_WITH_SSL);
+ final HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine()
+ .getStatusCode(), equalTo(200));
+
+ httpClient.close();
+ }
+
+ @Test
+ void using_builder_whenAcceptingAllCertificates_thenCanConsumeHttpsUriWithSelfSignedCertificate() throws IOException, GeneralSecurityException {
+ final SSLContext sslContext = new SSLContextBuilder()
+ .loadTrustMaterial(null, new TrustSelfSignedStrategy())
+ .build();
+ final NoopHostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
+
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLHostnameVerifier(hostnameVerifier)
+ .setSSLSocketFactory(sslsf)
+ .build();
+
+ final HttpGet getMethod = new HttpGet(HOST_WITH_SSL);
+ final HttpResponse response = httpClient.execute(getMethod);
+ assertThat(response.getStatusLine()
+ .getStatusCode(), equalTo(200));
+ httpClient.close();
+
+ }
+
+ @Test
+ void givenIgnoringCertificates_whenHttpsUrlIsConsumed_thenCorrect() throws Exception {
+ final SSLContext sslContext = new SSLContextBuilder()
+ .loadTrustMaterial(null, (certificate, authType) -> true)
+ .build();
+
+ final CloseableHttpClient client = HttpClients.custom()
+ .setSSLContext(sslContext)
+ .setSSLHostnameVerifier(new NoopHostnameVerifier())
+ .build();
+ final HttpGet httpGet = new HttpGet(HOST_WITH_SSL);
+ httpGet.setHeader("Accept", "application/xml");
+
+ final HttpResponse response = client.execute(httpGet);
+ assertThat(response.getStatusLine()
+ .getStatusCode(), equalTo(200));
+ }
+
+}
\ No newline at end of file
diff --git a/httpclient-simple/src/test/java/com/baeldung/httpclient/ResponseUtil.java b/apache-httpclient4/src/test/java/com/baeldung/httpclient/ResponseUtil.java
similarity index 100%
rename from httpclient-simple/src/test/java/com/baeldung/httpclient/ResponseUtil.java
rename to apache-httpclient4/src/test/java/com/baeldung/httpclient/ResponseUtil.java
diff --git a/apache-httpclient4/src/test/resources/.gitignore b/apache-httpclient4/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/apache-httpclient4/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/apache-httpclient4/src/test/resources/test.in b/apache-httpclient4/src/test/resources/test.in
new file mode 100644
index 0000000000..95d09f2b10
--- /dev/null
+++ b/apache-httpclient4/src/test/resources/test.in
@@ -0,0 +1 @@
+hello world
\ No newline at end of file
diff --git a/apache-libraries/pom.xml b/apache-libraries/pom.xml
index 3d78869865..c1def03bee 100644
--- a/apache-libraries/pom.xml
+++ b/apache-libraries/pom.xml
@@ -118,11 +118,6 @@
curator-recipes
${curator.version}
-
- org.apache.zookeeper
- zookeeper
- ${zookeeper.version}
-
com.fasterxml.jackson.core
jackson-core
@@ -191,17 +186,15 @@
- 1.8
- 1.8
1.8.2
- 2.19.0
- 1.1.2
- 1.1.0.Final
- 1.2.0
+ 2.45.0
+ 2.0.6
+ 2.0.1.Final
+ 1.2.15
3.10.0
- 1.2.1
- 1.2.1
- 1.2.1
+ 1.2.15
+ 1.2.15
+ 1.2.15
1.8.4
2.1.1-incubating
3.4.11
diff --git a/apache-libraries/src/main/java/com/baeldung/avro/util/serealization/AvroDeSerealizer.java b/apache-libraries/src/main/java/com/baeldung/avro/util/serialization/AvroDeSerializer.java
similarity index 84%
rename from apache-libraries/src/main/java/com/baeldung/avro/util/serealization/AvroDeSerealizer.java
rename to apache-libraries/src/main/java/com/baeldung/avro/util/serialization/AvroDeSerializer.java
index 7d30c3d1ee..cf4c360ba4 100644
--- a/apache-libraries/src/main/java/com/baeldung/avro/util/serealization/AvroDeSerealizer.java
+++ b/apache-libraries/src/main/java/com/baeldung/avro/util/serialization/AvroDeSerializer.java
@@ -1,4 +1,4 @@
-package com.baeldung.avro.util.serealization;
+package com.baeldung.avro.util.serialization;
import com.baeldung.avro.util.model.AvroHttpRequest;
import org.apache.avro.io.DatumReader;
@@ -10,11 +10,11 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
-public class AvroDeSerealizer {
+public class AvroDeSerializer {
- private static Logger logger = LoggerFactory.getLogger(AvroDeSerealizer.class);
+ private static Logger logger = LoggerFactory.getLogger(AvroDeSerializer.class);
- public AvroHttpRequest deSerealizeAvroHttpRequestJSON(byte[] data) {
+ public AvroHttpRequest deSerializeAvroHttpRequestJSON(byte[] data) {
DatumReader reader = new SpecificDatumReader<>(AvroHttpRequest.class);
Decoder decoder = null;
try {
@@ -27,7 +27,7 @@ public class AvroDeSerealizer {
return null;
}
- public AvroHttpRequest deSerealizeAvroHttpRequestBinary(byte[] data) {
+ public AvroHttpRequest deSerializeAvroHttpRequestBinary(byte[] data) {
DatumReader employeeReader = new SpecificDatumReader<>(AvroHttpRequest.class);
Decoder decoder = DecoderFactory.get()
.binaryDecoder(data, null);
diff --git a/apache-libraries/src/main/java/com/baeldung/avro/util/serealization/AvroSerealizer.java b/apache-libraries/src/main/java/com/baeldung/avro/util/serialization/AvroSerializer.java
similarity index 87%
rename from apache-libraries/src/main/java/com/baeldung/avro/util/serealization/AvroSerealizer.java
rename to apache-libraries/src/main/java/com/baeldung/avro/util/serialization/AvroSerializer.java
index 767b688dea..6d39060ec8 100644
--- a/apache-libraries/src/main/java/com/baeldung/avro/util/serealization/AvroSerealizer.java
+++ b/apache-libraries/src/main/java/com/baeldung/avro/util/serialization/AvroSerializer.java
@@ -1,4 +1,4 @@
-package com.baeldung.avro.util.serealization;
+package com.baeldung.avro.util.serialization;
import com.baeldung.avro.util.model.AvroHttpRequest;
import org.apache.avro.io.*;
@@ -9,11 +9,11 @@ import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-public class AvroSerealizer {
+public class AvroSerializer {
- private static final Logger logger = LoggerFactory.getLogger(AvroSerealizer.class);
+ private static final Logger logger = LoggerFactory.getLogger(AvroSerializer.class);
- public byte[] serealizeAvroHttpRequestJSON(AvroHttpRequest request) {
+ public byte[] serializeAvroHttpRequestJSON(AvroHttpRequest request) {
DatumWriter writer = new SpecificDatumWriter<>(AvroHttpRequest.class);
byte[] data = new byte[0];
ByteArrayOutputStream stream = new ByteArrayOutputStream();
@@ -30,7 +30,7 @@ public class AvroSerealizer {
return data;
}
- public byte[] serealizeAvroHttpRequestBinary(AvroHttpRequest request) {
+ public byte[] serializeAvroHttpRequestBinary(AvroHttpRequest request) {
DatumWriter writer = new SpecificDatumWriter<>(AvroHttpRequest.class);
byte[] data = new byte[0];
ByteArrayOutputStream stream = new ByteArrayOutputStream();
diff --git a/apache-libraries/src/test/java/com/baeldung/avro/util/serealization/AvroSerealizerDeSerealizerIntegrationTest.java b/apache-libraries/src/test/java/com/baeldung/avro/util/serialization/AvroSerializerDeSerializerIntegrationTest.java
similarity index 75%
rename from apache-libraries/src/test/java/com/baeldung/avro/util/serealization/AvroSerealizerDeSerealizerIntegrationTest.java
rename to apache-libraries/src/test/java/com/baeldung/avro/util/serialization/AvroSerializerDeSerializerIntegrationTest.java
index 3d413e1939..964eeb6d87 100644
--- a/apache-libraries/src/test/java/com/baeldung/avro/util/serealization/AvroSerealizerDeSerealizerIntegrationTest.java
+++ b/apache-libraries/src/test/java/com/baeldung/avro/util/serialization/AvroSerializerDeSerializerIntegrationTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.avro.util.serealization;
+package com.baeldung.avro.util.serialization;
import com.baeldung.avro.util.model.Active;
import com.baeldung.avro.util.model.AvroHttpRequest;
@@ -13,16 +13,16 @@ import java.util.Objects;
import static org.junit.Assert.*;
-public class AvroSerealizerDeSerealizerIntegrationTest {
+public class AvroSerializerDeSerializerIntegrationTest {
- AvroSerealizer serealizer;
- AvroDeSerealizer deSerealizer;
+ AvroSerializer serializer;
+ AvroDeSerializer deserializer;
AvroHttpRequest request;
@Before
public void setUp() throws Exception {
- serealizer = new AvroSerealizer();
- deSerealizer = new AvroDeSerealizer();
+ serializer = new AvroSerializer();
+ deserializer = new AvroDeSerializer();
ClientIdentifier clientIdentifier = ClientIdentifier.newBuilder()
.setHostName("localhost")
@@ -49,22 +49,22 @@ public class AvroSerealizerDeSerealizerIntegrationTest {
@Test
public void WhenSerializedUsingJSONEncoder_thenObjectGetsSerialized() {
- byte[] data = serealizer.serealizeAvroHttpRequestJSON(request);
+ byte[] data = serializer.serializeAvroHttpRequestJSON(request);
assertTrue(Objects.nonNull(data));
assertTrue(data.length > 0);
}
@Test
public void WhenSerializedUsingBinaryEncoder_thenObjectGetsSerialized() {
- byte[] data = serealizer.serealizeAvroHttpRequestBinary(request);
+ byte[] data = serializer.serializeAvroHttpRequestBinary(request);
assertTrue(Objects.nonNull(data));
assertTrue(data.length > 0);
}
@Test
public void WhenDeserializeUsingJSONDecoder_thenActualAndExpectedObjectsAreEqual() {
- byte[] data = serealizer.serealizeAvroHttpRequestJSON(request);
- AvroHttpRequest actualRequest = deSerealizer.deSerealizeAvroHttpRequestJSON(data);
+ byte[] data = serializer.serializeAvroHttpRequestJSON(request);
+ AvroHttpRequest actualRequest = deserializer.deSerializeAvroHttpRequestJSON(data);
assertEquals(actualRequest, request);
assertTrue(actualRequest.getRequestTime()
.equals(request.getRequestTime()));
@@ -72,12 +72,12 @@ public class AvroSerealizerDeSerealizerIntegrationTest {
@Test
public void WhenDeserializeUsingBinaryecoder_thenActualAndExpectedObjectsAreEqual() {
- byte[] data = serealizer.serealizeAvroHttpRequestBinary(request);
- AvroHttpRequest actualRequest = deSerealizer.deSerealizeAvroHttpRequestBinary(data);
+ byte[] data = serializer.serializeAvroHttpRequestBinary(request);
+ AvroHttpRequest actualRequest = deserializer.deSerializeAvroHttpRequestBinary(data);
assertEquals(actualRequest, request);
assertTrue(actualRequest.getRequestTime()
.equals(request.getRequestTime()));
}
-
+
}
diff --git a/apache-poi-2/README.md b/apache-poi-2/README.md
index 2c0deec575..e2b5160109 100644
--- a/apache-poi-2/README.md
+++ b/apache-poi-2/README.md
@@ -11,4 +11,5 @@ This module contains articles about Apache POI.
- [Creating a MS PowerPoint Presentation in Java](https://www.baeldung.com/apache-poi-slideshow)
- [Finding the Last Row in an Excel Spreadsheet From Java](https://www.baeldung.com/java-excel-find-last-row)
- [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas)
+- [Set the Date Format Using Apache POI](https://www.baeldung.com/java-apache-poi-date-format)
- More articles: [[<-- prev]](../apache-poi)
diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/excel/dateformat/ExcelDateFormat.java b/apache-poi-2/src/main/java/com/baeldung/poi/excel/dateformat/ExcelDateFormat.java
new file mode 100644
index 0000000000..6ee2fb3c3b
--- /dev/null
+++ b/apache-poi-2/src/main/java/com/baeldung/poi/excel/dateformat/ExcelDateFormat.java
@@ -0,0 +1,35 @@
+package com.baeldung.poi.excel.dateformat;
+
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class ExcelDateFormat {
+
+ public final static String CUSTOM_DATE_FORMAT = "m/d/yy h:mm";
+
+ /**
+ * Set default date format to a cell
+ * @param dateCell cell to set date format
+ * @param wb workbook to create date format cell style
+ */
+ public void setDefaultDateFormat(XSSFCell dateCell, XSSFWorkbook wb) {
+ CellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setDataFormat((short) 14);
+ dateCell.setCellStyle(cellStyle);
+ }
+
+ /**
+ * Set custom date format to a cell
+ * @param dateCell cell to set date format
+ * @param wb workbook to create date format cell style
+ */
+ public void setCustomDateFormat(XSSFCell dateCell, XSSFWorkbook wb) {
+ CellStyle cellStyle = wb.createCellStyle();
+ CreationHelper createHelper = wb.getCreationHelper();
+ short format = createHelper.createDataFormat().getFormat(CUSTOM_DATE_FORMAT);
+ cellStyle.setDataFormat(format);
+ dateCell.setCellStyle(cellStyle);
+ }
+}
diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/excel/dateformat/DateFormatUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/excel/dateformat/DateFormatUnitTest.java
new file mode 100644
index 0000000000..fe211beb77
--- /dev/null
+++ b/apache-poi-2/src/test/java/com/baeldung/poi/excel/dateformat/DateFormatUnitTest.java
@@ -0,0 +1,95 @@
+package com.baeldung.poi.excel.dateformat;
+
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+
+import static com.baeldung.poi.excel.dateformat.ExcelDateFormat.CUSTOM_DATE_FORMAT;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class DateFormatUnitTest {
+
+ private ExcelDateFormat excelDateFormat;
+
+ private XSSFWorkbook wb;
+
+ private Date date;
+
+
+ @BeforeEach
+ public void setup() {
+ excelDateFormat = new ExcelDateFormat();
+ wb = new XSSFWorkbook();
+ wb.createSheet();
+ date = new Date();
+ }
+
+ @Test
+ void givenExcelDate_whenSetDefaultDate_thenSuccess() {
+ // given Excel Sheet
+ XSSFSheet sheet = wb.getSheetAt(0);
+ XSSFCell dateCell = sheet.createRow(0).createCell(0);
+
+ // when set default date format
+ excelDateFormat.setDefaultDateFormat(dateCell, wb);
+ dateCell.setCellValue(date);
+
+ // then success
+ assertEquals(date, dateCell.getDateCellValue());
+ }
+
+ @Test
+ void givenExcelDate_whenSetCustomDate_thenSuccess() {
+ // given Excel Sheet
+ XSSFSheet sheet = wb.getSheetAt(0);
+ XSSFCell dateCellCustom = sheet.createRow(0).createCell(0);
+
+ // when set custom date format
+ excelDateFormat.setCustomDateFormat(dateCellCustom, wb);
+ dateCellCustom.setCellValue(date);
+
+ // then success
+ assertEquals(CUSTOM_DATE_FORMAT, dateCellCustom.getCellStyle().getDataFormatString());
+ assertEquals(date, dateCellCustom.getDateCellValue());
+ }
+
+ @Test
+ void givenExcelDefaultDateFormat_whenGetDefaultDateFormat_thenSuccess() {
+ // given Excel cell style with default date format
+ CellStyle cellStyle = wb.createCellStyle();
+
+ // when get default date format
+ cellStyle.setDataFormat((short) 14);
+ // then success
+ assertEquals("m/d/yy", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 15);
+ assertEquals("d-mmm-yy", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 16);
+ assertEquals("d-mmm", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 17);
+ assertEquals("mmm-yy", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 18);
+ assertEquals("h:mm AM/PM", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 19);
+ assertEquals("h:mm:ss AM/PM", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 20);
+ assertEquals("h:mm", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 21);
+ assertEquals("h:mm:ss", cellStyle.getDataFormatString());
+
+ cellStyle.setDataFormat((short) 22);
+ assertEquals("m/d/yy h:mm", cellStyle.getDataFormatString());
+ }
+}
diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml
index f4b6de8872..a562ebeec0 100644
--- a/apache-velocity/pom.xml
+++ b/apache-velocity/pom.xml
@@ -63,6 +63,7 @@
4.5.2
1.7
2.0
+ 3.3.2
\ No newline at end of file
diff --git a/asciidoctor/pom.xml b/asciidoctor/pom.xml
index e24917f2f4..b72f050379 100644
--- a/asciidoctor/pom.xml
+++ b/asciidoctor/pom.xml
@@ -62,10 +62,10 @@
- 1.5.6
- 1.5.6
- 1.5.0-alpha.15
- 1.5.0-alpha.15
+ 2.2.2
+ 2.5.7
+ 2.3.4
+ 2.3.4
\ No newline at end of file
diff --git a/aws-modules/aws-lambda/shipping-tracker/ShippingFunction/pom.xml b/aws-modules/aws-lambda/shipping-tracker/ShippingFunction/pom.xml
index c36c81375d..24f2a76912 100644
--- a/aws-modules/aws-lambda/shipping-tracker/ShippingFunction/pom.xml
+++ b/aws-modules/aws-lambda/shipping-tracker/ShippingFunction/pom.xml
@@ -69,8 +69,8 @@
- 1.8
- 1.8
+ 11
+ 11
5.4.21.Final
1.2.0
3.1.0
diff --git a/aws-modules/aws-lambda/todo-reminder/ToDoFunction/pom.xml b/aws-modules/aws-lambda/todo-reminder/ToDoFunction/pom.xml
index cb6dd08d1e..0dd2e4d14a 100644
--- a/aws-modules/aws-lambda/todo-reminder/ToDoFunction/pom.xml
+++ b/aws-modules/aws-lambda/todo-reminder/ToDoFunction/pom.xml
@@ -1,6 +1,6 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
helloworld
ToDoFunction
@@ -101,16 +101,16 @@
- 1.8
- 1.8
+ 11
+ 11
1.2.1
3.6.0
- 1.1.0
+ 1.2.1
1.2.0
2.13.2
11.2
- 5.0.1
- 1.2.0
+ 5.1.0
+ 2.0.2
4.1.0
3.19.0
5.8.1
diff --git a/aws-modules/aws-reactive/pom.xml b/aws-modules/aws-reactive/pom.xml
index fbad5e30d0..e6b50cadb2 100644
--- a/aws-modules/aws-reactive/pom.xml
+++ b/aws-modules/aws-reactive/pom.xml
@@ -77,6 +77,7 @@
org.projectlombok
lombok
+ ${lombok.version}
@@ -92,6 +93,7 @@
2.2.1.RELEASE
2.17.283
+ 1.18.20
\ No newline at end of file
diff --git a/axon/README.md b/axon/README.md
index 40547a68b8..9aeef05dd6 100644
--- a/axon/README.md
+++ b/axon/README.md
@@ -2,11 +2,17 @@
This module contains articles about Axon
+## Profiles
+
+Optionally the code can be run with the 'mongo' profile to use Mongo to store the projection. Otherwise, an in-memory
+projection is used.
+
## Scripts
-One script is included to easily start middleware using Docker:
+Two scripts are included to easily start middleware using Docker matching the properties files:
- `start_axon_server.sh` to start an Axon Server instance
+- `start_mongo.sh` to start a MongoDB instance
### Relevant articles
@@ -14,3 +20,5 @@ One script is included to easily start middleware using Docker:
- [Multi-Entity Aggregates in Axon](https://www.baeldung.com/java-axon-multi-entity-aggregates)
- [Snapshotting Aggregates in Axon](https://www.baeldung.com/axon-snapshotting-aggregates)
- [Dispatching Queries in Axon Framework](https://www.baeldung.com/axon-query-dispatching)
+- [Persisting the Query Model](https://www.baeldung.com/persisting-the-query-model)
+- [Using and testing Axon applications via REST](https://www.baeldung.com/using-and-testing-axon-applications-via-rest)
diff --git a/axon/pom.xml b/axon/pom.xml
index df14233863..42e32758ea 100644
--- a/axon/pom.xml
+++ b/axon/pom.xml
@@ -44,6 +44,10 @@
org.springframework.boot
spring-boot-starter-data-jpa
+
+ org.axonframework.extensions.mongo
+ axon-mongo
+
io.projectreactor
reactor-core
@@ -68,10 +72,32 @@
reactor-test
test
+
+ de.flapdoodle.embed
+ de.flapdoodle.embed.mongo
+ ${de.flapdoodle.embed.mongo.version}
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ org.springframework
+ spring-webflux
+ test
+
+
+ io.projectreactor.netty
+ reactor-netty-http
+ test
+
- 4.6.0
+ 4.6.3
+ 3.4.8
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/OrderApplication.java b/axon/src/main/java/com/baeldung/axon/OrderApplication.java
index 8f507e141c..9e5334c3a3 100644
--- a/axon/src/main/java/com/baeldung/axon/OrderApplication.java
+++ b/axon/src/main/java/com/baeldung/axon/OrderApplication.java
@@ -9,5 +9,4 @@ public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
-
}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/OrderApplicationConfiguration.java b/axon/src/main/java/com/baeldung/axon/OrderApplicationConfiguration.java
index 8b743144b4..e1b7d5b14c 100644
--- a/axon/src/main/java/com/baeldung/axon/OrderApplicationConfiguration.java
+++ b/axon/src/main/java/com/baeldung/axon/OrderApplicationConfiguration.java
@@ -11,8 +11,7 @@ import org.springframework.context.annotation.Configuration;
public class OrderApplicationConfiguration {
@Bean
- public SnapshotTriggerDefinition orderAggregateSnapshotTriggerDefinition(Snapshotter snapshotter,
- @Value("${axon.aggregate.order.snapshot-threshold:250}") int threshold) {
+ public SnapshotTriggerDefinition orderAggregateSnapshotTriggerDefinition(Snapshotter snapshotter, @Value("${axon.aggregate.order.snapshot-threshold:250}") int threshold) {
return new EventCountSnapshotTriggerDefinition(snapshotter, threshold);
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java
index 1065e9d22b..c58c0b27ac 100644
--- a/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java
+++ b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java
@@ -12,6 +12,7 @@ import com.baeldung.axon.coreapi.events.ProductRemovedEvent;
import com.baeldung.axon.coreapi.exceptions.DuplicateOrderLineException;
import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException;
import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException;
+
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.eventsourcing.EventSourcingHandler;
import org.axonframework.modelling.command.AggregateIdentifier;
diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java
index e471ecbfe0..aa774070c0 100644
--- a/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java
+++ b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java
@@ -7,6 +7,7 @@ import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent;
import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent;
import com.baeldung.axon.coreapi.events.ProductRemovedEvent;
import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException;
+
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.eventsourcing.EventSourcingHandler;
import org.axonframework.modelling.command.EntityId;
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java
index 28736aaadc..8f2babc2dc 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java
@@ -42,9 +42,6 @@ public class AddProductCommand {
@Override
public String toString() {
- return "AddProductCommand{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "AddProductCommand{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java
index 244b69f3b7..37f1df2725 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java
@@ -36,8 +36,6 @@ public class ConfirmOrderCommand {
@Override
public String toString() {
- return "ConfirmOrderCommand{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "ConfirmOrderCommand{" + "orderId='" + orderId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java
index ceb7fd6a08..294d53cab8 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java
@@ -36,8 +36,6 @@ public class CreateOrderCommand {
@Override
public String toString() {
- return "CreateOrderCommand{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "CreateOrderCommand{" + "orderId='" + orderId + '\'' + '}';
}
}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java
index f6f4db00fc..0874f88df8 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java
@@ -42,9 +42,6 @@ public class DecrementProductCountCommand {
@Override
public String toString() {
- return "DecrementProductCountCommand{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "DecrementProductCountCommand{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java
index 548faabe37..aceb93e478 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java
@@ -42,9 +42,6 @@ public class IncrementProductCountCommand {
@Override
public String toString() {
- return "IncrementProductCountCommand{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "IncrementProductCountCommand{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java
index 7312bc1fdb..f0f3a6e071 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java
@@ -36,8 +36,6 @@ public class ShipOrderCommand {
@Override
public String toString() {
- return "ShipOrderCommand{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "ShipOrderCommand{" + "orderId='" + orderId + '\'' + '}';
}
}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java
index d2b7d58435..3253c2f1d5 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java
@@ -33,8 +33,6 @@ public class OrderConfirmedEvent {
@Override
public String toString() {
- return "OrderConfirmedEvent{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "OrderConfirmedEvent{" + "orderId='" + orderId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java
index 5d2d8b7f55..2bb86108f9 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java
@@ -33,8 +33,6 @@ public class OrderCreatedEvent {
@Override
public String toString() {
- return "OrderCreatedEvent{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "OrderCreatedEvent{" + "orderId='" + orderId + '\'' + '}';
}
}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java
index 76aa684629..5161bc7bf1 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java
@@ -33,8 +33,6 @@ public class OrderShippedEvent {
@Override
public String toString() {
- return "OrderShippedEvent{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "OrderShippedEvent{" + "orderId='" + orderId + '\'' + '}';
}
}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java
index 091ef2a570..14510cb161 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java
@@ -39,9 +39,6 @@ public class ProductAddedEvent {
@Override
public String toString() {
- return "ProductAddedEvent{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "ProductAddedEvent{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java
index 4017916791..eec424cb24 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java
@@ -39,9 +39,6 @@ public class ProductCountDecrementedEvent {
@Override
public String toString() {
- return "ProductCountDecrementedEvent{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "ProductCountDecrementedEvent{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java
index 2910a9ea6f..0d008758c7 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java
@@ -39,9 +39,6 @@ public class ProductCountIncrementedEvent {
@Override
public String toString() {
- return "ProductCountIncrementedEvent{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "ProductCountIncrementedEvent{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java
index 7f89ccd1cc..13ff77db26 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java
@@ -39,9 +39,6 @@ public class ProductRemovedEvent {
@Override
public String toString() {
- return "ProductRemovedEvent{" +
- "orderId='" + orderId + '\'' +
- ", productId='" + productId + '\'' +
- '}';
+ return "ProductRemovedEvent{" + "orderId='" + orderId + '\'' + ", productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java
index 1810a053d3..9cef3e84ee 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java
@@ -40,7 +40,6 @@ public class Order {
products.computeIfPresent(productId, (id, count) -> --count);
}
-
public void removeProduct(String productId) {
products.remove(productId);
}
@@ -62,9 +61,7 @@ public class Order {
return false;
}
Order that = (Order) o;
- return Objects.equals(orderId, that.orderId)
- && Objects.equals(products, that.products)
- && orderStatus == that.orderStatus;
+ return Objects.equals(orderId, that.orderId) && Objects.equals(products, that.products) && orderStatus == that.orderStatus;
}
@Override
@@ -74,10 +71,6 @@ public class Order {
@Override
public String toString() {
- return "Order{" +
- "orderId='" + orderId + '\'' +
- ", products=" + products +
- ", orderStatus=" + orderStatus +
- '}';
+ return "Order{" + "orderId='" + orderId + '\'' + ", products=" + products + ", orderStatus=" + orderStatus + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderUpdatesQuery.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderUpdatesQuery.java
index 37d2e67445..b4e66289b4 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderUpdatesQuery.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderUpdatesQuery.java
@@ -32,8 +32,6 @@ public class OrderUpdatesQuery {
@Override
public String toString() {
- return "OrderUpdatesQuery{" +
- "orderId='" + orderId + '\'' +
- '}';
+ return "OrderUpdatesQuery{" + "orderId='" + orderId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/TotalProductsShippedQuery.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/TotalProductsShippedQuery.java
index 3a4129685b..8c3bbf3528 100644
--- a/axon/src/main/java/com/baeldung/axon/coreapi/queries/TotalProductsShippedQuery.java
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/TotalProductsShippedQuery.java
@@ -32,8 +32,6 @@ public class TotalProductsShippedQuery {
@Override
public String toString() {
- return "TotalProductsShippedQuery{" +
- "productId='" + productId + '\'' +
- '}';
+ return "TotalProductsShippedQuery{" + "productId='" + productId + '\'' + '}';
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java
index 64058d5eca..186aab3c0c 100644
--- a/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java
+++ b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java
@@ -8,12 +8,14 @@ import com.baeldung.axon.coreapi.commands.IncrementProductCountCommand;
import com.baeldung.axon.coreapi.commands.ShipOrderCommand;
import com.baeldung.axon.querymodel.OrderQueryService;
import com.baeldung.axon.querymodel.OrderResponse;
+
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
+
import reactor.core.publisher.Flux;
import java.util.List;
@@ -33,25 +35,28 @@ public class OrderRestEndpoint {
@PostMapping("/ship-order")
public CompletableFuture shipOrder() {
- String orderId = UUID.randomUUID().toString();
+ String orderId = UUID.randomUUID()
+ .toString();
return commandGateway.send(new CreateOrderCommand(orderId))
- .thenCompose(result -> commandGateway.send(new AddProductCommand(orderId, "Deluxe Chair")))
- .thenCompose(result -> commandGateway.send(new ConfirmOrderCommand(orderId)))
- .thenCompose(result -> commandGateway.send(new ShipOrderCommand(orderId)));
+ .thenCompose(result -> commandGateway.send(new AddProductCommand(orderId, "Deluxe Chair")))
+ .thenCompose(result -> commandGateway.send(new ConfirmOrderCommand(orderId)))
+ .thenCompose(result -> commandGateway.send(new ShipOrderCommand(orderId)));
}
@PostMapping("/ship-unconfirmed-order")
public CompletableFuture shipUnconfirmedOrder() {
- String orderId = UUID.randomUUID().toString();
+ String orderId = UUID.randomUUID()
+ .toString();
return commandGateway.send(new CreateOrderCommand(orderId))
- .thenCompose(result -> commandGateway.send(new AddProductCommand(orderId, "Deluxe Chair")))
- // This throws an exception, as an Order cannot be shipped if it has not been confirmed yet.
- .thenCompose(result -> commandGateway.send(new ShipOrderCommand(orderId)));
+ .thenCompose(result -> commandGateway.send(new AddProductCommand(orderId, "Deluxe Chair")))
+ // This throws an exception, as an Order cannot be shipped if it has not been confirmed yet.
+ .thenCompose(result -> commandGateway.send(new ShipOrderCommand(orderId)));
}
@PostMapping("/order")
public CompletableFuture createOrder() {
- return createOrder(UUID.randomUUID().toString());
+ return createOrder(UUID.randomUUID()
+ .toString());
}
@PostMapping("/order/{order-id}")
@@ -60,20 +65,17 @@ public class OrderRestEndpoint {
}
@PostMapping("/order/{order-id}/product/{product-id}")
- public CompletableFuture addProduct(@PathVariable("order-id") String orderId,
- @PathVariable("product-id") String productId) {
+ public CompletableFuture addProduct(@PathVariable("order-id") String orderId, @PathVariable("product-id") String productId) {
return commandGateway.send(new AddProductCommand(orderId, productId));
}
@PostMapping("/order/{order-id}/product/{product-id}/increment")
- public CompletableFuture incrementProduct(@PathVariable("order-id") String orderId,
- @PathVariable("product-id") String productId) {
+ public CompletableFuture incrementProduct(@PathVariable("order-id") String orderId, @PathVariable("product-id") String productId) {
return commandGateway.send(new IncrementProductCountCommand(orderId, productId));
}
@PostMapping("/order/{order-id}/product/{product-id}/decrement")
- public CompletableFuture decrementProduct(@PathVariable("order-id") String orderId,
- @PathVariable("product-id") String productId) {
+ public CompletableFuture decrementProduct(@PathVariable("order-id") String orderId, @PathVariable("product-id") String productId) {
return commandGateway.send(new DecrementProductCountCommand(orderId, productId));
}
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/InMemoryOrdersEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/InMemoryOrdersEventHandler.java
index fbdf819961..6e9dbbb335 100644
--- a/axon/src/main/java/com/baeldung/axon/querymodel/InMemoryOrdersEventHandler.java
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/InMemoryOrdersEventHandler.java
@@ -18,7 +18,9 @@ import org.axonframework.eventhandling.EventHandler;
import org.axonframework.queryhandling.QueryHandler;
import org.axonframework.queryhandling.QueryUpdateEmitter;
import org.reactivestreams.Publisher;
+import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
+
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -30,6 +32,7 @@ import java.util.Optional;
@Service
@ProcessingGroup("orders")
+@Profile("!mongo")
public class InMemoryOrdersEventHandler implements OrdersEventHandler {
private final Map orders = new HashMap<>();
@@ -106,7 +109,8 @@ public class InMemoryOrdersEventHandler implements OrdersEventHandler {
@QueryHandler
public Publisher handleStreaming(FindAllOrderedProductsQuery query) {
- return Mono.fromCallable(orders::values).flatMapMany(Flux::fromIterable);
+ return Mono.fromCallable(orders::values)
+ .flatMapMany(Flux::fromIterable);
}
@QueryHandler
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/MongoConfiguration.java b/axon/src/main/java/com/baeldung/axon/querymodel/MongoConfiguration.java
new file mode 100644
index 0000000000..d68569efc8
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/MongoConfiguration.java
@@ -0,0 +1,26 @@
+package com.baeldung.axon.querymodel;
+
+import com.mongodb.client.MongoClient;
+
+import org.axonframework.eventhandling.tokenstore.TokenStore;
+import org.axonframework.extensions.mongo.DefaultMongoTemplate;
+import org.axonframework.extensions.mongo.eventsourcing.tokenstore.MongoTokenStore;
+import org.axonframework.serialization.Serializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("mongo")
+public class MongoConfiguration {
+
+ @Bean
+ public TokenStore getTokenStore(MongoClient client, Serializer serializer) {
+ return MongoTokenStore.builder()
+ .mongoTemplate(DefaultMongoTemplate.builder()
+ .mongoDatabase(client)
+ .build())
+ .serializer(serializer)
+ .build();
+ }
+}
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/MongoOrdersEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/MongoOrdersEventHandler.java
new file mode 100644
index 0000000000..4da98a9f97
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/MongoOrdersEventHandler.java
@@ -0,0 +1,194 @@
+package com.baeldung.axon.querymodel;
+
+import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
+import com.baeldung.axon.coreapi.events.OrderCreatedEvent;
+import com.baeldung.axon.coreapi.events.OrderShippedEvent;
+import com.baeldung.axon.coreapi.events.ProductAddedEvent;
+import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent;
+import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent;
+import com.baeldung.axon.coreapi.events.ProductRemovedEvent;
+import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
+import com.baeldung.axon.coreapi.queries.Order;
+import com.baeldung.axon.coreapi.queries.OrderStatus;
+import com.baeldung.axon.coreapi.queries.OrderUpdatesQuery;
+import com.baeldung.axon.coreapi.queries.TotalProductsShippedQuery;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.model.IndexOptions;
+import com.mongodb.client.model.Indexes;
+import com.mongodb.client.result.UpdateResult;
+
+import groovyjarjarantlr4.v4.runtime.misc.NotNull;
+
+import org.axonframework.config.ProcessingGroup;
+import org.axonframework.eventhandling.EventHandler;
+import org.axonframework.queryhandling.QueryHandler;
+import org.axonframework.queryhandling.QueryUpdateEmitter;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.reactivestreams.Publisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+
+import reactor.core.publisher.Flux;
+
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+import static com.mongodb.client.model.Filters.*;
+
+@Service
+@ProcessingGroup("orders")
+@Profile("mongo")
+public class MongoOrdersEventHandler implements OrdersEventHandler {
+
+ static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup()
+ .lookupClass());
+
+ private final MongoCollection orders;
+ private final QueryUpdateEmitter emitter;
+ private static final String ORDER_COLLECTION_NAME = "orders";
+ private static final String AXON_FRAMEWORK_DATABASE_NAME = "axonframework";
+
+ private static final String ORDER_ID_PROPERTY_NAME = "orderId";
+ private static final String PRODUCTS_PROPERTY_NAME = "products";
+ private static final String ORDER_STATUS_PROPERTY_NAME = "orderStatus";
+
+ public MongoOrdersEventHandler(MongoClient client, QueryUpdateEmitter emitter) {
+ orders = client.getDatabase(AXON_FRAMEWORK_DATABASE_NAME)
+ .getCollection(ORDER_COLLECTION_NAME);
+ orders.createIndex(Indexes.ascending(ORDER_ID_PROPERTY_NAME), new IndexOptions().unique(true));
+ this.emitter = emitter;
+ }
+
+ @EventHandler
+ public void on(OrderCreatedEvent event) {
+ orders.insertOne(orderToDocument(new Order(event.getOrderId())));
+ }
+
+ @EventHandler
+ public void on(ProductAddedEvent event) {
+ update(event.getOrderId(), o -> o.addProduct(event.getProductId()));
+ }
+
+ @EventHandler
+ public void on(ProductCountIncrementedEvent event) {
+ update(event.getOrderId(), o -> o.incrementProductInstance(event.getProductId()));
+ }
+
+ @EventHandler
+ public void on(ProductCountDecrementedEvent event) {
+ update(event.getOrderId(), o -> o.decrementProductInstance(event.getProductId()));
+ }
+
+ @EventHandler
+ public void on(ProductRemovedEvent event) {
+ update(event.getOrderId(), o -> o.removeProduct(event.getProductId()));
+ }
+
+ @EventHandler
+ public void on(OrderConfirmedEvent event) {
+ update(event.getOrderId(), Order::setOrderConfirmed);
+ }
+
+ @EventHandler
+ public void on(OrderShippedEvent event) {
+ update(event.getOrderId(), Order::setOrderShipped);
+ }
+
+ @QueryHandler
+ public List handle(FindAllOrderedProductsQuery query) {
+ List orderList = new ArrayList<>();
+ orders.find()
+ .forEach(d -> orderList.add(documentToOrder(d)));
+ return orderList;
+ }
+
+ @Override
+ public Publisher handleStreaming(FindAllOrderedProductsQuery query) {
+ return Flux.fromIterable(orders.find())
+ .map(this::documentToOrder);
+ }
+
+ @QueryHandler
+ public Integer handle(TotalProductsShippedQuery query) {
+ AtomicInteger result = new AtomicInteger();
+ orders.find(shippedProductFilter(query.getProductId()))
+ .map(d -> d.get(PRODUCTS_PROPERTY_NAME, Document.class))
+ .map(d -> d.getInteger(query.getProductId(), 0))
+ .forEach(result::addAndGet);
+ return result.get();
+ }
+
+ @QueryHandler
+ public Order handle(OrderUpdatesQuery query) {
+ return getOrder(query.getOrderId()).orElse(null);
+ }
+
+ @Override
+ public void reset(List orderList) {
+ orders.deleteMany(new Document());
+ orderList.forEach(o -> orders.insertOne(orderToDocument(o)));
+ }
+
+ private Optional getOrder(String orderId) {
+ return Optional.ofNullable(orders.find(eq(ORDER_ID_PROPERTY_NAME, orderId))
+ .first())
+ .map(this::documentToOrder);
+ }
+
+ private Order emitUpdate(Order order) {
+ emitter.emit(OrderUpdatesQuery.class, q -> order.getOrderId()
+ .equals(q.getOrderId()), order);
+ return order;
+ }
+
+ private Order updateOrder(Order order, Consumer updateFunction) {
+ updateFunction.accept(order);
+ return order;
+ }
+
+ private UpdateResult persistUpdate(Order order) {
+ return orders.replaceOne(eq(ORDER_ID_PROPERTY_NAME, order.getOrderId()), orderToDocument(order));
+ }
+
+ private void update(String orderId, Consumer updateFunction) {
+ UpdateResult result = getOrder(orderId).map(o -> updateOrder(o, updateFunction))
+ .map(this::emitUpdate)
+ .map(this::persistUpdate)
+ .orElse(null);
+ logger.info("Result of updating order with orderId '{}': {}", orderId, result);
+ }
+
+ private Document orderToDocument(Order order) {
+ return new Document(ORDER_ID_PROPERTY_NAME, order.getOrderId()).append(PRODUCTS_PROPERTY_NAME, order.getProducts())
+ .append(ORDER_STATUS_PROPERTY_NAME, order.getOrderStatus()
+ .toString());
+ }
+
+ private Order documentToOrder(@NotNull Document document) {
+ Order order = new Order(document.getString(ORDER_ID_PROPERTY_NAME));
+ Document products = document.get(PRODUCTS_PROPERTY_NAME, Document.class);
+ products.forEach((k, v) -> order.getProducts()
+ .put(k, (Integer) v));
+ String status = document.getString(ORDER_STATUS_PROPERTY_NAME);
+ if (OrderStatus.CONFIRMED.toString()
+ .equals(status)) {
+ order.setOrderConfirmed();
+ } else if (OrderStatus.SHIPPED.toString()
+ .equals(status)) {
+ order.setOrderShipped();
+ }
+ return order;
+ }
+
+ private Bson shippedProductFilter(String productId) {
+ return and(eq(ORDER_STATUS_PROPERTY_NAME, OrderStatus.SHIPPED.toString()), exists(String.format(PRODUCTS_PROPERTY_NAME + ".%s", productId)));
+ }
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrderQueryService.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrderQueryService.java
index ae391c3cb1..8196a98957 100644
--- a/axon/src/main/java/com/baeldung/axon/querymodel/OrderQueryService.java
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/OrderQueryService.java
@@ -37,12 +37,12 @@ public class OrderQueryService {
public Flux allOrdersStreaming() {
Publisher publisher = queryGateway.streamingQuery(new FindAllOrderedProductsQuery(), Order.class);
- return Flux.from(publisher).map(OrderResponse::new);
+ return Flux.from(publisher)
+ .map(OrderResponse::new);
}
public Integer totalShipped(String productId) {
- return queryGateway.scatterGather(new TotalProductsShippedQuery(productId),
- ResponseTypes.instanceOf(Integer.class), 10L, TimeUnit.SECONDS)
+ return queryGateway.scatterGather(new TotalProductsShippedQuery(productId), ResponseTypes.instanceOf(Integer.class), 10L, TimeUnit.SECONDS)
.reduce(0, Integer::sum);
}
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrderStatusResponse.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrderStatusResponse.java
index 90430b1e3d..2c4d32bff3 100644
--- a/axon/src/main/java/com/baeldung/axon/querymodel/OrderStatusResponse.java
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/OrderStatusResponse.java
@@ -7,7 +7,8 @@ public enum OrderStatusResponse {
static OrderStatusResponse toResponse(OrderStatus status) {
for (OrderStatusResponse response : values()) {
- if (response.toString().equals(status.toString())) {
+ if (response.toString()
+ .equals(status.toString())) {
return response;
}
}
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java
index 7e49abf93b..740e00cf72 100644
--- a/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java
@@ -11,6 +11,7 @@ import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
import com.baeldung.axon.coreapi.queries.Order;
import com.baeldung.axon.coreapi.queries.OrderUpdatesQuery;
import com.baeldung.axon.coreapi.queries.TotalProductsShippedQuery;
+
import org.reactivestreams.Publisher;
import java.util.List;
diff --git a/axon/src/main/resources/application-mongo.properties b/axon/src/main/resources/application-mongo.properties
new file mode 100644
index 0000000000..f642d1591c
--- /dev/null
+++ b/axon/src/main/resources/application-mongo.properties
@@ -0,0 +1,6 @@
+spring.data.mongodb.host=localhost
+spring.data.mongodb.port=27017
+spring.data.mongodb.authentication-database=admin
+spring.data.mongodb.username=admin1234
+spring.data.mongodb.password=somepassword
+spring.data.mongodb.database=order-projection
\ No newline at end of file
diff --git a/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java
index c1d6bdccc2..fe7f57f854 100644
--- a/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java
+++ b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java
@@ -17,6 +17,7 @@ import com.baeldung.axon.coreapi.events.ProductRemovedEvent;
import com.baeldung.axon.coreapi.exceptions.DuplicateOrderLineException;
import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException;
import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException;
+
import org.axonframework.test.aggregate.AggregateTestFixture;
import org.axonframework.test.aggregate.FixtureConfiguration;
import org.axonframework.test.matchers.Matchers;
@@ -26,8 +27,10 @@ import java.util.UUID;
class OrderAggregateUnitTest {
- private static final String ORDER_ID = UUID.randomUUID().toString();
- private static final String PRODUCT_ID = UUID.randomUUID().toString();
+ private static final String ORDER_ID = UUID.randomUUID()
+ .toString();
+ private static final String PRODUCT_ID = UUID.randomUUID()
+ .toString();
private FixtureConfiguration fixture;
@@ -39,101 +42,95 @@ class OrderAggregateUnitTest {
@Test
void giveNoPriorActivity_whenCreateOrderCommand_thenShouldPublishOrderCreatedEvent() {
fixture.givenNoPriorActivity()
- .when(new CreateOrderCommand(ORDER_ID))
- .expectEvents(new OrderCreatedEvent(ORDER_ID));
+ .when(new CreateOrderCommand(ORDER_ID))
+ .expectEvents(new OrderCreatedEvent(ORDER_ID));
}
@Test
void givenOrderCreatedEvent_whenAddProductCommand_thenShouldPublishProductAddedEvent() {
fixture.given(new OrderCreatedEvent(ORDER_ID))
- .when(new AddProductCommand(ORDER_ID, PRODUCT_ID))
- .expectEvents(new ProductAddedEvent(ORDER_ID, PRODUCT_ID));
+ .when(new AddProductCommand(ORDER_ID, PRODUCT_ID))
+ .expectEvents(new ProductAddedEvent(ORDER_ID, PRODUCT_ID));
}
@Test
void givenOrderCreatedEventAndProductAddedEvent_whenAddProductCommandForSameProductId_thenShouldThrowDuplicateOrderLineException() {
fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID))
- .when(new AddProductCommand(ORDER_ID, PRODUCT_ID))
- .expectException(DuplicateOrderLineException.class)
- .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(PRODUCT_ID)));
+ .when(new AddProductCommand(ORDER_ID, PRODUCT_ID))
+ .expectException(DuplicateOrderLineException.class)
+ .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(PRODUCT_ID)));
}
@Test
void givenOrderCreatedEventAndProductAddedEvent_whenIncrementProductCountCommand_thenShouldPublishProductCountIncrementedEvent() {
fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID))
- .when(new IncrementProductCountCommand(ORDER_ID, PRODUCT_ID))
- .expectEvents(new ProductCountIncrementedEvent(ORDER_ID, PRODUCT_ID));
+ .when(new IncrementProductCountCommand(ORDER_ID, PRODUCT_ID))
+ .expectEvents(new ProductCountIncrementedEvent(ORDER_ID, PRODUCT_ID));
}
@Test
void givenOrderCreatedEventProductAddedEventAndProductCountIncrementedEvent_whenDecrementProductCountCommand_thenShouldPublishProductCountDecrementedEvent() {
- fixture.given(new OrderCreatedEvent(ORDER_ID),
- new ProductAddedEvent(ORDER_ID, PRODUCT_ID),
- new ProductCountIncrementedEvent(ORDER_ID, PRODUCT_ID))
- .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID))
- .expectEvents(new ProductCountDecrementedEvent(ORDER_ID, PRODUCT_ID));
+ fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID), new ProductCountIncrementedEvent(ORDER_ID, PRODUCT_ID))
+ .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID))
+ .expectEvents(new ProductCountDecrementedEvent(ORDER_ID, PRODUCT_ID));
}
@Test
void givenOrderCreatedEventAndProductAddedEvent_whenDecrementProductCountCommand_thenShouldPublishProductRemovedEvent() {
fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID))
- .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID))
- .expectEvents(new ProductRemovedEvent(ORDER_ID, PRODUCT_ID));
+ .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID))
+ .expectEvents(new ProductRemovedEvent(ORDER_ID, PRODUCT_ID));
}
@Test
void givenOrderCreatedEvent_whenConfirmOrderCommand_thenShouldPublishOrderConfirmedEvent() {
fixture.given(new OrderCreatedEvent(ORDER_ID))
- .when(new ConfirmOrderCommand(ORDER_ID))
- .expectEvents(new OrderConfirmedEvent(ORDER_ID));
+ .when(new ConfirmOrderCommand(ORDER_ID))
+ .expectEvents(new OrderConfirmedEvent(ORDER_ID));
}
@Test
void givenOrderCreatedEventAndOrderConfirmedEvent_whenConfirmOrderCommand_thenExpectNoEvents() {
fixture.given(new OrderCreatedEvent(ORDER_ID), new OrderConfirmedEvent(ORDER_ID))
- .when(new ConfirmOrderCommand(ORDER_ID))
- .expectNoEvents();
+ .when(new ConfirmOrderCommand(ORDER_ID))
+ .expectNoEvents();
}
@Test
void givenOrderCreatedEvent_whenShipOrderCommand_thenShouldThrowUnconfirmedOrderException() {
fixture.given(new OrderCreatedEvent(ORDER_ID))
- .when(new ShipOrderCommand(ORDER_ID))
- .expectException(UnconfirmedOrderException.class);
+ .when(new ShipOrderCommand(ORDER_ID))
+ .expectException(UnconfirmedOrderException.class);
}
@Test
void givenOrderCreatedEventAndOrderConfirmedEvent_whenShipOrderCommand_thenShouldPublishOrderShippedEvent() {
fixture.given(new OrderCreatedEvent(ORDER_ID), new OrderConfirmedEvent(ORDER_ID))
- .when(new ShipOrderCommand(ORDER_ID))
- .expectEvents(new OrderShippedEvent(ORDER_ID));
+ .when(new ShipOrderCommand(ORDER_ID))
+ .expectEvents(new OrderShippedEvent(ORDER_ID));
}
@Test
void givenOrderCreatedEventProductAndOrderConfirmedEvent_whenAddProductCommand_thenShouldThrowOrderAlreadyConfirmedException() {
fixture.given(new OrderCreatedEvent(ORDER_ID), new OrderConfirmedEvent(ORDER_ID))
- .when(new AddProductCommand(ORDER_ID, PRODUCT_ID))
- .expectException(OrderAlreadyConfirmedException.class)
- .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID)));
+ .when(new AddProductCommand(ORDER_ID, PRODUCT_ID))
+ .expectException(OrderAlreadyConfirmedException.class)
+ .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID)));
}
@Test
void givenOrderCreatedEventProductAddedEventAndOrderConfirmedEvent_whenIncrementProductCountCommand_thenShouldThrowOrderAlreadyConfirmedException() {
- fixture.given(new OrderCreatedEvent(ORDER_ID),
- new ProductAddedEvent(ORDER_ID, PRODUCT_ID),
- new OrderConfirmedEvent(ORDER_ID))
- .when(new IncrementProductCountCommand(ORDER_ID, PRODUCT_ID))
- .expectException(OrderAlreadyConfirmedException.class)
- .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID)));
+ fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID), new OrderConfirmedEvent(ORDER_ID))
+ .when(new IncrementProductCountCommand(ORDER_ID, PRODUCT_ID))
+ .expectException(OrderAlreadyConfirmedException.class)
+ .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID)));
}
@Test
void givenOrderCreatedEventProductAddedEventAndOrderConfirmedEvent_whenDecrementProductCountCommand_thenShouldThrowOrderAlreadyConfirmedException() {
- fixture.given(new OrderCreatedEvent(ORDER_ID),
- new ProductAddedEvent(ORDER_ID, PRODUCT_ID),
- new OrderConfirmedEvent(ORDER_ID))
- .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID))
- .expectException(OrderAlreadyConfirmedException.class)
- .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID)));
+ fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID), new OrderConfirmedEvent(ORDER_ID))
+ .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID))
+ .expectException(OrderAlreadyConfirmedException.class)
+ .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID)));
}
}
\ No newline at end of file
diff --git a/axon/src/test/java/com/baeldung/axon/gui/OrderRestEndpointManualTest.java b/axon/src/test/java/com/baeldung/axon/gui/OrderRestEndpointManualTest.java
new file mode 100644
index 0000000000..3b5c130c89
--- /dev/null
+++ b/axon/src/test/java/com/baeldung/axon/gui/OrderRestEndpointManualTest.java
@@ -0,0 +1,188 @@
+package com.baeldung.axon.gui;
+
+import com.baeldung.axon.OrderApplication;
+import com.baeldung.axon.querymodel.OrderResponse;
+import com.baeldung.axon.querymodel.OrderStatusResponse;
+
+import org.junit.jupiter.api.*;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+import reactor.test.StepVerifier;
+
+import java.util.ArrayList;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest(classes = OrderApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+//marked as manual as the test is unstable on Jenkins due to low resources
+class OrderRestEndpointManualTest {
+
+ @LocalServerPort
+ private int port;
+
+ @Test
+ @DirtiesContext
+ void givenCreateOrderCalled_whenCallingAllOrders_thenOneCreatedOrderIsReturned() {
+ WebClient client = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ createRandomNewOrder(client);
+ StepVerifier.create(retrieveListResponse(client.get()
+ .uri("http://localhost:" + port + "/all-orders")))
+ .expectNextMatches(list -> 1 == list.size() && list.get(0)
+ .getOrderStatus() == OrderStatusResponse.CREATED)
+ .verifyComplete();
+ }
+
+ @Test
+ @DirtiesContext
+ void givenCreateOrderCalledThreeTimesAnd_whenCallingAllOrdersStreaming_thenTwoCreatedOrdersAreReturned() {
+ WebClient client = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ for (int i = 0; i < 3; i++) {
+ createRandomNewOrder(client);
+ }
+ StepVerifier.create(retrieveStreamingResponse(client.get()
+ .uri("http://localhost:" + port + "/all-orders-streaming")))
+ .expectNextMatches(o -> o.getOrderStatus() == OrderStatusResponse.CREATED)
+ .expectNextMatches(o -> o.getOrderStatus() == OrderStatusResponse.CREATED)
+ .expectNextMatches(o -> o.getOrderStatus() == OrderStatusResponse.CREATED)
+ .verifyComplete();
+ }
+
+ @Test
+ @DirtiesContext
+ void givenRuleExistThatNeedConfirmationBeforeShipping_whenCallingShipUnconfirmed_thenErrorReturned() {
+ WebClient client = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ StepVerifier.create(retrieveResponse(client.post()
+ .uri("http://localhost:" + port + "/ship-unconfirmed-order")))
+ .verifyError(WebClientResponseException.class);
+ }
+
+ @Test
+ @DirtiesContext
+ void givenShipOrderCalled_whenCallingAllShippedChairs_then234PlusOneIsReturned() {
+ WebClient client = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ verifyVoidPost(client, "http://localhost:" + port + "/ship-order");
+ StepVerifier.create(retrieveIntegerResponse(client.get()
+ .uri("http://localhost:" + port + "/total-shipped/Deluxe Chair")))
+ .assertNext(r -> assertEquals(235, r))
+ .verifyComplete();
+ }
+
+ @Test
+ @DirtiesContext
+ void givenOrdersAreUpdated_whenCallingOrderUpdates_thenUpdatesReturned() {
+ WebClient updaterClient = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ WebClient receiverClient = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ String orderId = UUID.randomUUID()
+ .toString();
+ String productId = UUID.randomUUID()
+ .toString();
+ StepVerifier.create(retrieveResponse(updaterClient.post()
+ .uri("http://localhost:" + port + "/order/" + orderId)))
+ .assertNext(Assertions::assertNotNull)
+ .verifyComplete();
+ ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+ executor.schedule(() -> addIncrementDecrementConfirmAndShipProduct(orderId, productId), 1L, TimeUnit.SECONDS);
+ try {
+ StepVerifier.create(retrieveStreamingResponse(receiverClient.get()
+ .uri("http://localhost:" + port + "/order-updates/" + orderId)))
+ .assertNext(p -> assertTrue(p.getProducts()
+ .isEmpty()))
+ .assertNext(p -> assertEquals(1, p.getProducts()
+ .get(productId)))
+ .assertNext(p -> assertEquals(2, p.getProducts()
+ .get(productId)))
+ .assertNext(p -> assertEquals(1, p.getProducts()
+ .get(productId)))
+ .assertNext(p -> assertEquals(OrderStatusResponse.CONFIRMED, p.getOrderStatus()))
+ .assertNext(p -> assertEquals(OrderStatusResponse.SHIPPED, p.getOrderStatus()))
+ .thenCancel()
+ .verify();
+ } finally {
+ executor.shutdown();
+ }
+ }
+
+ private void addIncrementDecrementConfirmAndShipProduct(String orderId, String productId) {
+ WebClient client = WebClient.builder()
+ .clientConnector(httpConnector())
+ .build();
+ String base = "http://localhost:" + port + "/order/" + orderId;
+ verifyVoidPost(client, base + "/product/" + productId);
+ verifyVoidPost(client, base + "/product/" + productId + "/increment");
+ verifyVoidPost(client, base + "/product/" + productId + "/decrement");
+ verifyVoidPost(client, base + "/confirm");
+ verifyVoidPost(client, base + "/ship");
+ }
+
+ private void createRandomNewOrder(WebClient client){
+ StepVerifier.create(retrieveResponse(client.post()
+ .uri("http://localhost:" + port + "/order")))
+ .assertNext(Assertions::assertNotNull)
+ .verifyComplete();
+ }
+
+ private void verifyVoidPost(WebClient client, String uri) {
+ StepVerifier.create(retrieveResponse(client.post()
+ .uri(uri)))
+ .verifyComplete();
+ }
+
+ private static ReactorClientHttpConnector httpConnector() {
+ HttpClient httpClient = HttpClient.create()
+ .wiretap(true);
+ return new ReactorClientHttpConnector(httpClient);
+ }
+
+ private Mono retrieveResponse(WebClient.RequestBodySpec spec) {
+ return spec.retrieve()
+ .bodyToMono(String.class);
+ }
+
+ private Mono retrieveListResponse(WebClient.RequestHeadersSpec> spec) {
+ return spec.accept(MediaType.APPLICATION_JSON)
+ .retrieve()
+ .bodyToMono(ResponseList.class);
+ }
+
+ private Mono retrieveIntegerResponse(WebClient.RequestHeadersSpec> spec) {
+ return spec.retrieve()
+ .bodyToMono(Integer.class);
+ }
+
+ private Flux retrieveStreamingResponse(WebClient.RequestHeadersSpec> spec) {
+ return spec.retrieve()
+ .bodyToFlux(OrderResponse.class);
+ }
+
+ private static class ResponseList extends ArrayList {
+
+ private ResponseList() {
+ super();
+ }
+ }
+}
diff --git a/axon/src/test/java/com/baeldung/axon/querymodel/AbstractOrdersEventHandlerUnitTest.java b/axon/src/test/java/com/baeldung/axon/querymodel/AbstractOrdersEventHandlerUnitTest.java
index 2396d0f10b..fb7833a3f6 100644
--- a/axon/src/test/java/com/baeldung/axon/querymodel/AbstractOrdersEventHandlerUnitTest.java
+++ b/axon/src/test/java/com/baeldung/axon/querymodel/AbstractOrdersEventHandlerUnitTest.java
@@ -12,8 +12,10 @@ import com.baeldung.axon.coreapi.queries.Order;
import com.baeldung.axon.coreapi.queries.OrderStatus;
import com.baeldung.axon.coreapi.queries.OrderUpdatesQuery;
import com.baeldung.axon.coreapi.queries.TotalProductsShippedQuery;
+
import org.axonframework.queryhandling.QueryUpdateEmitter;
import org.junit.jupiter.api.*;
+
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
@@ -27,10 +29,14 @@ import static org.mockito.Mockito.*;
public abstract class AbstractOrdersEventHandlerUnitTest {
- private static final String ORDER_ID_1 = UUID.randomUUID().toString();
- private static final String ORDER_ID_2 = UUID.randomUUID().toString();
- private static final String PRODUCT_ID_1 = UUID.randomUUID().toString();
- private static final String PRODUCT_ID_2 = UUID.randomUUID().toString();
+ private static final String ORDER_ID_1 = UUID.randomUUID()
+ .toString();
+ private static final String ORDER_ID_2 = UUID.randomUUID()
+ .toString();
+ private static final String PRODUCT_ID_1 = UUID.randomUUID()
+ .toString();
+ private static final String PRODUCT_ID_2 = UUID.randomUUID()
+ .toString();
private OrdersEventHandler handler;
private static Order orderOne;
private static Order orderTwo;
@@ -39,12 +45,15 @@ public abstract class AbstractOrdersEventHandlerUnitTest {
@BeforeAll
static void createOrders() {
orderOne = new Order(ORDER_ID_1);
- orderOne.getProducts().put(PRODUCT_ID_1, 3);
+ orderOne.getProducts()
+ .put(PRODUCT_ID_1, 3);
orderOne.setOrderShipped();
orderTwo = new Order(ORDER_ID_2);
- orderTwo.getProducts().put(PRODUCT_ID_1, 1);
- orderTwo.getProducts().put(PRODUCT_ID_2, 1);
+ orderTwo.getProducts()
+ .put(PRODUCT_ID_1, 1);
+ orderTwo.getProducts()
+ .put(PRODUCT_ID_2, 1);
orderTwo.setOrderConfirmed();
}
@@ -64,10 +73,18 @@ public abstract class AbstractOrdersEventHandlerUnitTest {
assertNotNull(result);
assertEquals(2, result.size());
- Order order_1 = result.stream().filter(o -> o.getOrderId().equals(ORDER_ID_1)).findFirst().orElse(null);
+ Order order_1 = result.stream()
+ .filter(o -> o.getOrderId()
+ .equals(ORDER_ID_1))
+ .findFirst()
+ .orElse(null);
assertEquals(orderOne, order_1);
- Order order_2 = result.stream().filter(o -> o.getOrderId().equals(ORDER_ID_2)).findFirst().orElse(null);
+ Order order_2 = result.stream()
+ .filter(o -> o.getOrderId()
+ .equals(ORDER_ID_2))
+ .findFirst()
+ .orElse(null);
assertEquals(orderTwo, order_2);
}
@@ -75,9 +92,11 @@ public abstract class AbstractOrdersEventHandlerUnitTest {
void givenTwoOrdersPlacedOfWhichOneNotShipped_whenFindAllOrderedProductsQueryStreaming_thenCorrectOrdersAreReturned() {
resetWithTwoOrders();
final Consumer orderVerifier = order -> {
- if (order.getOrderId().equals(orderOne.getOrderId())) {
+ if (order.getOrderId()
+ .equals(orderOne.getOrderId())) {
assertEquals(orderOne, order);
- } else if (order.getOrderId().equals(orderTwo.getOrderId())) {
+ } else if (order.getOrderId()
+ .equals(orderTwo.getOrderId())) {
assertEquals(orderTwo, order);
} else {
throw new RuntimeException("Would expect either order one or order two");
@@ -85,10 +104,10 @@ public abstract class AbstractOrdersEventHandlerUnitTest {
};
StepVerifier.create(Flux.from(handler.handleStreaming(new FindAllOrderedProductsQuery())))
- .assertNext(orderVerifier)
- .assertNext(orderVerifier)
- .expectComplete()
- .verify();
+ .assertNext(orderVerifier)
+ .assertNext(orderVerifier)
+ .expectComplete()
+ .verify();
}
@Test
@@ -120,7 +139,8 @@ public abstract class AbstractOrdersEventHandlerUnitTest {
Order result = handler.handle(new OrderUpdatesQuery(ORDER_ID_1));
assertNotNull(result);
assertEquals(ORDER_ID_1, result.getOrderId());
- assertEquals(3, result.getProducts().get(PRODUCT_ID_1));
+ assertEquals(3, result.getProducts()
+ .get(PRODUCT_ID_1));
assertEquals(OrderStatus.SHIPPED, result.getOrderStatus());
}
diff --git a/axon/src/test/java/com/baeldung/axon/querymodel/MongoOrdersEventHandlerUnitTest.java b/axon/src/test/java/com/baeldung/axon/querymodel/MongoOrdersEventHandlerUnitTest.java
new file mode 100644
index 0000000000..c183294dc1
--- /dev/null
+++ b/axon/src/test/java/com/baeldung/axon/querymodel/MongoOrdersEventHandlerUnitTest.java
@@ -0,0 +1,20 @@
+package com.baeldung.axon.querymodel;
+
+import com.mongodb.client.MongoClient;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
+
+@DataMongoTest
+public class MongoOrdersEventHandlerUnitTest extends AbstractOrdersEventHandlerUnitTest {
+
+ @Autowired
+ MongoClient mongoClient;
+
+ @Override
+ protected OrdersEventHandler getHandler() {
+ mongoClient.getDatabase("axonframework")
+ .drop();
+ return new MongoOrdersEventHandler(mongoClient, emitter);
+ }
+}
diff --git a/axon/src/test/java/com/baeldung/axon/querymodel/OrderQueryServiceIntegrationTest.java b/axon/src/test/java/com/baeldung/axon/querymodel/OrderQueryServiceIntegrationTest.java
index dfb4881fdc..4a89fe0e4e 100644
--- a/axon/src/test/java/com/baeldung/axon/querymodel/OrderQueryServiceIntegrationTest.java
+++ b/axon/src/test/java/com/baeldung/axon/querymodel/OrderQueryServiceIntegrationTest.java
@@ -6,7 +6,6 @@ import com.baeldung.axon.coreapi.events.OrderShippedEvent;
import com.baeldung.axon.coreapi.events.ProductAddedEvent;
import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent;
import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent;
-import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
import com.baeldung.axon.coreapi.queries.Order;
import org.axonframework.eventhandling.gateway.EventGateway;
@@ -66,9 +65,9 @@ class OrderQueryServiceIntegrationTest {
void givenOrderCreatedEventSend_whenCallingAllOrdersStreaming_thenOneOrderIsReturned() {
Flux result = queryService.allOrdersStreaming();
StepVerifier.create(result)
- .assertNext(order -> assertEquals(orderId, order.getOrderId()))
- .expectComplete()
- .verify();
+ .assertNext(order -> assertEquals(orderId, order.getOrderId()))
+ .expectComplete()
+ .verify();
}
@Test
diff --git a/axon/src/test/resources/application.properties b/axon/src/test/resources/application.properties
index 35b5452b57..c42b7a4e90 100644
--- a/axon/src/test/resources/application.properties
+++ b/axon/src/test/resources/application.properties
@@ -1 +1,2 @@
+spring.mongodb.embedded.version=5.0.6
axon.axonserver.enabled=false
\ No newline at end of file
diff --git a/axon/start_mongo.sh b/axon/start_mongo.sh
new file mode 100755
index 0000000000..2cc5a3a7cf
--- /dev/null
+++ b/axon/start_mongo.sh
@@ -0,0 +1,7 @@
+docker run \
+ -d \
+ --name order_projection \
+ -p 27017:27017 \
+ -e MONGO_INITDB_ROOT_USERNAME=admin1234 \
+ -e MONGO_INITDB_ROOT_PASSWORD=somepassword \
+ mongo
\ No newline at end of file
diff --git a/azure/pom.xml b/azure/pom.xml
index ae20ae7785..6a06282a71 100644
--- a/azure/pom.xml
+++ b/azure/pom.xml
@@ -36,8 +36,8 @@
runtime
- mysql
- mysql-connector-java
+ com.mysql
+ mysql-connector-j
runtime
diff --git a/core-groovy-modules/core-groovy-2/README.md b/core-groovy-modules/core-groovy-2/README.md
index 9f81ac6c16..f128b43092 100644
--- a/core-groovy-modules/core-groovy-2/README.md
+++ b/core-groovy-modules/core-groovy-2/README.md
@@ -14,4 +14,4 @@ This module contains articles about core Groovy concepts
- [A Quick Guide to Working with Web Services in Groovy](https://www.baeldung.com/groovy-web-services)
- [Categories in Groovy](https://www.baeldung.com/groovy-categories)
- [How to Determine the Data Type in Groovy](https://www.baeldung.com/groovy-determine-data-type)
-- [[<-- Prev]](/core-groovy)
+- [[<-- Prev]](/core-groovy-modules/core-groovy)
diff --git a/core-groovy-modules/core-groovy-2/pom.xml b/core-groovy-modules/core-groovy-2/pom.xml
index a177844a15..ca6a9a62c7 100644
--- a/core-groovy-modules/core-groovy-2/pom.xml
+++ b/core-groovy-modules/core-groovy-2/pom.xml
@@ -83,7 +83,7 @@
org.codehaus.groovy
groovy-eclipse-batch
- ${groovy.version}-01
+ ${groovy-eclipse-batch.version}
@@ -155,16 +155,18 @@
- central
- https://jcenter.bintray.com
+ maven_central
+ Maven Central
+ https://repo.maven.apache.org/maven2/
1.1.3
- 3.1.0
- 3.8.0
- 3.3.0-01
+ 3.4.2
+ 3.8.1
+ 3.7.0
+ 3.0.8-01
-
\ No newline at end of file
+
diff --git a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/BaeldungCategory.groovy b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/BaeldungCategory.groovy
index 479c39699f..ccb1c7fc95 100644
--- a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/BaeldungCategory.groovy
+++ b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/BaeldungCategory.groovy
@@ -1,17 +1,17 @@
-package com.baeldung.category;
+package com.baeldung.category
class BaeldungCategory {
- public static String capitalize(String self) {
- String capitalizedStr = self;
+ static String capitalize(String self) {
+ String capitalizedStr = self
if (self.size() > 0) {
- capitalizedStr = self.substring(0, 1).toUpperCase() + self.substring(1);
+ capitalizedStr = self.substring(0, 1).toUpperCase() + self.substring(1)
}
+
return capitalizedStr
}
-
- public static double toThePower(Number self, Number exponent) {
- return Math.pow(self, exponent);
- }
+ static double toThePower(Number self, Number exponent) {
+ return Math.pow(self, exponent)
+ }
}
diff --git a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/NumberCategory.groovy b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/NumberCategory.groovy
index ccf2ed519b..4f38b87ec5 100644
--- a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/NumberCategory.groovy
+++ b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/category/NumberCategory.groovy
@@ -1,17 +1,15 @@
-package com.baeldung.category;
-
-import groovy.lang.Category
+package com.baeldung.category
@Category(Number)
class NumberCategory {
- public Number cube() {
- return this*this*this
+ Number cube() {
+ return this**3
}
- public int divideWithRoundUp(BigDecimal divisor, boolean isRoundUp) {
+ int divideWithRoundUp(BigDecimal divisor, boolean isRoundUp) {
def mathRound = isRoundUp ? BigDecimal.ROUND_UP : BigDecimal.ROUND_DOWN
- return (int)new BigDecimal(this).divide(divisor, 0, mathRound)
+
+ return (int) new BigDecimal(this).divide(divisor, 0, mathRound)
}
-
}
diff --git a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy
index 3ac88b7952..40c935ce08 100644
--- a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy
+++ b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy
@@ -1,14 +1,19 @@
package com.baeldung.determinedatatype
class Person {
-
- private int ageAsInt
- private Double ageAsDouble
- private String ageAsString
-
+
+ int ageAsInt
+ Double ageAsDouble
+ String ageAsString
+
Person() {}
- Person(int ageAsInt) { this.ageAsInt = ageAsInt}
- Person(Double ageAsDouble) { this.ageAsDouble = ageAsDouble}
- Person(String ageAsString) { this.ageAsString = ageAsString}
+
+ Person(int ageAsInt) { this.ageAsInt = ageAsInt }
+
+ Person(Double ageAsDouble) { this.ageAsDouble = ageAsDouble }
+
+ Person(String ageAsString) { this.ageAsString = ageAsString }
+}
+
+class Student extends Person {
}
-class Student extends Person {}
diff --git a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/Employee.groovy b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/Employee.groovy
index f49d0f906b..cade7dab3c 100644
--- a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/Employee.groovy
+++ b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/Employee.groovy
@@ -1,18 +1,14 @@
package com.baeldung.metaprogramming
-import groovy.transform.AutoClone
-import groovy.transform.Canonical
-import groovy.transform.EqualsAndHashCode
-import groovy.transform.ToString
-import groovy.transform.TupleConstructor
-import groovy.util.logging.*
+import groovy.transform.*
+import groovy.util.logging.Log
-@Canonical
+@ToString(includePackage = false, excludes = ['id'])
@TupleConstructor
@EqualsAndHashCode
-@ToString(includePackage=false, excludes=['id'])
-@Log
-@AutoClone
+@Canonical
+@AutoClone(style = AutoCloneStyle.SIMPLE)
+@Log
class Employee {
long id
@@ -30,16 +26,15 @@ class Employee {
def propertyMissing(String propertyName, propertyValue) {
println "property '$propertyName' is not available"
log.info "$propertyName is not available"
- "property '$propertyName' is not available"
+ "property '$propertyName' with value '$propertyValue' is not available"
}
- def methodMissing(String methodName, def methodArgs) {
+ def methodMissing(String methodName, Object methodArgs) {
log.info "$methodName is not defined"
"method '$methodName' is not defined"
}
-
+
def logEmp() {
log.info "Employee: $lastName, $firstName is of $age years age"
}
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/extension/BasicExtensions.groovy b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/extension/BasicExtensions.groovy
index 0612ecb955..7e9f0111cd 100644
--- a/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/extension/BasicExtensions.groovy
+++ b/core-groovy-modules/core-groovy-2/src/main/groovy/com/baeldung/metaprogramming/extension/BasicExtensions.groovy
@@ -2,32 +2,31 @@ package com.baeldung.metaprogramming.extension
import com.baeldung.metaprogramming.Employee
-import java.time.LocalDate
import java.time.Year
class BasicExtensions {
-
+
static int getYearOfBirth(Employee self) {
return Year.now().value - self.age
}
-
+
static String capitalize(String self) {
return self.substring(0, 1).toUpperCase() + self.substring(1)
}
static void printCounter(Integer self) {
- while (self>0) {
+ while (self > 0) {
println self
self--
}
}
-
+
static Long square(Long self) {
- return self*self
+ return self * self
}
-
+
static BigDecimal cube(BigDecimal self) {
- return self*self*self
+ return self * self * self
}
-
-}
\ No newline at end of file
+
+}
diff --git a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/category/CategoryUnitTest.groovy b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/category/CategoryUnitTest.groovy
index a1f67b1e2e..370dfb316e 100644
--- a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/category/CategoryUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/category/CategoryUnitTest.groovy
@@ -1,17 +1,17 @@
package com.baeldung.category
-import groovy.time.*
+import groovy.time.TimeCategory
+import groovy.xml.DOMBuilder
+import groovy.xml.QName
+import groovy.xml.dom.DOMCategory
+
import java.text.SimpleDateFormat
-import groovy.xml.*
-import groovy.xml.dom.*
-import com.baeldung.category.BaeldungCategory
-import com.baeldung.category.NumberCategory
class CategoryUnitTest extends GroovyTestCase {
void test_whenUsingTimeCategory_thenOperationOnDate() {
def jan_1_2019 = new Date("01/01/2019")
- use (TimeCategory) {
+ use(TimeCategory) {
assert jan_1_2019 + 10.seconds == new Date("01/01/2019 00:00:10")
assert jan_1_2019 + 20.minutes == new Date("01/01/2019 00:20:00")
@@ -30,7 +30,7 @@ class CategoryUnitTest extends GroovyTestCase {
void test_whenUsingTimeCategory_thenOperationOnNumber() {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy")
- use (TimeCategory) {
+ use(TimeCategory) {
assert sdf.format(5.days.from.now) == sdf.format(new Date() + 5.days)
sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss")
@@ -57,7 +57,7 @@ class CategoryUnitTest extends GroovyTestCase {
def root = baeldungArticlesDom.documentElement
- use (DOMCategory) {
+ use(DOMCategory) {
assert root.article.size() == 2
def articles = root.article
@@ -75,27 +75,26 @@ class CategoryUnitTest extends GroovyTestCase {
assert root.article[2].title.text() == "Metaprogramming in Groovy"
}
}
-
+
void test_whenUsingBaeldungCategory_thenCapitalizeString() {
- use (BaeldungCategory) {
+ use(BaeldungCategory) {
assert "norman".capitalize() == "Norman"
- }
+ }
}
-
+
void test_whenUsingBaeldungCategory_thenOperationsOnNumber() {
- use (BaeldungCategory) {
+ use(BaeldungCategory) {
assert 50.toThePower(2) == 2500
assert 2.4.toThePower(4) == 33.1776
}
}
-
+
void test_whenUsingNumberCategory_thenOperationsOnNumber() {
- use (NumberCategory) {
+ use(NumberCategory) {
assert 3.cube() == 27
assert 25.divideWithRoundUp(6, true) == 5
assert 120.23.divideWithRoundUp(6.1, true) == 20
assert 150.9.divideWithRoundUp(12.1, false) == 12
}
}
-
}
diff --git a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy
index 4c6589f207..414ba52fc5 100644
--- a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy
+++ b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy
@@ -1,56 +1,68 @@
package com.baeldung.determinedatatype
-import org.junit.Assert
-import org.junit.Test
-import com.baeldung.determinedatatype.Person
+import spock.lang.Specification
-public class PersonTest {
-
- @Test
- public void givenWhenParameterTypeIsInteger_thenReturnTrue() {
+class PersonTest extends Specification {
+
+ def "givenWhenParameterTypeIsIntegerThenReturnTrue"() {
+ given:
Person personObj = new Person(10)
- Assert.assertTrue(personObj.ageAsInt instanceof Integer)
- }
-
- @Test
- public void givenWhenParameterTypeIsDouble_thenReturnTrue() {
- Person personObj = new Person(10.0)
- Assert.assertTrue((personObj.ageAsDouble).getClass() == Double)
- }
-
- @Test
- public void givenWhenParameterTypeIsString_thenReturnTrue() {
- Person personObj = new Person("10 years")
- Assert.assertTrue(personObj.ageAsString.class == String)
- }
-
- @Test
- public void givenClassName_WhenParameterIsInteger_thenReturnTrue() {
- Assert.assertTrue(Person.class.getDeclaredField('ageAsInt').type == int.class)
- }
-
- @Test
- public void givenWhenObjectIsInstanceOfType_thenReturnTrue() {
- Person personObj = new Person()
- Assert.assertTrue(personObj instanceof Person)
+
+ expect:
+ personObj.ageAsInt.class == Integer
}
- @Test
- public void givenWhenInstanceIsOfSubtype_thenReturnTrue() {
+ def "givenWhenParameterTypeIsDouble_thenReturnTrue"() {
+ given:
+ Person personObj = new Person(10.0)
+
+ expect:
+ personObj.ageAsDouble.class == Double
+ }
+
+ def "givenWhenParameterTypeIsString_thenReturnTrue"() {
+ given:
+ Person personObj = new Person("10 years")
+
+ expect:
+ personObj.ageAsString.class == String
+ }
+
+ def "givenClassName_WhenParameterIsInteger_thenReturnTrue"() {
+ expect:
+ Person.class.getDeclaredField('ageAsInt').type == int.class
+ }
+
+ def "givenWhenObjectIsInstanceOfType_thenReturnTrue"() {
+ given:
+ Person personObj = new Person()
+
+ expect:
+ personObj.class == Person
+ }
+
+ def "givenWhenInstanceIsOfSubtype_thenReturnTrue"() {
+ given:
Student studentObj = new Student()
- Assert.assertTrue(studentObj in Person)
+
+ expect:
+ studentObj.class.superclass == Person
}
-
- @Test
- public void givenGroovyList_WhenFindClassName_thenReturnTrue() {
- def ageList = ['ageAsString','ageAsDouble', 10]
- Assert.assertTrue(ageList.class == ArrayList)
- Assert.assertTrue(ageList.getClass() == ArrayList)
+
+ def "givenGroovyList_WhenFindClassName_thenReturnTrue"() {
+ given:
+ def ageList = ['ageAsString', 'ageAsDouble', 10]
+
+ expect:
+ ageList.class == ArrayList
+ ageList.getClass() == ArrayList
}
-
- @Test
- public void givenGrooyMap_WhenFindClassName_thenReturnTrue() {
- def ageMap = [ageAsString: '10 years', ageAsDouble: 10.0]
- Assert.assertFalse(ageMap.class == LinkedHashMap)
+
+ def "givenGroovyMap_WhenFindClassName_thenReturnTrue"() {
+ given:
+ def ageMap = [ageAsString: '10 years', ageAsDouble: 10.0]
+
+ expect:
+ ageMap.getClass() == LinkedHashMap
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/metaprogramming/MetaprogrammingUnitTest.groovy b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/metaprogramming/MetaprogrammingUnitTest.groovy
index 4a8631eb95..6959c97533 100644
--- a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/metaprogramming/MetaprogrammingUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/metaprogramming/MetaprogrammingUnitTest.groovy
@@ -1,123 +1,163 @@
package com.baeldung.metaprogramming
+import spock.lang.Specification
-import java.time.LocalDate
-import java.time.Period
import java.time.Year
-class MetaprogrammingUnitTest extends GroovyTestCase {
+class MetaprogrammingUnitTest extends Specification {
- Employee emp = new Employee(firstName: "Norman", lastName: "Lewis")
+ Employee emp
- void testPropertyMissing() {
- assert emp.address == "property 'address' is not available"
+ void setup() {
+ emp = new Employee(firstName: "Norman", lastName: "Lewis")
}
- void testMethodMissing() {
+ def "testPropertyMissing"() {
+ expect:
+ emp.address == "property 'address' is not available"
+ }
+
+ def "testMethodMissing"() {
+ given:
Employee emp = new Employee()
- try {
- emp.getFullName()
- } catch(MissingMethodException e) {
- println "method is not defined"
- }
- assert emp.getFullName() == "method 'getFullName' is not defined"
+
+ expect:
+ emp.getFullName() == "method 'getFullName' is not defined"
}
- void testMetaClassProperty() {
+ def "testMetaClassProperty"() {
+ when:
Employee.metaClass.address = ""
- emp = new Employee(firstName: "Norman", lastName: "Lewis", address: "US")
- assert emp.address == "US"
+
+ and:
+ emp = new Employee(firstName: "Norman",
+ lastName: "Lewis",
+ address: "US")
+
+ then:
+ emp.address == "US"
}
- void testMetaClassMethod() {
+ def "testMetaClassMethod"() {
+ when:
emp.metaClass.getFullName = {
"$lastName, $firstName"
}
- assert emp.getFullName() == "Lewis, Norman"
+
+ then:
+ emp.getFullName() == "Lewis, Norman"
}
- void testMetaClassConstructor() {
- try {
- Employee emp = new Employee("Norman")
- } catch(GroovyRuntimeException e) {
- assert e.message == "Could not find matching constructor for: com.baeldung.metaprogramming.Employee(String)"
- }
+ def "testOnlyNameConstructor"() {
+ when:
+ new Employee("Norman")
+ then:
+ thrown(GroovyRuntimeException)
+ }
+
+ def "testMetaClassConstructor"() {
+ when:
Employee.metaClass.constructor = { String firstName ->
new Employee(firstName: firstName)
}
+ and:
Employee norman = new Employee("Norman")
- assert norman.firstName == "Norman"
- assert norman.lastName == null
+
+ then:
+ norman.firstName == "Norman"
+ norman.lastName == null
}
- void testJavaMetaClass() {
+ def "testJavaMetaClass"() {
+ when:
String.metaClass.capitalize = { String str ->
str.substring(0, 1).toUpperCase() + str.substring(1)
}
- assert "norman".capitalize() == "Norman"
+
+ and:
+ String.metaClass.static.joinWith = { String delimiter, String... args ->
+ String.join(delimiter, args)
+ }
+
+ then:
+ "norman".capitalize() == "Norman"
+ String.joinWith(" -> ", "a", "b", "c") == "a -> b -> c"
}
- void testEmployeeExtension() {
+ def "testEmployeeExtension"() {
+ given:
def age = 28
def expectedYearOfBirth = Year.now() - age
Employee emp = new Employee(age: age)
- assert emp.getYearOfBirth() == expectedYearOfBirth.value
+
+ expect:
+ emp.getYearOfBirth() == expectedYearOfBirth.value
}
- void testJavaClassesExtensions() {
+ def "testJavaClassesExtensions"() {
+ when:
5.printCounter()
- assert 40l.square() == 1600l
-
- assert (2.98).cube() == 26.463592
+ then:
+ 40L.square() == 1600L
+ (2.98).cube() == 26.463592
}
- void testStaticEmployeeExtension() {
+ def "testStaticEmployeeExtension"() {
assert Employee.getDefaultObj().firstName == "firstName"
assert Employee.getDefaultObj().lastName == "lastName"
assert Employee.getDefaultObj().age == 20
}
- void testToStringAnnotation() {
- Employee employee = new Employee()
- employee.id = 1
- employee.firstName = "norman"
- employee.lastName = "lewis"
- employee.age = 28
+ def "testToStringAnnotation"() {
+ when:
+ Employee employee = new Employee().tap {
+ id = 1
+ firstName = "norman"
+ lastName = "lewis"
+ age = 28
+ }
- assert employee.toString() == "Employee(norman, lewis, 28)"
+ then:
+ employee.toString() == "Employee(norman, lewis, 28)"
}
- void testTupleConstructorAnnotation() {
+ def "testTupleConstructorAnnotation"() {
+ when:
Employee norman = new Employee(1, "norman", "lewis", 28)
- assert norman.toString() == "Employee(norman, lewis, 28)"
-
Employee snape = new Employee(2, "snape")
- assert snape.toString() == "Employee(snape, null, 0)"
+ then:
+ norman.toString() == "Employee(norman, lewis, 28)"
+ snape.toString() == "Employee(snape, null, 0)"
}
-
- void testEqualsAndHashCodeAnnotation() {
+
+ def "testEqualsAndHashCodeAnnotation"() {
+ when:
Employee norman = new Employee(1, "norman", "lewis", 28)
Employee normanCopy = new Employee(1, "norman", "lewis", 28)
- assert norman.equals(normanCopy)
- assert norman.hashCode() == normanCopy.hashCode()
- }
-
- void testAutoCloneAnnotation() {
- try {
- Employee norman = new Employee(1, "norman", "lewis", 28)
- def normanCopy = norman.clone()
- assert norman == normanCopy
- } catch(CloneNotSupportedException e) {
- e.printStackTrace()
- }
+
+ then:
+ norman == normanCopy
+ norman.hashCode() == normanCopy.hashCode()
}
- void testLoggingAnnotation() {
+ def "testAutoCloneAnnotation"() {
+ given:
+ Employee norman = new Employee(1, "norman", "lewis", 28)
+
+ when:
+ def normanCopy = norman.clone()
+
+ then:
+ norman == normanCopy
+ }
+
+ def "testLoggingAnnotation"() {
+ given:
Employee employee = new Employee(1, "Norman", "Lewis", 28)
- employee.logEmp()
+ employee.logEmp() // INFO: Employee: Lewis, Norman is of 28 years age
}
}
diff --git a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy
index 1846ae664c..800f3b119e 100644
--- a/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy
@@ -1,48 +1,62 @@
package com.baeldung.templateengine
+import groovy.text.GStringTemplateEngine
import groovy.text.SimpleTemplateEngine
import groovy.text.StreamingTemplateEngine
-import groovy.text.GStringTemplateEngine
-import groovy.text.XmlTemplateEngine
import groovy.text.XmlTemplateEngine
import groovy.text.markup.MarkupTemplateEngine
import groovy.text.markup.TemplateConfiguration
+import spock.lang.Specification
-class TemplateEnginesUnitTest extends GroovyTestCase {
-
- def bindMap = [user: "Norman", signature: "Baeldung"]
-
- void testSimpleTemplateEngine() {
+class TemplateEnginesUnitTest extends Specification {
+
+ final Map BIND_MAP = [user: "Norman", signature: "Baeldung"]
+
+ def "testSimpleTemplateEngine"() {
+ given:
def smsTemplate = 'Dear <% print user %>, Thanks for reading our Article. ${signature}'
- def smsText = new SimpleTemplateEngine().createTemplate(smsTemplate).make(bindMap)
- assert smsText.toString() == "Dear Norman, Thanks for reading our Article. Baeldung"
+ when:
+ def smsText = new SimpleTemplateEngine().createTemplate(smsTemplate).make(BIND_MAP)
+
+ then:
+ smsText.toString() == "Dear Norman, Thanks for reading our Article. Baeldung"
}
-
- void testStreamingTemplateEngine() {
+
+ def "testStreamingTemplateEngine"() {
+ given:
def articleEmailTemplate = new File('src/main/resources/articleEmail.template')
- bindMap.articleText = """1. Overview
-This is a tutorial article on Template Engines""" //can be a string larger than 64k
-
- def articleEmailText = new StreamingTemplateEngine().createTemplate(articleEmailTemplate).make(bindMap)
-
- assert articleEmailText.toString() == """Dear Norman,
-Please read the requested article below.
-1. Overview
-This is a tutorial article on Template Engines
-From,
-Baeldung"""
-
+ //can be a string larger than 64k
+ BIND_MAP.articleText = """|1. Overview
+ |This is a tutorial article on Template Engines""".stripMargin()
+
+ when:
+ def articleEmailText = new StreamingTemplateEngine().createTemplate(articleEmailTemplate).make(BIND_MAP)
+
+ then:
+ articleEmailText.toString() == """|Dear Norman,
+ |Please read the requested article below.
+ |1. Overview
+ |This is a tutorial article on Template Engines
+ |From,
+ |Baeldung""".stripMargin()
}
-
- void testGStringTemplateEngine() {
+
+ def "testGStringTemplateEngine"() {
+ given:
def emailTemplate = new File('src/main/resources/email.template')
- def emailText = new GStringTemplateEngine().createTemplate(emailTemplate).make(bindMap)
-
- assert emailText.toString() == "Dear Norman,\nThanks for subscribing our services.\nBaeldung"
+
+ when:
+ def emailText = new GStringTemplateEngine().createTemplate(emailTemplate).make(BIND_MAP)
+
+ then:
+ emailText.toString() == """|Dear Norman,
+ |Thanks for subscribing our services.
+ |Baeldung""".stripMargin()
}
-
- void testXmlTemplateEngine() {
+
+ def "testXmlTemplateEngine"() {
+ given:
def emailXmlTemplate = '''
def emailContent = "Thanks for subscribing our services."
@@ -51,11 +65,16 @@ Baeldung"""
${signature}
'''
- def emailXml = new XmlTemplateEngine().createTemplate(emailXmlTemplate).make(bindMap)
+
+ when:
+ def emailXml = new XmlTemplateEngine().createTemplate(emailXmlTemplate).make(BIND_MAP)
+
+ then:
println emailXml.toString()
}
-
- void testMarkupTemplateEngineHtml() {
+
+ def "testMarkupTemplateEngineHtml"() {
+ given:
def emailHtmlTemplate = """html {
head {
title('Service Subscription Email')
@@ -66,14 +85,16 @@ Baeldung"""
p('Baeldung')
}
}"""
-
-
+
+ when:
def emailHtml = new MarkupTemplateEngine().createTemplate(emailHtmlTemplate).make()
+
+ then:
println emailHtml.toString()
-
}
-
- void testMarkupTemplateEngineXml() {
+
+ def "testMarkupTemplateEngineXml"() {
+ given:
def emailXmlTemplate = """xmlDeclaration()
xs{
email {
@@ -83,14 +104,18 @@ Baeldung"""
}
}
"""
- TemplateConfiguration config = new TemplateConfiguration()
- config.autoIndent = true
- config.autoEscape = true
- config.autoNewLine = true
+ TemplateConfiguration config = new TemplateConfiguration().with {
+ autoIndent = true
+ autoEscape = true
+ autoNewLine = true
+ return it
+ }
+
+ when:
def emailXml = new MarkupTemplateEngine(config).createTemplate(emailXmlTemplate).make()
-
+
+ then:
println emailXml.toString()
}
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy-collections/pom.xml b/core-groovy-modules/core-groovy-collections/pom.xml
index 5269121140..6d43ce7d18 100644
--- a/core-groovy-modules/core-groovy-collections/pom.xml
+++ b/core-groovy-modules/core-groovy-collections/pom.xml
@@ -113,9 +113,11 @@
- central
- http://jcenter.bintray.com
+ maven_central
+ Maven Central
+ https://repo.maven.apache.org/maven2/
-
\ No newline at end of file
+
+
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/ListFindUnitTest.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/ListFindUnitTest.groovy
index 82a2138be4..325cf18c5f 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/ListFindUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/ListFindUnitTest.groovy
@@ -1,58 +1,57 @@
package com.baeldung.find
-import com.baeldung.find.Person
-import org.junit.Test
+import spock.lang.Specification
-import static org.junit.Assert.*
+class ListFindUnitTest extends Specification {
-class ListFindUnitTest {
-
- private final personList = [
- new Person("Regina", "Fitzpatrick", 25),
- new Person("Abagail", "Ballard", 26),
- new Person("Lucian", "Walter", 30),
+ final personList = [
+ new Person("Regina", "Fitzpatrick", 25),
+ new Person("Abagail", "Ballard", 26),
+ new Person("Lucian", "Walter", 30),
]
- @Test
- void whenListContainsElement_thenCheckReturnsTrue() {
+ def "whenListContainsElement_thenCheckReturnsTrue"() {
+ given:
def list = ['a', 'b', 'c']
- assertTrue(list.indexOf('a') > -1)
- assertTrue(list.contains('a'))
+ expect:
+ list.indexOf('a') > -1
+ list.contains('a')
}
- @Test
- void whenListContainsElement_thenCheckWithMembershipOperatorReturnsTrue() {
+ def "whenListContainsElement_thenCheckWithMembershipOperatorReturnsTrue"() {
+ given:
def list = ['a', 'b', 'c']
- assertTrue('a' in list)
+ expect:
+ 'a' in list
}
- @Test
- void givenListOfPerson_whenUsingStreamMatching_thenShouldEvaluateList() {
- assertTrue(personList.stream().anyMatch {it.age > 20})
- assertFalse(personList.stream().allMatch {it.age < 30})
+ def "givenListOfPerson_whenUsingStreamMatching_thenShouldEvaluateList"() {
+ expect:
+ personList.stream().anyMatch { it.age > 20 }
+ !personList.stream().allMatch { it.age < 30 }
}
- @Test
- void givenListOfPerson_whenUsingCollectionMatching_thenShouldEvaluateList() {
- assertTrue(personList.any {it.age > 20})
- assertFalse(personList.every {it.age < 30})
+ def "givenListOfPerson_whenUsingCollectionMatching_thenShouldEvaluateList"() {
+ expect:
+ personList.any { it.age > 20 }
+ !personList.every { it.age < 30 }
}
- @Test
- void givenListOfPerson_whenUsingStreamFind_thenShouldReturnMatchingElements() {
- assertTrue(personList.stream().filter {it.age > 20}.findAny().isPresent())
- assertFalse(personList.stream().filter {it.age > 30}.findAny().isPresent())
- assertTrue(personList.stream().filter {it.age > 20}.findAll().size() == 3)
- assertTrue(personList.stream().filter {it.age > 30}.findAll().isEmpty())
+ def "givenListOfPerson_whenUsingStreamFind_thenShouldReturnMatchingElements"() {
+ expect:
+ personList.stream().filter { it.age > 20 }.findAny().isPresent()
+ !personList.stream().filter { it.age > 30 }.findAny().isPresent()
+ personList.stream().filter { it.age > 20 }.findAll().size() == 3
+ personList.stream().filter { it.age > 30 }.findAll().isEmpty()
}
- @Test
- void givenListOfPerson_whenUsingCollectionFind_thenShouldReturnMatchingElements() {
- assertNotNull(personList.find {it.age > 20})
- assertNull(personList.find {it.age > 30})
- assertTrue(personList.findAll {it.age > 20}.size() == 3)
- assertTrue(personList.findAll {it.age > 30}.isEmpty())
+ def "givenListOfPerson_whenUsingCollectionFind_thenShouldReturnMatchingElements"() {
+ expect:
+ personList.find { it.age > 20 } == new Person("Regina", "Fitzpatrick", 25)
+ personList.find { it.age > 30 } == null
+ personList.findAll { it.age > 20 }.size() == 3
+ personList.findAll { it.age > 30 }.isEmpty()
}
}
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/MapFindUnitTest.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/MapFindUnitTest.groovy
index 16e231182b..74d85ad71b 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/MapFindUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/MapFindUnitTest.groovy
@@ -1,76 +1,81 @@
package com.baeldung.find
-import com.baeldung.find.Person
-import org.junit.Test
+import spock.lang.Specification
-import static org.junit.Assert.*
+class MapFindUnitTest extends Specification {
-class MapFindUnitTest {
-
- private final personMap = [
- Regina : new Person("Regina", "Fitzpatrick", 25),
- Abagail: new Person("Abagail", "Ballard", 26),
- Lucian : new Person("Lucian", "Walter", 30)
+ final personMap = [
+ Regina: new Person("Regina", "Fitzpatrick", 25),
+ Abagail: new Person("Abagail", "Ballard", 26),
+ Lucian: new Person("Lucian", "Walter", 30)
]
- @Test
- void whenMapContainsKeyElement_thenCheckReturnsTrue() {
+ def "whenMapContainsKeyElement_thenCheckReturnsTrue"() {
+ given:
def map = [a: 'd', b: 'e', c: 'f']
- assertTrue(map.containsKey('a'))
- assertFalse(map.containsKey('e'))
- assertTrue(map.containsValue('e'))
+ expect:
+ map.containsKey('a')
+ !map.containsKey('e')
+ map.containsValue('e')
}
- @Test
- void whenMapContainsKeyElement_thenCheckByMembershipReturnsTrue() {
+ def "whenMapContainsKeyElement_thenCheckByMembershipReturnsTrue"() {
+ given:
def map = [a: 'd', b: 'e', c: 'f']
- assertTrue('a' in map)
- assertFalse('f' in map)
+ expect:
+ 'a' in map
+ 'f' !in map
}
- @Test
- void whenMapContainsFalseBooleanValues_thenCheckReturnsFalse() {
+ def "whenMapContainsFalseBooleanValues_thenCheckReturnsFalse"() {
+ given:
def map = [a: true, b: false, c: null]
- assertTrue(map.containsKey('b'))
- assertTrue('a' in map)
- assertFalse('b' in map)
- assertFalse('c' in map)
+ expect:
+ map.containsKey('b')
+ 'a' in map
+ 'b' !in map // get value of key 'b' and does the assertion
+ 'c' !in map
}
- @Test
- void givenMapOfPerson_whenUsingStreamMatching_thenShouldEvaluateMap() {
- assertTrue(personMap.keySet().stream().anyMatch {it == "Regina"})
- assertFalse(personMap.keySet().stream().allMatch {it == "Albert"})
- assertFalse(personMap.values().stream().allMatch {it.age < 30})
- assertTrue(personMap.entrySet().stream().anyMatch {it.key == "Abagail" && it.value.lastname == "Ballard"})
+ def "givenMapOfPerson_whenUsingStreamMatching_thenShouldEvaluateMap"() {
+ expect:
+ personMap.keySet().stream()
+ .anyMatch { it == "Regina" }
+ !personMap.keySet().stream()
+ .allMatch { it == "Albert" }
+ !personMap.values().stream()
+ .allMatch { it.age < 30 }
+ personMap.entrySet().stream()
+ .anyMatch { it.key == "Abagail" && it.value.lastname == "Ballard" }
}
- @Test
- void givenMapOfPerson_whenUsingCollectionMatching_thenShouldEvaluateMap() {
- assertTrue(personMap.keySet().any {it == "Regina"})
- assertFalse(personMap.keySet().every {it == "Albert"})
- assertFalse(personMap.values().every {it.age < 30})
- assertTrue(personMap.any {firstname, person -> firstname == "Abagail" && person.lastname == "Ballard"})
+ def "givenMapOfPerson_whenUsingCollectionMatching_thenShouldEvaluateMap"() {
+ expect:
+ personMap.keySet().any { it == "Regina" }
+ !personMap.keySet().every { it == "Albert" }
+ !personMap.values().every { it.age < 30 }
+ personMap.any { firstname, person -> firstname == "Abagail" && person.lastname == "Ballard" }
}
- @Test
- void givenMapOfPerson_whenUsingCollectionFind_thenShouldReturnElements() {
- assertNotNull(personMap.find {it.key == "Abagail" && it.value.lastname == "Ballard"})
- assertTrue(personMap.findAll {it.value.age > 20}.size() == 3)
+ def "givenMapOfPerson_whenUsingCollectionFind_thenShouldReturnElements"() {
+ expect:
+ personMap.find { it.key == "Abagail" && it.value.lastname == "Ballard" }
+ personMap.findAll { it.value.age > 20 }.size() == 3
}
- @Test
- void givenMapOfPerson_whenUsingStreamFind_thenShouldReturnElements() {
- assertTrue(
- personMap.entrySet().stream()
- .filter {it.key == "Abagail" && it.value.lastname == "Ballard"}
- .findAny().isPresent())
- assertTrue(
- personMap.entrySet().stream()
- .filter {it.value.age > 20}
- .findAll().size() == 3)
+ def "givenMapOfPerson_whenUsingStreamFind_thenShouldReturnElements"() {
+ expect:
+ personMap.entrySet().stream()
+ .filter { it.key == "Abagail" && it.value.lastname == "Ballard" }
+ .findAny()
+ .isPresent()
+
+ personMap.entrySet().stream()
+ .filter { it.value.age > 20 }
+ .findAll()
+ .size() == 3
}
}
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/Person.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/Person.groovy
index e65826363a..a9266c4079 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/Person.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/Person.groovy
@@ -1,37 +1,10 @@
package com.baeldung.find
+import groovy.transform.Canonical
+
+@Canonical
class Person {
- private String firstname
- private String lastname
- private Integer age
-
- Person(String firstname, String lastname, Integer age) {
- this.firstname = firstname
- this.lastname = lastname
- this.age = age
- }
-
- String getFirstname() {
- return firstname
- }
-
- void setFirstname(String firstname) {
- this.firstname = firstname
- }
-
- String getLastname() {
- return lastname
- }
-
- void setLastname(String lastname) {
- this.lastname = lastname
- }
-
- Integer getAge() {
- return age
- }
-
- void setAge(Integer age) {
- this.age = age
- }
+ String firstname
+ String lastname
+ Integer age
}
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/SetFindUnitTest.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/SetFindUnitTest.groovy
index d2d03d5427..d82cf689d3 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/SetFindUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/find/SetFindUnitTest.groovy
@@ -1,16 +1,15 @@
package com.baeldung.find
-import org.junit.Test
+import spock.lang.Specification
-import static org.junit.Assert.assertTrue
+class SetFindUnitTest extends Specification {
-class SetFindUnitTest {
-
- @Test
- void whenSetContainsElement_thenCheckReturnsTrue() {
+ def "whenSetContainsElement_thenCheckReturnsTrue"() {
+ given:
def set = ['a', 'b', 'c'] as Set
- assertTrue(set.contains('a'))
- assertTrue('a' in set)
+ expect:
+ set.contains('a')
+ 'a' in set
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/iteratemap/IterateMapUnitTest.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/iteratemap/IterateMapUnitTest.groovy
index 970203ce85..4cbcaee2d8 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/iteratemap/IterateMapUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/iteratemap/IterateMapUnitTest.groovy
@@ -1,85 +1,54 @@
package com.baeldung.iteratemap
-import com.baeldung.find.Person
-import org.junit.Test
+import spock.lang.Specification
-import static org.junit.Assert.*
+class IterateMapUnitTest extends Specification {
-class IterateMapUnitTest {
-
- @Test
- void whenUsingEach_thenMapIsIterated() {
- def map = [
- 'FF0000' : 'Red',
- '00FF00' : 'Lime',
- '0000FF' : 'Blue',
- 'FFFF00' : 'Yellow'
- ]
+ final Map map = [
+ 'FF0000': 'Red',
+ '00FF00': 'Lime',
+ '0000FF': 'Blue',
+ 'FFFF00': 'Yellow',
+ 'E6E6FA': 'Lavender',
+ 'D8BFD8': 'Thistle',
+ 'DDA0DD': 'Plum',
+ ]
+ def "whenUsingEach_thenMapIsIterated"() {
+ expect:
map.each { println "Hex Code: $it.key = Color Name: $it.value" }
}
- @Test
- void whenUsingEachWithEntry_thenMapIsIterated() {
- def map = [
- 'E6E6FA' : 'Lavender',
- 'D8BFD8' : 'Thistle',
- 'DDA0DD' : 'Plum',
- ]
-
+ def "whenUsingEachWithEntry_thenMapIsIterated"() {
+ expect:
map.each { entry -> println "Hex Code: $entry.key = Color Name: $entry.value" }
}
- @Test
- void whenUsingEachWithKeyAndValue_thenMapIsIterated() {
- def map = [
- '000000' : 'Black',
- 'FFFFFF' : 'White',
- '808080' : 'Gray'
- ]
-
+ def "whenUsingEachWithKeyAndValue_thenMapIsIterated"() {
+ expect:
map.each { key, val ->
println "Hex Code: $key = Color Name $val"
}
}
- @Test
- void whenUsingEachWithIndexAndEntry_thenMapIsIterated() {
- def map = [
- '800080' : 'Purple',
- '4B0082' : 'Indigo',
- '6A5ACD' : 'Slate Blue'
- ]
-
+ def "whenUsingEachWithIndexAndEntry_thenMapIsIterated"() {
+ expect:
map.eachWithIndex { entry, index ->
- def indent = ((index == 0 || index % 2 == 0) ? " " : "")
+ def indent = index % 2 == 0 ? " " : ""
println "$indent Hex Code: $entry.key = Color Name: $entry.value"
}
}
- @Test
- void whenUsingEachWithIndexAndKeyAndValue_thenMapIsIterated() {
- def map = [
- 'FFA07A' : 'Light Salmon',
- 'FF7F50' : 'Coral',
- 'FF6347' : 'Tomato',
- 'FF4500' : 'Orange Red'
- ]
-
+ def "whenUsingEachWithIndexAndKeyAndValue_thenMapIsIterated"() {
+ expect:
map.eachWithIndex { key, val, index ->
- def indent = ((index == 0 || index % 2 == 0) ? " " : "")
+ def indent = index % 2 == 0 ? " " : ""
println "$indent Hex Code: $key = Color Name: $val"
}
}
- @Test
- void whenUsingForLoop_thenMapIsIterated() {
- def map = [
- '2E8B57' : 'Seagreen',
- '228B22' : 'Forest Green',
- '008000' : 'Green'
- ]
-
+ def "whenUsingForLoop_thenMapIsIterated"() {
+ expect:
for (entry in map) {
println "Hex Code: $entry.key = Color Name: $entry.value"
}
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy
index e4c0a0c177..5baa19f360 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy
@@ -1,173 +1,171 @@
package com.baeldung.lists
-import static groovy.test.GroovyAssert.*
-import org.junit.Test
+import spock.lang.Specification
-class ListUnitTest {
-
- @Test
- void testCreateList() {
+class ListUnitTest extends Specification {
+ def "testCreateList"() {
+ when:
def list = [1, 2, 3]
- assertNotNull(list)
-
def listMix = ['A', "b", 1, true]
- assertTrue(listMix == ['A', "b", 1, true])
-
def linkedList = [1, 2, 3] as LinkedList
- assertTrue(linkedList instanceof LinkedList)
-
ArrayList arrList = [1, 2, 3]
- assertTrue(arrList.class == ArrayList)
-
def copyList = new ArrayList(arrList)
- assertTrue(copyList == arrList)
-
def cloneList = arrList.clone()
- assertTrue(cloneList == arrList)
+
+ then:
+ list
+ listMix == ['A', "b", 1, true]
+ linkedList instanceof LinkedList
+ arrList.class == ArrayList
+ copyList == arrList
+ cloneList == arrList
}
- @Test
- void testCreateEmptyList() {
-
+ def "testCreateEmptyList"() {
+ when:
def emptyList = []
- assertTrue(emptyList.size() == 0)
+
+ then:
+ emptyList.isEmpty()
}
- @Test
- void testCompareTwoLists() {
-
+ def "testCompareTwoLists"() {
+ when:
def list1 = [5, 6.0, 'p']
def list2 = [5, 6.0, 'p']
- assertTrue(list1 == list2)
+
+ then:
+ list1 == list2
}
- @Test
- void testGetItemsFromList(){
-
+ def "testGetItemsFromList"() {
+ when:
def list = ["Hello", "World"]
- assertTrue(list.get(1) == "World")
- assertTrue(list[1] == "World")
- assertTrue(list[-1] == "World")
- assertTrue(list.getAt(1) == "World")
- assertTrue(list.getAt(-2) == "Hello")
+ then:
+ list.get(1) == "World"
+ list[1] == "World"
+ list[-1] == "World"
+ list.getAt(1) == "World"
+ list.getAt(-2) == "Hello"
}
- @Test
- void testAddItemsToList() {
+ def "testAddItemsToList"() {
+ given:
+ def list1 = []
+ def list2 = []
+ def list3 = [1, 2]
- def list = []
+ when:
+ list1 << 1 // [1]
+ list1.add("Apple") // [1, "Apple"]
- list << 1
- list.add("Apple")
- assertTrue(list == [1, "Apple"])
+ list2[2] = "Box" // [null, "Box"]
+ list2[4] = true // [null, "Box", null, true]
- list[2] = "Box"
- list[4] = true
- assertTrue(list == [1, "Apple", "Box", null, true])
+ list1.add(1, 6.0) // [1, 6.0, "Apple"]
+ list1 += list3 // [1, 6.0, "Apple", 1, 2]
+ list1 += 12 // [1, 6.0, "Apple", 1, 2, 12]
- list.add(1, 6.0)
- assertTrue(list == [1, 6.0, "Apple", "Box", null, true])
-
- def list2 = [1, 2]
- list += list2
- list += 12
- assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12])
+ then:
+ list1 == [1, 6.0, "Apple", 1, 2, 12]
+ list2 == [null, null, "Box", null, true]
}
- @Test
- void testUpdateItemsInList() {
+ def "testUpdateItemsInList"() {
+ given:
+ def list = [1, "Apple", 80, "App"]
- def list =[1, "Apple", 80, "App"]
+ when:
list[1] = "Box"
- list.set(2,90)
- assertTrue(list == [1, "Box", 90, "App"])
+ list.set(2, 90)
+
+ then:
+ list == [1, "Box", 90, "App"]
}
- @Test
- void testRemoveItemsFromList(){
-
+ def "testRemoveItemsFromList"() {
+ given:
def list = [1, 2, 3, 4, 5, 5, 6, 6, 7]
- list.remove(3)
- assertTrue(list == [1, 2, 3, 5, 5, 6, 6, 7])
+ when:
+ list.remove(3) // [1, 2, 3, 5, 5, 6, 6, 7]
+ list.removeElement(5) // [1, 2, 3, 5, 6, 6, 7]
+ list = list - 6 // [1, 2, 3, 5, 7]
- list.removeElement(5)
- assertTrue(list == [1, 2, 3, 5, 6, 6, 7])
-
- assertTrue(list - 6 == [1, 2, 3, 5, 7])
+ then:
+ list == [1, 2, 3, 5, 7]
}
- @Test
- void testIteratingOnAList(){
-
+ def "testIteratingOnAList"() {
+ given:
def list = [1, "App", 3, 4]
- list.each{ println it * 2}
- list.eachWithIndex{ it, i -> println "$i : $it" }
+ expect:
+ list.each { println it * 2 }
+ list.eachWithIndex { it, i -> println "$i : $it" }
}
- @Test
- void testCollectingToAnotherList(){
-
+ def "testCollectingToAnotherList"() {
+ given:
def list = ["Kay", "Henry", "Justin", "Tom"]
- assertTrue(list.collect{"Hi " + it} == ["Hi Kay", "Hi Henry", "Hi Justin", "Hi Tom"])
+
+ when:
+ def collect = list.collect { "Hi " + it }
+
+ then:
+ collect == ["Hi Kay", "Hi Henry", "Hi Justin", "Hi Tom"]
}
- @Test
- void testJoinItemsInAList(){
- assertTrue(["One", "Two", "Three"].join(",") == "One,Two,Three")
+ def "testJoinItemsInAList"() {
+ expect:
+ ["One", "Two", "Three"].join(",") == "One,Two,Three"
}
- @Test
- void testFilteringOnLists(){
+ def "testFilteringOnLists"() {
+ given:
def filterList = [2, 1, 3, 4, 5, 6, 76]
-
- assertTrue(filterList.find{it > 3} == 4)
-
- assertTrue(filterList.findAll{it > 3} == [4, 5, 6, 76])
-
- assertTrue(filterList.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76])
-
- assertTrue(filterList.grep( Number )== [2, 1, 3, 4, 5, 6, 76])
-
- assertTrue(filterList.grep{ it> 6 }== [76])
-
def conditionList = [2, 1, 3, 4, 5, 6, 76]
- assertFalse(conditionList.every{ it < 6})
-
- assertTrue(conditionList.any{ it%2 == 0})
+ expect:
+ filterList.find { it > 3 } == 4
+ filterList.findAll { it > 3 } == [4, 5, 6, 76]
+ filterList.findAll { it instanceof Number } == [2, 1, 3, 4, 5, 6, 76]
+ filterList.grep(Number) == [2, 1, 3, 4, 5, 6, 76]
+ filterList.grep { it > 6 } == [76]
+ !(conditionList.every { it < 6 })
+ conditionList.any { it % 2 == 0 }
}
- @Test
- void testGetUniqueItemsInAList(){
- assertTrue([1, 3, 3, 4].toUnique() == [1, 3, 4])
-
+ def "testGetUniqueItemsInAList"() {
+ given:
def uniqueList = [1, 3, 3, 4]
- uniqueList.unique()
- assertTrue(uniqueList == [1, 3, 4])
- assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique{ it.size()} == ["A", "Ba", "Bat"])
+ when:
+ uniqueList.unique(true)
+
+ then:
+ [1, 3, 3, 4].toUnique() == [1, 3, 4]
+ uniqueList == [1, 3, 4]
+ ["A", "B", "Ba", "Bat", "Cat"].toUnique { it.size() } == ["A", "Ba", "Bat"]
}
- @Test
- void testSorting(){
-
- assertTrue([1, 2, 1, 0].sort() == [0, 1, 1, 2])
- Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1}
-
+ def "testSorting"() {
+ given:
+ Comparator naturalOrder = { a, b -> a == b ? 0 : a < b ? -1 : 1 }
def list = [1, 2, 1, 0]
- list.sort(mc)
- assertTrue(list == [2, 1, 1, 0])
-
def strList = ["na", "ppp", "as"]
- assertTrue(strList.max() == "ppp")
-
- Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1}
def numberList = [3, 2, 0, 7]
- assertTrue(numberList.min(minc) == 0)
+
+ when:
+ list.sort(naturalOrder.reversed())
+
+ then:
+ list == [2, 1, 1, 0]
+ strList.max() == "ppp"
+ [1, 2, 1, 0].sort() == [0, 1, 1, 2]
+ numberList.min(naturalOrder) == 0
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/maps/MapTest.groovy b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/maps/MapTest.groovy
index deb552c420..9529330089 100644
--- a/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/maps/MapTest.groovy
+++ b/core-groovy-modules/core-groovy-collections/src/test/groovy/com/baeldung/maps/MapTest.groovy
@@ -1,148 +1,160 @@
-package com.baeldung.maps;
+package com.baeldung.maps
-import static groovy.test.GroovyAssert.*
-import org.junit.Test
+import spock.lang.Specification
-class MapTest{
-
- @Test
- void createMap() {
+class MapTest extends Specification {
+ def "createMap"() {
+ when:
def emptyMap = [:]
- assertNotNull(emptyMap)
+ def map = [name: "Jerry", age: 42, city: "New York"]
- assertTrue(emptyMap instanceof java.util.LinkedHashMap)
-
- def map = [name:"Jerry", age: 42, city: "New York"]
- assertTrue(map.size() == 3)
+ then:
+ emptyMap != null
+ emptyMap instanceof java.util.LinkedHashMap
+ map.size() == 3
}
- @Test
- void addItemsToMap() {
-
- def map = [name:"Jerry"]
-
- map["age"] = 42
-
- map.city = "New York"
-
+ def "addItemsToMap"() {
+ given:
+ def map = [name: "Jerry"]
def hobbyLiteral = "hobby"
def hobbyMap = [(hobbyLiteral): "Singing"]
+ def appendToMap = [:]
+
+ when:
+ map["age"] = 42
+ map.city = "New York"
+
map.putAll(hobbyMap)
- assertTrue(map == [name:"Jerry", age: 42, city: "New York", hobby:"Singing"])
- assertTrue(hobbyMap.hobby == "Singing")
- assertTrue(hobbyMap[hobbyLiteral] == "Singing")
-
- map.plus([1:20]) // returns new map
+ appendToMap.plus([1: 20])
+ appendToMap << [2: 30]
- map << [2:30]
+ then:
+ map == [name: "Jerry", age: 42, city: "New York", hobby: "Singing"]
+ hobbyMap.hobby == "Singing"
+ hobbyMap[hobbyLiteral] == "Singing"
+
+ appendToMap == [2: 30] // plus(Map) returns new instance of Map
}
- @Test
- void getItemsFromMap() {
-
- def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]
-
- assertTrue(map["name"] == "Jerry")
-
- assertTrue(map.name == "Jerry")
-
+ def "getItemsFromMap"() {
+ when:
+ def map = [name: "Jerry", age: 42, city: "New York", hobby: "Singing"]
def propertyAge = "age"
- assertTrue(map[propertyAge] == 42)
+
+ then:
+ map["name"] == "Jerry"
+ map.name == "Jerry"
+ map[propertyAge] == 42
+ map."$propertyAge" == 42
}
- @Test
- void removeItemsFromMap() {
+ def "removeItemsFromMap"() {
+ given:
+ def map = [1: 20, a: 30, 2: 42, 4: 34, ba: 67, 6: 39, 7: 49]
+ def removeAllKeysOfTypeString = [1: 20, a: 30, ba: 67, 6: 39, 7: 49]
+ def retainAllEntriesWhereValueIsEven = [1: 20, a: 30, ba: 67, 6: 39, 7: 49]
- def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
+ when:
+ def minusMap = map - [2: 42, 4: 34]
+ removeAllKeysOfTypeString.removeAll { it.key instanceof String }
+ retainAllEntriesWhereValueIsEven.retainAll { it.value % 2 == 0 }
- def minusMap = map.minus([2:42, 4:34]);
- assertTrue(minusMap == [1:20, a:30, ba:67, 6:39, 7:49])
-
- minusMap.removeAll{it -> it.key instanceof String}
- assertTrue( minusMap == [ 1:20, 6:39, 7:49])
-
- minusMap.retainAll{it -> it.value %2 == 0}
- assertTrue( minusMap == [1:20])
+ then:
+ minusMap == [1: 20, a: 30, ba: 67, 6: 39, 7: 49]
+ removeAllKeysOfTypeString == [1: 20, 6: 39, 7: 49]
+ retainAllEntriesWhereValueIsEven == [1: 20, a: 30]
}
- @Test
- void iteratingOnMaps(){
- def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]
+ def "iteratingOnMaps"() {
+ when:
+ def map = [name: "Jerry", age: 42, city: "New York", hobby: "Singing"]
- map.each{ entry -> println "$entry.key: $entry.value" }
-
- map.eachWithIndex{ entry, i -> println "$i $entry.key: $entry.value" }
-
- map.eachWithIndex{ key, value, i -> println "$i $key: $value" }
+ then:
+ map.each { entry -> println "$entry.key: $entry.value" }
+ map.eachWithIndex { entry, i -> println "$i $entry.key: $entry.value" }
+ map.eachWithIndex { key, value, i -> println "$i $key: $value" }
}
- @Test
- void filteringAndSearchingMaps(){
- def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]
+ def "filteringAndSearchingMaps"() {
+ given:
+ def map = [name: "Jerry", age: 42, city: "New York", hobby: "Singing"]
- assertTrue(map.find{ it.value == "New York"}.key == "city")
+ when:
+ def find = map.find { it.value == "New York" }
+ def finaAll = map.findAll { it.value == "New York" }
+ def grep = map.grep { it.value == "New York" }
+ def every = map.every { it -> it.value instanceof String }
+ def any = map.any { it -> it.value instanceof String }
- assertTrue(map.findAll{ it.value == "New York"} == [city : "New York"])
+ then:
+ find.key == "city"
- map.grep{it.value == "New York"}.each{ it -> assertTrue(it.key == "city" && it.value == "New York")}
+ finaAll instanceof Map
+ finaAll == [city: "New York"]
- assertTrue(map.every{it -> it.value instanceof String} == false)
+ grep instanceof Collection
+ grep.each { it -> assert it.key == "city" && it.value == "New York" }
- assertTrue(map.any{it -> it.value instanceof String} == true)
+ every instanceof Boolean
+ !every
+
+ any instanceof Boolean
+ any
}
- @Test
- void collect(){
-
- def map = [1: [name:"Jerry", age: 42, city: "New York"],
- 2: [name:"Long", age: 25, city: "New York"],
- 3: [name:"Dustin", age: 29, city: "New York"],
- 4: [name:"Dustin", age: 34, city: "New York"]]
-
- def names = map.collect{entry -> entry.value.name} // returns only list
- assertTrue(names == ["Jerry", "Long", "Dustin", "Dustin"])
-
- def uniqueNames = map.collect([] as HashSet){entry -> entry.value.name}
- assertTrue(uniqueNames == ["Jerry", "Long", "Dustin"] as Set)
-
- def idNames = map.collectEntries{key, value -> [key, value.name]}
- assertTrue(idNames == [1:"Jerry", 2: "Long", 3:"Dustin", 4: "Dustin"])
-
- def below30Names = map.findAll{it.value.age < 30}.collect{key, value -> value.name}
- assertTrue(below30Names == ["Long", "Dustin"])
+ def "collect"() {
+ given:
+ def map = [
+ 1: [name: "Jerry", age: 42, city: "New York"],
+ 2: [name: "Long", age: 25, city: "New York"],
+ 3: [name: "Dustin", age: 29, city: "New York"],
+ 4: [name: "Dustin", age: 34, city: "New York"]
+ ]
+ when:
+ def names = map.collect { entry -> entry.value.name } // returns only list
+ def uniqueNames = map.collect { entry -> entry.value.name }
+ .unique()
+ def idNames = map.collectEntries { key, value -> [key, value.name] }
+ def below30Names = map.findAll { it.value.age < 30 }
+ .collect { key, value -> value.name }
+ then:
+ names == ["Jerry", "Long", "Dustin", "Dustin"]
+ uniqueNames == ["Jerry", "Long", "Dustin"]
+ idNames == [1: "Jerry", 2: "Long", 3: "Dustin", 4: "Dustin"]
+ below30Names == ["Long", "Dustin"]
}
- @Test
- void group(){
- def map = [1:20, 2: 40, 3: 11, 4: 93]
-
- def subMap = map.groupBy{it.value % 2}
- println subMap
- assertTrue(subMap == [0:[1:20, 2:40 ], 1:[3:11, 4:93]])
+ def "group"() {
+ given:
+ def map = [1: 20, 2: 40, 3: 11, 4: 93]
+ when:
+ def subMap = map.groupBy { it.value % 2 }
def keySubMap = map.subMap([1, 2])
- assertTrue(keySubMap == [1:20, 2:40])
+ then:
+ subMap == [0: [1: 20, 2: 40], 1: [3: 11, 4: 93]]
+ keySubMap == [1: 20, 2: 40]
}
- @Test
- void sorting(){
- def map = [ab:20, a: 40, cb: 11, ba: 93]
+ def "sorting"() {
+ given:
+ def map = [ab: 20, a: 40, cb: 11, ba: 93]
+ when:
def naturallyOrderedMap = map.sort()
- assertTrue([a:40, ab:20, ba:93, cb:11] == naturallyOrderedMap)
-
def compSortedMap = map.sort({ k1, k2 -> k1 <=> k2 } as Comparator)
- assertTrue([a:40, ab:20, ba:93, cb:11] == compSortedMap)
-
def cloSortedMap = map.sort({ it1, it2 -> it1.value <=> it1.value })
- assertTrue([cb:11, ab:20, a:40, ba:93] == cloSortedMap)
+ then:
+ naturallyOrderedMap == [a: 40, ab: 20, ba: 93, cb: 11]
+ compSortedMap == [a: 40, ab: 20, ba: 93, cb: 11]
+ cloSortedMap == [cb: 11, ab: 20, a: 40, ba: 93]
}
-
}
diff --git a/core-groovy-modules/core-groovy-strings/pom.xml b/core-groovy-modules/core-groovy-strings/pom.xml
index e51ebfbd4b..fac0f25219 100644
--- a/core-groovy-modules/core-groovy-strings/pom.xml
+++ b/core-groovy-modules/core-groovy-strings/pom.xml
@@ -103,9 +103,10 @@
- central
- https://jcenter.bintray.com
+ maven_central
+ Maven Central
+ https://repo.maven.apache.org/maven2/
-
\ No newline at end of file
+
diff --git a/core-groovy-modules/core-groovy-strings/src/test/groovy/com/baeldung/removeprefix/RemovePrefixTest.groovy b/core-groovy-modules/core-groovy-strings/src/test/groovy/com/baeldung/removeprefix/RemovePrefixTest.groovy
index 61b81fe1b2..8b7ce9c355 100644
--- a/core-groovy-modules/core-groovy-strings/src/test/groovy/com/baeldung/removeprefix/RemovePrefixTest.groovy
+++ b/core-groovy-modules/core-groovy-strings/src/test/groovy/com/baeldung/removeprefix/RemovePrefixTest.groovy
@@ -1,70 +1,74 @@
package com.baeldung.removeprefix
-import org.junit.Assert
-import org.junit.Test
+import spock.lang.Specification
-class RemovePrefixTest {
+class RemovePrefixTest extends Specification {
-
- @Test
- public void whenCasePrefixIsRemoved_thenReturnTrue() {
+ def "whenCasePrefixIsRemoved_thenReturnTrue"() {
+ given:
def trimPrefix = {
it.startsWith('Groovy-') ? it.minus('Groovy-') : it
}
-
+
+ when:
def actual = trimPrefix("Groovy-Tutorials at Baeldung")
def expected = "Tutorials at Baeldung"
- Assert.assertEquals(expected, actual)
+ then:
+ expected == actual
}
- @Test
- public void whenPrefixIsRemoved_thenReturnTrue() {
-
+ def "whenPrefixIsRemoved_thenReturnTrue"() {
+ given:
String prefix = "groovy-"
String trimPrefix = "Groovy-Tutorials at Baeldung"
- def actual;
- if(trimPrefix.startsWithIgnoreCase(prefix)) {
+
+ when:
+ def actual
+ if (trimPrefix.startsWithIgnoreCase(prefix)) {
actual = trimPrefix.substring(prefix.length())
}
-
def expected = "Tutorials at Baeldung"
- Assert.assertEquals(expected, actual)
+ then:
+ expected == actual
}
- @Test
- public void whenPrefixIsRemovedUsingRegex_thenReturnTrue() {
-
+ def "whenPrefixIsRemovedUsingRegex_thenReturnTrue"() {
+ given:
def regex = ~"^([Gg])roovy-"
String trimPrefix = "Groovy-Tutorials at Baeldung"
+
+ when:
String actual = trimPrefix - regex
-
def expected = "Tutorials at Baeldung"
- Assert.assertEquals(expected, actual)
+ then:
+ expected == actual
}
- @Test
- public void whenPrefixIsRemovedUsingReplaceFirst_thenReturnTrue() {
- def regex = ~"^groovy"
- String trimPrefix = "groovyTutorials at Baeldung's groovy page"
+ def "whenPrefixIsRemovedUsingReplaceFirst_thenReturnTrue"() {
+ given:
+ def regex = ~"^groovy"
+ String trimPrefix = "groovyTutorials at Baeldung's groovy page"
+
+ when:
String actual = trimPrefix.replaceFirst(regex, "")
-
def expected = "Tutorials at Baeldung's groovy page"
-
- Assert.assertEquals(expected, actual)
+
+ then:
+ expected == actual
}
- @Test
- public void whenPrefixIsRemovedUsingReplaceAll_thenReturnTrue() {
-
+ def "whenPrefixIsRemovedUsingReplaceAll_thenReturnTrue"() {
+ given:
String trimPrefix = "groovyTutorials at Baeldung groovy"
+
+ when:
String actual = trimPrefix.replaceAll(/^groovy/, "")
-
def expected = "Tutorials at Baeldung groovy"
- Assert.assertEquals(expected, actual)
+ then:
+ expected == actual
}
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/pom.xml b/core-groovy-modules/core-groovy/pom.xml
index 413fbde106..cf6cca9e18 100644
--- a/core-groovy-modules/core-groovy/pom.xml
+++ b/core-groovy-modules/core-groovy/pom.xml
@@ -3,6 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
+
core-groovy
1.0-SNAPSHOT
core-groovy
@@ -103,9 +104,10 @@
- central
- https://jcenter.bintray.com
+ maven_central
+ Maven Central
+ https://repo.maven.apache.org/maven2/
-
\ No newline at end of file
+
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/file/ReadFile.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/file/ReadFile.groovy
index 4239fa534c..1418947cc7 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/file/ReadFile.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/file/ReadFile.groovy
@@ -10,13 +10,14 @@ class ReadFile {
int readFileLineByLine(String filePath) {
File file = new File(filePath)
def line, noOfLines = 0;
+
file.withReader { reader ->
- while ((line = reader.readLine())!=null)
- {
+ while ((line = reader.readLine()) != null) {
println "${line}"
noOfLines++
}
}
+
return noOfLines
}
@@ -26,9 +27,7 @@ class ReadFile {
* @return
*/
List readFileInList(String filePath) {
- File file = new File(filePath)
- def lines = file.readLines()
- return lines
+ return new File(filePath).readLines()
}
/**
@@ -37,9 +36,7 @@ class ReadFile {
* @return
*/
String readFileString(String filePath) {
- File file = new File(filePath)
- String fileContent = file.text
- return fileContent
+ return new File(filePath).text
}
/**
@@ -48,9 +45,7 @@ class ReadFile {
* @return
*/
String readFileStringWithCharset(String filePath) {
- File file = new File(filePath)
- String utf8Content = file.getText("UTF-8")
- return utf8Content
+ return new File(filePath).getText("UTF-8")
}
/**
@@ -59,49 +54,44 @@ class ReadFile {
* @return
*/
byte[] readBinaryFile(String filePath) {
- File file = new File(filePath)
- byte[] binaryContent = file.bytes
- return binaryContent
+ return new File(filePath).bytes
}
-
+
/**
* More Examples of reading a file
* @return
*/
def moreExamples() {
-
+
//with reader with utf-8
new File("src/main/resources/utf8Content.html").withReader('UTF-8') { reader ->
def line
- while ((line = reader.readLine())!=null) {
+ while ((line = reader.readLine()) != null) {
println "${line}"
}
}
-
- //collect api
- def list = new File("src/main/resources/fileContent.txt").collect {it}
-
- //as operator
+
+ // collect api
+ def list = new File("src/main/resources/fileContent.txt").collect { it }
+
+ // as operator
def array = new File("src/main/resources/fileContent.txt") as String[]
-
- //eachline
- new File("src/main/resources/fileContent.txt").eachLine { line ->
- println line
- }
-
+
+ // eachline
+ new File("src/main/resources/fileContent.txt").eachLine { println it }
+
//newInputStream with eachLine
- def is = new File("src/main/resources/fileContent.txt").newInputStream()
- is.eachLine {
- println it
+
+ // try-with-resources automatically closes BufferedInputStream resource
+ try (def inputStream = new File("src/main/resources/fileContent.txt").newInputStream()) {
+ inputStream.eachLine { println it }
}
- is.close()
-
- //withInputStream
+
+ // withInputStream
new File("src/main/resources/fileContent.txt").withInputStream { stream ->
stream.eachLine { line ->
println line
}
}
}
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
index b3a0852a0b..4a7c3f8529 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
@@ -1,9 +1,10 @@
package com.baeldung.strings;
class Concatenate {
+
String first = 'Hello'
String last = 'Groovy'
-
+
String doSimpleConcat() {
return 'My name is ' + first + ' ' + last
}
@@ -23,21 +24,28 @@ class Concatenate {
String doConcatUsingLeftShiftOperator() {
return 'My name is ' << first << ' ' << last
}
-
+
String doConcatUsingArrayJoinMethod() {
return ['My name is', first, last].join(' ')
}
String doConcatUsingArrayInjectMethod() {
- return [first,' ', last]
- .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name); return initial }).toString()
+ return [first, ' ', last]
+ .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name) })
+ .toString()
}
-
+
String doConcatUsingStringBuilder() {
- return new StringBuilder().append('My name is ').append(first).append(' ').append(last)
+ return new StringBuilder().append('My name is ')
+ .append(first)
+ .append(' ')
+ .append(last)
}
String doConcatUsingStringBuffer() {
- return new StringBuffer().append('My name is ').append(first).append(' ').append(last)
+ return new StringBuffer().append('My name is ')
+ .append(first)
+ .append(' ')
+ .append(last)
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
index 6ec5cda571..a3fed81c8b 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
@@ -1,8 +1,8 @@
package com.baeldung.traits
trait AnimalTrait {
-
+
String basicBehavior() {
return "Animalistic!!"
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
index 3e0677ba18..fc53b1bef9 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
@@ -1,9 +1,8 @@
package com.baeldung.traits
class Dog implements WalkingTrait, SpeakingTrait {
-
+
String speakAndWalk() {
WalkingTrait.super.speakAndWalk()
}
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
index b3e4285476..16f1fab984 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
@@ -1,12 +1,14 @@
package com.baeldung.traits
class Employee implements UserTrait {
-
+
+ @Override
String name() {
return 'Bob'
}
+ @Override
String lastName() {
return "Marley"
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
index e78d59bbfd..5417334269 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
@@ -1,6 +1,6 @@
package com.baeldung.traits
interface Human {
-
+
String lastName()
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
index f437a94bd9..969982e8e0 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
@@ -1,13 +1,12 @@
package com.baeldung.traits
trait SpeakingTrait {
-
+
String basicAbility() {
return "Speaking!!"
}
-
+
String speakAndWalk() {
return "Speak and walk!!"
}
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
index 0d395bffcd..1d1d188460 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
@@ -1,36 +1,35 @@
package com.baeldung.traits
trait UserTrait implements Human {
-
+
+ String email
+ String address
+
+ abstract String name()
+
String sayHello() {
return "Hello!"
}
-
- abstract String name()
-
+
String showName() {
- return "Hello, ${name()}!"
+ return "Hello, ${name()}!"
}
private String greetingMessage() {
return 'Hello, from a private method!'
}
-
+
String greet() {
def msg = greetingMessage()
println msg
msg
}
-
+
def self() {
- return this
+ return this
}
-
+
String showLastName() {
return "Hello, ${lastName()}!"
}
-
- String email
- String address
}
-
\ No newline at end of file
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy
index f5ae8fab30..e29561157c 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy
@@ -1,9 +1,9 @@
package com.baeldung
trait VehicleTrait extends WheelTrait {
-
+
String showWheels() {
- return "Num of Wheels $noOfWheels"
+ return "Num of Wheels $noOfWheels"
}
-
-}
\ No newline at end of file
+
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
index 66cff8809f..84be49ec25 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
@@ -1,13 +1,13 @@
package com.baeldung.traits
trait WalkingTrait {
-
+
String basicAbility() {
return "Walking!!"
}
-
+
String speakAndWalk() {
return "Walk and speak!!"
}
-
-}
\ No newline at end of file
+
+}
diff --git a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy
index 364d5b883e..7f2448e185 100644
--- a/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy
+++ b/core-groovy-modules/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy
@@ -1,7 +1,6 @@
package com.baeldung
trait WheelTrait {
-
+
int noOfWheels
-
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
index da1dfc10ba..87cfc79761 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
@@ -1,71 +1,76 @@
package com.baeldung.file
import spock.lang.Specification
-import spock.lang.Ignore
class ReadFileUnitTest extends Specification {
ReadFile readFile
- void setup () {
+ void setup() {
readFile = new ReadFile()
}
- def 'Should return number of lines in File using ReadFile.readFileLineByLine given filePath' () {
+ def 'Should return number of lines in File using ReadFile.readFileLineByLine given filePath'() {
given:
- def filePath = "src/main/resources/fileContent.txt"
+ def filePath = "src/main/resources/fileContent.txt"
+
when:
- def noOfLines = readFile.readFileLineByLine(filePath)
+ def noOfLines = readFile.readFileLineByLine(filePath)
+
then:
- noOfLines
- noOfLines instanceof Integer
- assert noOfLines, 3
- }
-
- def 'Should return File Content in list of lines using ReadFile.readFileInList given filePath' () {
- given:
- def filePath = "src/main/resources/fileContent.txt"
- when:
- def lines = readFile.readFileInList(filePath)
- then:
- lines
- lines instanceof List
- assert lines.size(), 3
- }
-
- def 'Should return file content in string using ReadFile.readFileString given filePath' () {
- given:
- def filePath = "src/main/resources/fileContent.txt"
- when:
- def fileContent = readFile.readFileString(filePath)
- then:
- fileContent
- fileContent instanceof String
- fileContent.contains("""Line 1 : Hello World!!!
-Line 2 : This is a file content.
-Line 3 : String content""")
-
+ noOfLines
+ noOfLines instanceof Integer
+ noOfLines == 3
}
- def 'Should return UTF-8 encoded file content in string using ReadFile.readFileStringWithCharset given filePath' () {
+ def 'Should return File Content in list of lines using ReadFile.readFileInList given filePath'() {
given:
- def filePath = "src/main/resources/utf8Content.html"
+ def filePath = "src/main/resources/fileContent.txt"
+
when:
- def encodedContent = readFile.readFileStringWithCharset(filePath)
+ def lines = readFile.readFileInList(filePath)
+
then:
- encodedContent
- encodedContent instanceof String
+ lines
+ lines instanceof List
+ lines.size() == 3
}
-
- def 'Should return binary file content in byte array using ReadFile.readBinaryFile given filePath' () {
+
+ def 'Should return file content in string using ReadFile.readFileString given filePath'() {
given:
- def filePath = "src/main/resources/sample.png"
+ def filePath = "src/main/resources/fileContent.txt"
+
when:
- def binaryContent = readFile.readBinaryFile(filePath)
+ def fileContent = readFile.readFileString(filePath)
+
then:
- binaryContent
- binaryContent instanceof byte[]
- binaryContent.length == 329
+ fileContent
+ fileContent instanceof String
+ fileContent.contains(["Line 1 : Hello World!!!", "Line 2 : This is a file content.", "Line 3 : String content"].join("\r\n"))
}
-
-}
\ No newline at end of file
+
+ def 'Should return UTF-8 encoded file content in string using ReadFile.readFileStringWithCharset given filePath'() {
+ given:
+ def filePath = "src/main/resources/utf8Content.html"
+
+ when:
+ def encodedContent = readFile.readFileStringWithCharset(filePath)
+
+ then:
+ encodedContent
+ encodedContent instanceof String
+ }
+
+ def 'Should return binary file content in byte array using ReadFile.readBinaryFile given filePath'() {
+ given:
+ def filePath = "src/main/resources/sample.png"
+
+ when:
+ def binaryContent = readFile.readBinaryFile(filePath)
+
+ then:
+ binaryContent
+ binaryContent instanceof byte[]
+ binaryContent.length == 329
+ }
+}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy
index ac96a55773..da982744e9 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy
@@ -1,28 +1,29 @@
package com.baeldung.groovy.sql
import groovy.sql.GroovyResultSet
-import groovy.sql.GroovyRowResult
import groovy.sql.Sql
-import groovy.transform.CompileStatic
-import static org.junit.Assert.*
import org.junit.Test
+import static org.junit.Assert.*
+
class SqlTest {
- final Map dbConnParams = [url: 'jdbc:hsqldb:mem:testDB', user: 'sa', password: '', driver: 'org.hsqldb.jdbc.JDBCDriver']
+ final Map dbConnParams = [url: 'jdbc:hsqldb:mem:testDB',
+ user: 'sa',
+ password: '',
+ driver: 'org.hsqldb.jdbc.JDBCDriver']
@Test
void whenNewSqlInstance_thenDbIsAccessed() {
def sql = Sql.newInstance(dbConnParams)
sql.close()
- sql.close()
}
@Test
void whenTableDoesNotExist_thenSelectFails() {
try {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.eachRow('select * from PROJECT') {}
+ sql.eachRow('SELECT * FROM PROJECT') {}
}
fail("An exception should have been thrown")
@@ -34,12 +35,12 @@ class SqlTest {
@Test
void whenTableCreated_thenSelectIsPossible() {
Sql.withInstance(dbConnParams) { Sql sql ->
- def result = sql.execute 'create table PROJECT_1 (id integer not null, name varchar(50), url varchar(100))'
+ def result = sql.execute 'CREATE TABLE PROJECT_1 (ID INTEGER NOT NULL, NAME VARCHAR(50), URL VARCHAR(100))'
assertEquals(0, sql.updateCount)
assertFalse(result)
- result = sql.execute('select * from PROJECT_1')
+ result = sql.execute('SELECT * FROM PROJECT_1')
assertTrue(result)
}
@@ -48,7 +49,7 @@ class SqlTest {
@Test
void whenIdentityColumn_thenInsertReturnsNewId() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
def ids = sql.executeInsert("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
assertEquals(0, ids[0][0])
@@ -62,9 +63,10 @@ class SqlTest {
@Test
void whenUpdate_thenNumberOfAffectedRows() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
sql.executeInsert("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
+
def count = sql.executeUpdate("UPDATE PROJECT_3 SET URL = 'https://' + URL")
assertEquals(2, count)
@@ -74,7 +76,7 @@ class SqlTest {
@Test
void whenEachRow_thenResultSetHasProperties() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
sql.executeInsert("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
@@ -93,7 +95,7 @@ class SqlTest {
@Test
void whenPagination_thenSubsetIsReturned() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
def rows = sql.rows('SELECT * FROM PROJECT_5 ORDER BY NAME', 1, 1)
@@ -106,9 +108,11 @@ class SqlTest {
@Test
void whenParameters_thenReplacement() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
- sql.execute('INSERT INTO PROJECT_6 (NAME, URL) VALUES (?, ?)', 'tutorials', 'github.com/eugenp/tutorials')
- sql.execute("INSERT INTO PROJECT_6 (NAME, URL) VALUES (:name, :url)", [name: 'REST with Spring', url: 'github.com/eugenp/REST-With-Spring'])
+ sql.execute 'CREATE TABLE PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute('INSERT INTO PROJECT_6 (NAME, URL) VALUES (?, ?)',
+ 'tutorials', 'github.com/eugenp/tutorials')
+ sql.execute("INSERT INTO PROJECT_6 (NAME, URL) VALUES (:name, :url)",
+ [name: 'REST with Spring', url: 'github.com/eugenp/REST-With-Spring'])
def rows = sql.rows("SELECT * FROM PROJECT_6 WHERE NAME = 'tutorials'")
@@ -123,7 +127,7 @@ class SqlTest {
@Test
void whenParametersInGString_thenReplacement() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_7 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_7 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.execute "INSERT INTO PROJECT_7 (NAME, URL) VALUES (${'tutorials'}, ${'github.com/eugenp/tutorials'})"
def name = 'REST with Spring'
def url = 'github.com/eugenp/REST-With-Spring'
@@ -143,7 +147,7 @@ class SqlTest {
void whenTransactionRollback_thenNoDataInserted() {
Sql.withInstance(dbConnParams) { Sql sql ->
sql.withTransaction {
- sql.execute 'create table PROJECT_8 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_8 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_8 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
sql.executeInsert("INSERT INTO PROJECT_8 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
sql.rollback()
@@ -159,7 +163,7 @@ class SqlTest {
void whenTransactionRollbackThenCommit_thenOnlyLastInserted() {
Sql.withInstance(dbConnParams) { Sql sql ->
sql.withTransaction {
- sql.execute 'create table PROJECT_9 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_9 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
sql.rollback()
sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
@@ -179,11 +183,12 @@ class SqlTest {
Sql.withInstance(dbConnParams) { Sql sql ->
try {
sql.withTransaction {
- sql.execute 'create table PROJECT_10 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_10 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_10 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
throw new Exception('rollback')
}
- } catch (ignored) {}
+ } catch (ignored) {
+ }
def rows = sql.rows("SELECT * FROM PROJECT_10")
@@ -196,11 +201,12 @@ class SqlTest {
Sql.withInstance(dbConnParams) { Sql sql ->
try {
sql.cacheConnection {
- sql.execute 'create table PROJECT_11 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_11 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_11 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
throw new Exception('This does not rollback')
}
- } catch (ignored) {}
+ } catch (ignored) {
+ }
def rows = sql.rows("SELECT * FROM PROJECT_11")
@@ -211,7 +217,7 @@ class SqlTest {
/*@Test
void whenModifyResultSet_thenDataIsChanged() {
Sql.withInstance(dbConnParams) { Sql sql ->
- sql.execute 'create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute 'CREATE TABLE PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/json/JsonParserTest.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/json/JsonParserTest.groovy
index e65550a3be..fa7b2fd3c8 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/json/JsonParserTest.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/json/JsonParserTest.groovy
@@ -1,5 +1,6 @@
package com.baeldung.json
+import groovy.json.JsonGenerator
import spock.lang.Specification
import java.text.SimpleDateFormat
@@ -8,20 +9,42 @@ class JsonParserTest extends Specification {
JsonParser jsonParser
- void setup () {
+ void setup() {
jsonParser = new JsonParser()
}
- def 'Should parse to Account given Json String' () {
+ def 'Should parse to Account given Json String'() {
given:
- def json = '{"id":"1234","value":15.6}'
+ def json = '{"id":"1234","value":15.6}'
+
when:
- def account = jsonParser.toObject(json)
+ def account = jsonParser.toObject(json)
+
then:
- account
- account instanceof Account
- account.id == '1234'
- account.value == 15.6
+ account
+ account instanceof Account
+ account.id == '1234'
+ account.value == 15.6
+ }
+
+ def 'Should format date and exclude value field'() {
+ given:
+ def account = new Account(
+ id: '123',
+ value: 15.6,
+ createdAt: new SimpleDateFormat('MM/dd/yyyy').parse('14/01/2023')
+ )
+
+ def jsonGenerator = new JsonGenerator.Options()
+ .dateFormat('MM/dd/yyyy')
+ .excludeFieldsByName('value')
+ .build()
+
+ when:
+ def accountToJson = jsonGenerator.toJson(account)
+
+ then:
+ accountToJson == '{"createdAt":"01/31/2024","id":"123"}'
}
/*def 'Should parse to Account given Json String with date property' () {
@@ -52,15 +75,20 @@ class JsonParserTest extends Specification {
json == '{"value":15.6,"createdAt":"2018-01-01T00:00:00+0000","id":"123"}'
}*/
- def 'Should prettify given a json string' () {
+ def 'Should prettify given a json string'() {
given:
- String json = '{"value":15.6,"createdAt":"01/01/2018","id":"123456"}'
+ String json = '{"value":15.6,"createdAt":"01/01/2018","id":"123456"}'
+
when:
- def jsonPretty = jsonParser.prettyfy(json)
+ def jsonPretty = jsonParser.prettyfy(json)
+
then:
- jsonPretty
- jsonPretty == '{\n "value": 15.6,\n "createdAt": "01/01/2018",\n "id": "123456"\n}'
+ jsonPretty
+ jsonPretty == '''\
+{
+ "value": 15.6,
+ "createdAt": "01/01/2018",
+ "id": "123456"
+}'''
}
-
-
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
index 3ef4a5d460..e4a178a14b 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
@@ -1,101 +1,88 @@
-import com.baeldung.strings.Concatenate;
+import com.baeldung.strings.Concatenate
+import spock.lang.Specification
-class ConcatenateTest extends GroovyTestCase {
-
- void testSimpleConcat() {
- def name = new Concatenate()
- name.first = 'Joe';
- name.last = 'Smith';
- def expected = 'My name is Joe Smith'
- assertToString(name.doSimpleConcat(), expected)
- }
-
- void testConcatUsingGString() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingGString(), expected)
- }
-
- void testConcatUsingGStringClosures() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingGStringClosures(), expected)
- }
-
- void testConcatUsingStringConcatMethod() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingStringConcatMethod(), expected)
+class ConcatenateTest extends Specification {
+
+ final Concatenate NAME = new Concatenate(first: 'Joe', last: 'Smith')
+ final String EXPECTED = "My name is Joe Smith";
+
+ def "SimpleConcat"() {
+ expect:
+ NAME.doSimpleConcat() == EXPECTED
}
- void testConcatUsingLeftShiftOperator() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingLeftShiftOperator(), expected)
+ def "ConcatUsingGString"() {
+ expect:
+ NAME.doConcatUsingGString() == EXPECTED
}
- void testConcatUsingArrayJoinMethod() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingArrayJoinMethod(), expected)
+ def "ConcatUsingGStringClosures"() {
+ expect:
+ NAME.doConcatUsingGStringClosures() == EXPECTED
}
- void testConcatUsingArrayInjectMethod() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingArrayInjectMethod(), expected)
+ def "ConcatUsingStringConcatMethod"() {
+ expect:
+ NAME.doConcatUsingStringConcatMethod() == EXPECTED
}
- void testConcatUsingStringBuilder() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingStringBuilder(), expected)
+ def "ConcatUsingLeftShiftOperator"() {
+ expect:
+ NAME.doConcatUsingLeftShiftOperator() == EXPECTED
}
- void testConcatUsingStringBuffer() {
- def name = new Concatenate()
- name.first = "Joe";
- name.last = "Smith";
- def expected = "My name is Joe Smith"
- assertToString(name.doConcatUsingStringBuffer(), expected)
+ def "ConcatUsingArrayJoinMethod"() {
+ expect:
+ NAME.doConcatUsingArrayJoinMethod() == EXPECTED
}
- void testConcatMultilineUsingStringConcatMethod() {
- def name = new Concatenate()
- name.first = '''Joe
+ def "ConcatUsingArrayInjectMethod"() {
+ expect:
+ NAME.doConcatUsingArrayInjectMethod() == EXPECTED
+ }
+
+ def "ConcatUsingStringBuilder"() {
+ expect:
+ NAME.doConcatUsingStringBuilder() == EXPECTED
+ }
+
+ def "ConcatUsingStringBuffer"() {
+ expect:
+ NAME.doConcatUsingStringBuffer() == EXPECTED
+ }
+
+ def "ConcatMultilineUsingStringConcatMethod"() {
+ when:
+ NAME.first = '''Joe
Smith
- ''';
- name.last = 'Junior';
+ '''
+ NAME.last = 'Junior'
+
+ then:
def expected = '''My name is Joe
Smith
- Junior''';
- assertToString(name.doConcatUsingStringConcatMethod(), expected)
+ Junior'''
+ NAME.doConcatUsingStringConcatMethod() == expected
}
- void testGStringvsClosure(){
- def first = "Joe";
- def last = "Smith";
- def eagerGString = "My name is $first $last"
- def lazyGString = "My name is ${-> first} ${-> last}"
+ def "GStringvsClosure"() {
+ given:
+ def eagerGString = "My name is $NAME.first $NAME.last"
+ def lazyGString = "My name is ${-> NAME.first} ${-> NAME.last}"
- assert eagerGString == "My name is Joe Smith"
- assert lazyGString == "My name is Joe Smith"
- first = "David";
- assert eagerGString == "My name is Joe Smith"
- assert lazyGString == "My name is David Smith"
- }
+ expect:
+ eagerGString == "My name is Joe Smith"
+ lazyGString == "My name is Joe Smith"
+ }
+
+ def "LazyVsEager"() {
+ given:
+ def eagerGString = "My name is $NAME.first $NAME.last"
+ def lazyGString = "My name is ${-> NAME.first} ${-> NAME.last}"
+ NAME.first = "David"
+
+ expect:
+ eagerGString == "My name is Joe Smith"
+ lazyGString == "My name is David Smith"
+ }
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
index 3865bc73fa..89202d9500 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
@@ -13,7 +13,7 @@ class StringMatchingSpec extends Specification {
expect:
p instanceof Pattern
- and: "you can use slash strings to avoid escaping of blackslash"
+ and: "you can use slash strings to avoid escaping of backslash"
def digitPattern = ~/\d*/
digitPattern.matcher('4711').matches()
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy
index 48cf48fa8a..cce6ede989 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy
@@ -1,110 +1,119 @@
package com.baeldung.stringtoint
-import org.junit.Test
+import spock.lang.Specification
import java.text.DecimalFormat
-import static org.junit.Assert.assertEquals
-import static org.junit.Assert.assertNull
+class ConvertStringToInt extends Specification {
-class ConvertStringToInt {
+ final String STRING_NUM = "123"
+ final int EXPECTED_INT = 123
- @Test
- void givenString_whenUsingAsInteger_thenConvertToInteger() {
- def stringNum = "123"
+ def "givenString_whenUsingAsInteger_thenConvertToInteger"() {
+ given:
def invalidString = "123a"
- Integer expectedInteger = 123
- Integer integerNum = stringNum as Integer
+ Integer integerNum = STRING_NUM as Integer
+
+ when:
def intNum = invalidString?.isInteger() ? invalidString as Integer : null
- assertNull(null, intNum)
- assertEquals(integerNum, expectedInteger)
+ then:
+ intNum == null
+ integerNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingAsInt_thenConvertToInt() {
- def stringNum = "123"
- int expectedInt = 123
- int intNum = stringNum as int
+ def "givenString_whenUsingAsInt_thenConvertToInt"() {
+ given:
+ int intNum = STRING_NUM as int
- assertEquals(intNum, expectedInt)
+ expect:
+ intNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingToInteger_thenConvertToInteger() {
- def stringNum = "123"
- int expectedInt = 123
- int intNum = stringNum.toInteger()
+ def "givenString_whenUsingToInteger_thenConvertToInteger"() {
+ given:
+ int intNum = STRING_NUM.toInteger()
- assertEquals(intNum, expectedInt)
+ expect:
+ intNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingParseInt_thenConvertToInteger() {
- def stringNum = "123"
- int expectedInt = 123
- int intNum = Integer.parseInt(stringNum)
+ def "givenString_whenUsingParseInt_thenConvertToInteger"() {
+ given:
+ int intNum = Integer.parseInt(STRING_NUM)
- assertEquals(intNum, expectedInt)
+ expect:
+ intNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingValueOf_thenConvertToInteger() {
- def stringNum = "123"
- int expectedInt = 123
- int intNum = Integer.valueOf(stringNum)
+ def "givenString_whenUsingValueOf_thenConvertToInteger"() {
+ given:
+ int intNum = Integer.valueOf(STRING_NUM)
- assertEquals(intNum, expectedInt)
+ expect:
+ intNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingIntValue_thenConvertToInteger() {
- def stringNum = "123"
- int expectedInt = 123
- int intNum = new Integer(stringNum).intValue()
+ def "givenString_whenUsingIntValue_thenConvertToInteger"() {
+ given:
+ int intNum = Integer.valueOf(STRING_NUM).intValue()
- assertEquals(intNum, expectedInt)
+ expect:
+ intNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingNewInteger_thenConvertToInteger() {
- def stringNum = "123"
- int expectedInt = 123
- int intNum = new Integer(stringNum)
+ def "givenString_whenUsingNewInteger_thenConvertToInteger"() {
+ given:
+ Integer intNum = Integer.valueOf(STRING_NUM)
- assertEquals(intNum, expectedInt)
+ expect:
+ intNum == EXPECTED_INT
}
- @Test
- void givenString_whenUsingDecimalFormat_thenConvertToInteger() {
- def stringNum = "123"
- int expectedInt = 123
+ def "givenString_whenUsingDecimalFormat_thenConvertToInteger"() {
+ given:
DecimalFormat decimalFormat = new DecimalFormat("#")
- int intNum = decimalFormat.parse(stringNum).intValue()
- assertEquals(intNum, expectedInt)
+ when:
+ int intNum = decimalFormat.parse(STRING_NUM).intValue()
+
+ then:
+ intNum == EXPECTED_INT
}
- @Test(expected = NumberFormatException.class)
- void givenInvalidString_whenUsingAs_thenThrowNumberFormatException() {
+ def "givenInvalidString_whenUsingAs_thenThrowNumberFormatException"() {
+ given:
def invalidString = "123a"
+
+ when:
invalidString as Integer
+
+ then:
+ thrown(NumberFormatException)
}
- @Test(expected = NullPointerException.class)
- void givenNullString_whenUsingToInteger_thenThrowNullPointerException() {
+ def "givenNullString_whenUsingToInteger_thenThrowNullPointerException"() {
+ given:
def invalidString = null
+
+ when:
invalidString.toInteger()
+
+ then:
+ thrown(NullPointerException)
}
- @Test
- void givenString_whenUsingIsInteger_thenCheckIfCorrectValue() {
+ def "givenString_whenUsingIsInteger_thenCheckIfCorrectValue"() {
+ given:
def invalidString = "123a"
def validString = "123"
+
+ when:
def invalidNum = invalidString?.isInteger() ? invalidString as Integer : false
def correctNum = validString?.isInteger() ? validString as Integer : false
- assertEquals(false, invalidNum)
- assertEquals(123, correctNum)
+ then:
+ !invalidNum
+ correctNum == 123
}
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
index c043723d95..30365ec9d7 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
@@ -1,19 +1,18 @@
package groovy.com.baeldung.stringtypes
-import org.junit.Assert
-import org.junit.Test
+import spock.lang.Specification
-class CharacterInGroovy {
+class CharacterInGroovy extends Specification {
- @Test
- void 'character'() {
+ def 'character'() {
+ given:
char a = 'A' as char
char b = 'B' as char
char c = (char) 'C'
- Assert.assertTrue(a instanceof Character)
- Assert.assertTrue(b instanceof Character)
- Assert.assertTrue(c instanceof Character)
+ expect:
+ a instanceof Character
+ b instanceof Character
+ c instanceof Character
}
-
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
index a730244d0a..e1074145f4 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
@@ -1,67 +1,76 @@
package groovy.com.baeldung.stringtypes
-import org.junit.Assert
-import org.junit.Test
+import spock.lang.Specification
-class DoubleQuotedString {
+class DoubleQuotedString extends Specification {
- @Test
- void 'escape double quoted string'() {
+ def 'escape double quoted string'() {
+ given:
def example = "Hello \"world\"!"
- println(example)
+ expect:
+ example == 'Hello "world"!'
}
- @Test
- void 'String ang GString'() {
+ def 'String ang GString'() {
+ given:
def string = "example"
def stringWithExpression = "example${2}"
- Assert.assertTrue(string instanceof String)
- Assert.assertTrue(stringWithExpression instanceof GString)
- Assert.assertTrue(stringWithExpression.toString() instanceof String)
+ expect:
+ string instanceof String
+ stringWithExpression instanceof GString
+ stringWithExpression.toString() instanceof String
}
- @Test
- void 'placeholder with variable'() {
+ def 'placeholder with variable'() {
+ given:
def name = "John"
+
+ when:
def helloName = "Hello $name!".toString()
- Assert.assertEquals("Hello John!", helloName)
+ then:
+ helloName == "Hello John!"
}
- @Test
- void 'placeholder with expression'() {
+ def 'placeholder with expression'() {
+ given:
def result = "result is ${2 * 2}".toString()
- Assert.assertEquals("result is 4", result)
+ expect:
+ result == "result is 4"
}
- @Test
- void 'placeholder with dotted access'() {
+ def 'placeholder with dotted access'() {
+ given:
def person = [name: 'John']
+ when:
def myNameIs = "I'm $person.name, and you?".toString()
- Assert.assertEquals("I'm John, and you?", myNameIs)
+ then:
+ myNameIs == "I'm John, and you?"
}
- @Test
- void 'placeholder with method call'() {
+ def 'placeholder with method call'() {
+ given:
def name = 'John'
+ when:
def result = "Uppercase name: ${name.toUpperCase()}".toString()
- Assert.assertEquals("Uppercase name: JOHN", result)
+ then:
+ result == "Uppercase name: JOHN"
}
- @Test
- void 'GString and String hashcode'() {
+ def 'GString and String hashcode'() {
+ given:
def string = "2+2 is 4"
def gstring = "2+2 is ${4}"
- Assert.assertTrue(string.hashCode() != gstring.hashCode())
+ expect:
+ string.hashCode() != gstring.hashCode()
}
-
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
index 569991b788..924515570c 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
@@ -1,15 +1,14 @@
package groovy.com.baeldung.stringtypes
-import org.junit.Assert
-import org.junit.Test
+import spock.lang.Specification
-class SingleQuotedString {
+class SingleQuotedString extends Specification {
- @Test
- void 'single quoted string'() {
- def example = 'Hello world'
+ def 'single quoted string'() {
+ given:
+ def example = 'Hello world!'
- Assert.assertEquals('Hello world!', 'Hello' + ' world!')
+ expect:
+ example == 'Hello' + ' world!'
}
-
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
index e45f352285..9d29210d81 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
@@ -1,26 +1,29 @@
package groovy.com.baeldung.stringtypes
-import org.junit.Assert
-import org.junit.Test
+import spock.lang.Specification
-class Strings {
+class Strings extends Specification {
- @Test
- void 'string interpolation '() {
+ def 'string interpolation '() {
+ given:
def name = "Kacper"
+ when:
def result = "Hello ${name}!"
- Assert.assertEquals("Hello Kacper!", result.toString())
+ then:
+ result.toString() == "Hello Kacper!"
}
- @Test
- void 'string concatenation'() {
+ def 'string concatenation'() {
+ given:
def first = "first"
def second = "second"
+ when:
def concatenation = first + second
- Assert.assertEquals("firstsecond", concatenation)
+ then:
+ concatenation == "firstsecond"
}
}
diff --git a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
index 85130e8f07..b47cba6437 100644
--- a/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
+++ b/core-groovy-modules/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
@@ -7,108 +7,111 @@ class TraitsUnitTest extends Specification {
Employee employee
Dog dog
- void setup () {
+ void setup() {
employee = new Employee()
dog = new Dog()
}
- def 'Should return msg string when using Employee.sayHello method provided by UserTrait' () {
+ def 'Should return msg string when using Employee.sayHello method provided by UserTrait'() {
when:
- def msg = employee.sayHello()
+ def msg = employee.sayHello()
+
then:
- msg
- msg instanceof String
- assert msg == "Hello!"
+ msg
+ msg instanceof String
+ msg == "Hello!"
}
-
- def 'Should return displayMsg string when using Employee.showName method' () {
+
+ def 'Should return displayMsg string when using Employee.showName method'() {
when:
- def displayMsg = employee.showName()
+ def displayMsg = employee.showName()
+
then:
- displayMsg
- displayMsg instanceof String
- assert displayMsg == "Hello, Bob!"
+ displayMsg
+ displayMsg instanceof String
+ displayMsg == "Hello, Bob!"
}
-
- def 'Should return greetMsg string when using Employee.greet method' () {
+
+ def 'Should return greetMsg string when using Employee.greet method'() {
when:
- def greetMsg = employee.greet()
+ def greetMsg = employee.greet()
+
then:
- greetMsg
- greetMsg instanceof String
- assert greetMsg == "Hello, from a private method!"
+ greetMsg
+ greetMsg instanceof String
+ greetMsg == "Hello, from a private method!"
}
-
- def 'Should return MissingMethodException when using Employee.greetingMessage method' () {
+
+ def 'Should return MissingMethodException when using Employee.greetingMessage method'() {
when:
- def exception
- try {
- employee.greetingMessage()
- }catch(Exception e) {
- exception = e
- }
-
+ employee.greetingMessage()
+
then:
- exception
- exception instanceof groovy.lang.MissingMethodException
- assert exception.message == "No signature of method: com.baeldung.traits.Employee.greetingMessage()"+
- " is applicable for argument types: () values: []"
+ thrown(MissingMethodException)
+ specificationContext.thrownException.message ==
+ "No signature of method: com.baeldung.traits.Employee.greetingMessage() is applicable for argument types: () values: []"
}
-
- def 'Should return employee instance when using Employee.whoAmI method' () {
+
+ def 'Should return employee instance when using Employee.whoAmI method'() {
when:
- def emp = employee.self()
+ def emp = employee.self()
+
then:
- emp
- emp instanceof Employee
- assert emp.is(employee)
+ emp
+ emp instanceof Employee
+ emp.is(employee)
}
-
- def 'Should display lastName when using Employee.showLastName method' () {
+
+ def 'Should display lastName when using Employee.showLastName method'() {
when:
- def lastNameMsg = employee.showLastName()
+ def lastNameMsg = employee.showLastName()
+
then:
- lastNameMsg
- lastNameMsg instanceof String
- assert lastNameMsg == "Hello, Marley!"
+ lastNameMsg
+ lastNameMsg instanceof String
+ lastNameMsg == "Hello, Marley!"
}
-
- def 'Should be able to define properties of UserTrait in Employee instance' () {
+
+ def 'Should be able to define properties of UserTrait in Employee instance'() {
when:
- employee = new Employee(email: "a@e.com", address: "baeldung.com")
+ employee = new Employee(email: "a@e.com", address: "baeldung.com")
+
then:
- employee
- employee instanceof Employee
- assert employee.email == "a@e.com"
- assert employee.address == "baeldung.com"
+ employee
+ employee instanceof Employee
+ employee.email == "a@e.com"
+ employee.address == "baeldung.com"
}
-
- def 'Should execute basicAbility method from SpeakingTrait and return msg string' () {
+
+ def 'Should execute basicAbility method from SpeakingTrait and return msg string'() {
when:
- def speakMsg = dog.basicAbility()
+ def speakMsg = dog.basicAbility()
+
then:
- speakMsg
- speakMsg instanceof String
- assert speakMsg == "Speaking!!"
+ speakMsg
+ speakMsg instanceof String
+ speakMsg == "Speaking!!"
}
-
- def 'Should verify multiple inheritance with traits and execute overridden traits method' () {
+
+ def 'Should verify multiple inheritance with traits and execute overridden traits method'() {
when:
- def walkSpeakMsg = dog.speakAndWalk()
- println walkSpeakMsg
+ def walkSpeakMsg = dog.speakAndWalk()
+ println walkSpeakMsg
+
then:
- walkSpeakMsg
- walkSpeakMsg instanceof String
- assert walkSpeakMsg == "Walk and speak!!"
+ walkSpeakMsg
+ walkSpeakMsg instanceof String
+ walkSpeakMsg == "Walk and speak!!"
}
-
- def 'Should implement AnimalTrait at runtime and access basicBehavior method' () {
+
+ def 'Should implement AnimalTrait at runtime and access basicBehavior method'() {
when:
- def dogInstance = new Dog() as AnimalTrait
- def basicBehaviorMsg = dogInstance.basicBehavior()
+ def dogInstance = new Dog() as AnimalTrait
+ def basicBehaviorMsg = dogInstance.basicBehavior()
+
then:
- basicBehaviorMsg
- basicBehaviorMsg instanceof String
- assert basicBehaviorMsg == "Animalistic!!"
+ basicBehaviorMsg
+ basicBehaviorMsg instanceof String
+ basicBehaviorMsg == "Animalistic!!"
}
-}
\ No newline at end of file
+}
diff --git a/core-groovy-modules/pom.xml b/core-groovy-modules/pom.xml
index e1ff538942..6faa7f94c8 100644
--- a/core-groovy-modules/pom.xml
+++ b/core-groovy-modules/pom.xml
@@ -21,12 +21,12 @@
- 2.5.7
- 2.5.6
- 2.5.6
- 2.4.0
- 1.1-groovy-2.4
- 1.6
+ 3.0.15
+ 3.0.15
+ 3.0.15
+ 2.7.1
+ 2.3-groovy-3.0
+ 2.1.0
-
\ No newline at end of file
+
diff --git a/core-java-modules/core-java-11-3/README.md b/core-java-modules/core-java-11-3/README.md
index e77e5b7f3d..4f5eb3ea56 100644
--- a/core-java-modules/core-java-11-3/README.md
+++ b/core-java-modules/core-java-11-3/README.md
@@ -5,3 +5,4 @@ This module contains articles about Java 11 core features
### Relevant articles
- [Adding Parameters to Java HttpClient Requests](https://www.baeldung.com/java-httpclient-request-parameters)
- [Writing a List of Strings Into a Text File](https://www.baeldung.com/java-list-to-text-file)
+- [Java HttpClient – Map JSON Response to Java Class](https://www.baeldung.com/java-httpclient-map-json-response)
diff --git a/core-java-modules/core-java-11-3/pom.xml b/core-java-modules/core-java-11-3/pom.xml
index b4a4591b28..ccccae5ba1 100644
--- a/core-java-modules/core-java-11-3/pom.xml
+++ b/core-java-modules/core-java-11-3/pom.xml
@@ -14,6 +14,20 @@
1.0.0-SNAPSHOT
../../pom.xml
+
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
@@ -32,6 +46,8 @@
11
11
+ 2.14.1
+ 2.10
\ No newline at end of file
diff --git a/core-java-modules/core-java-11-3/src/main/java/com/baeldung/httppojo/Todo.java b/core-java-modules/core-java-11-3/src/main/java/com/baeldung/httppojo/Todo.java
new file mode 100644
index 0000000000..01a1ee5c52
--- /dev/null
+++ b/core-java-modules/core-java-11-3/src/main/java/com/baeldung/httppojo/Todo.java
@@ -0,0 +1,73 @@
+package com.baeldung.httppojo;
+
+import java.util.Objects;
+
+public class Todo {
+
+ int userId;
+ int id;
+ String title;
+ boolean completed;
+
+ public Todo() {
+ }
+
+ public Todo(int userId, int id, String title, boolean completed) {
+ this.userId = userId;
+ this.id = id;
+ this.title = title;
+ this.completed = completed;
+ }
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ public void setCompleted(boolean completed) {
+ this.completed = completed;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ Todo todo = (Todo) o;
+ return userId == todo.userId && id == todo.id && completed == todo.completed && Objects.equals(title, todo.title);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(userId, id, title, completed);
+ }
+
+ @Override
+ public String toString() {
+ return "{" + "userId=" + userId + ", id=" + id + ", title='" + title + '\'' + ", completed=" + completed + '}';
+ }
+}
diff --git a/core-java-modules/core-java-11-3/src/main/java/com/baeldung/httppojo/TodoAppClient.java b/core-java-modules/core-java-11-3/src/main/java/com/baeldung/httppojo/TodoAppClient.java
new file mode 100644
index 0000000000..c2295d97ce
--- /dev/null
+++ b/core-java-modules/core-java-11-3/src/main/java/com/baeldung/httppojo/TodoAppClient.java
@@ -0,0 +1,107 @@
+package com.baeldung.httppojo;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.List;
+import java.util.concurrent.CompletionException;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+public class TodoAppClient {
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ Gson gson = new GsonBuilder().create();
+
+ public String sampleApiRequest() throws Exception {
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
+ .build();
+
+ HttpResponse response = client.send(request, BodyHandlers.ofString());
+
+ return response.body();
+
+ }
+
+ public Todo syncGson() throws Exception {
+ String response = sampleApiRequest();
+
+ List todo = gson.fromJson(response, new TypeToken>() {
+ }.getType());
+
+ return todo.get(1);
+
+ }
+
+ public Todo syncJackson() throws Exception {
+ String response = sampleApiRequest();
+
+ Todo[] todo = objectMapper.readValue(response, Todo[].class);
+
+ return todo[1];
+
+ }
+
+ public Todo asyncJackson() throws Exception {
+
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
+ .build();
+
+ TodoAppClient todoAppClient = new TodoAppClient();
+
+ List todo = HttpClient.newHttpClient()
+ .sendAsync(request, BodyHandlers.ofString())
+ .thenApply(HttpResponse::body)
+ .thenApply(todoAppClient::readValueJackson)
+ .get();
+
+ return todo.get(1);
+
+ }
+
+ public Todo asyncGson() throws Exception {
+
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
+ .build();
+ TodoAppClient todoAppClient = new TodoAppClient();
+
+ List todo = HttpClient.newHttpClient()
+ .sendAsync(request, BodyHandlers.ofString())
+ .thenApply(HttpResponse::body)
+ .thenApply(todoAppClient::readValueGson)
+ .get();
+
+ return todo.get(1);
+
+ }
+
+ List readValueJackson(String content) {
+
+ try {
+ return objectMapper.readValue(content, new TypeReference>() {
+ });
+ } catch (IOException ioe) {
+ throw new CompletionException(ioe);
+ }
+ }
+
+ List readValueGson(String content) {
+
+ return gson.fromJson(content, new TypeToken>() {
+ }.getType());
+
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-11-3/src/test/java/com/baeldung/httppojo/HttpClientPojoClassUnitTest.java b/core-java-modules/core-java-11-3/src/test/java/com/baeldung/httppojo/HttpClientPojoClassUnitTest.java
new file mode 100644
index 0000000000..a364a8d27e
--- /dev/null
+++ b/core-java-modules/core-java-11-3/src/test/java/com/baeldung/httppojo/HttpClientPojoClassUnitTest.java
@@ -0,0 +1,45 @@
+package com.baeldung.httppojo;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class HttpClientPojoClassUnitTest {
+
+ Todo expectedTodo = new Todo(1, 2, "quis ut nam facilis et officia qui", false);
+
+ @Test
+ public void givenSampleApiCall_whenResponseIsMappedByGson_thenCompareResponseMappedByGson() throws Exception {
+ TodoAppClient sampleGson = new TodoAppClient();
+
+ assertEquals(expectedTodo, sampleGson.syncGson());
+
+ }
+
+ @Test
+ public void givenSampleApiCall_whenResponseIsMappedByJackson_thenCompareResponseMappedByJackson() throws Exception {
+ TodoAppClient sampleJackson = new TodoAppClient();
+
+ assertEquals(expectedTodo, sampleJackson.syncJackson());
+ }
+
+ @Test
+ public void givenSampleRestApi_whenApiIsConsumedByHttpClient_thenCompareJsonString() throws Exception {
+ TodoAppClient sampleTest = new TodoAppClient();
+ assertNotNull(sampleTest.sampleApiRequest());
+
+ }
+
+ @Test
+ public void givenSampleApiAsyncCall_whenResponseIsMappedByJackson_thenCompareResponseMappedByJackson() throws Exception {
+ TodoAppClient sampleAsynJackson = new TodoAppClient();
+ assertEquals(expectedTodo, sampleAsynJackson.asyncJackson());
+ }
+
+ @Test
+ public void givenSampleApiAsyncCall_whenResponseIsMappedByGson_thenCompareResponseMappedByGson() throws Exception {
+ TodoAppClient sampleAsynGson = new TodoAppClient();
+ assertEquals(expectedTodo, sampleAsynGson.asyncGson());
+ }
+
+}
diff --git a/core-java-modules/core-java-14/README.md b/core-java-modules/core-java-14/README.md
index 00fd2fa320..97be9391fb 100644
--- a/core-java-modules/core-java-14/README.md
+++ b/core-java-modules/core-java-14/README.md
@@ -12,3 +12,4 @@ This module contains articles about Java 14.
- [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword)
- [New Features in Java 14](https://www.baeldung.com/java-14-new-features)
- [Java 14 Record vs. Lombok](https://www.baeldung.com/java-record-vs-lombok)
+- [Record vs. Final Class in Java](https://www.baeldung.com/java-record-vs-final-class)
diff --git a/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/recordvsfinal/USCitizen.java b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/recordvsfinal/USCitizen.java
new file mode 100644
index 0000000000..9ff3676ae7
--- /dev/null
+++ b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/recordvsfinal/USCitizen.java
@@ -0,0 +1,18 @@
+package com.baeldung.java14.recordvsfinal;
+
+public record USCitizen(String firstName, String lastName, String address) {
+ static int countryCode;
+
+ // static initializer
+ static {
+ countryCode = 1;
+ }
+
+ public static int getCountryCode() {
+ return countryCode;
+ }
+
+ public String getFullName() {
+ return firstName + " " + lastName;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/recordvsfinal/USCitizenUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/recordvsfinal/USCitizenUnitTest.java
new file mode 100644
index 0000000000..bb4c16b500
--- /dev/null
+++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/recordvsfinal/USCitizenUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.java14.recordvsfinal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class USCitizenUnitTest {
+
+ @Test
+ public void givenName_whenGetNameAndCode_thenExpectedValuesReturned() {
+
+ String firstName = "Joan";
+ String lastName = "Winn";
+ String address = "1892 Black Stallion Road";
+ int countryCode = 1;
+
+ USCitizen citizen = new USCitizen(firstName, lastName, address);
+
+ assertEquals(firstName + " " + lastName, citizen.getFullName());
+ assertEquals(countryCode, USCitizen.getCountryCode());
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-16/pom.xml b/core-java-modules/core-java-16/pom.xml
index 4adc3ee6d1..a2c0d4855b 100644
--- a/core-java-modules/core-java-16/pom.xml
+++ b/core-java-modules/core-java-16/pom.xml
@@ -63,4 +63,4 @@
3.0.0-M5
-
\ No newline at end of file
+
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/enumallt/DinosaurEnum.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/enumallt/DinosaurEnum.java
new file mode 100644
index 0000000000..a50f79947c
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/enumallt/DinosaurEnum.java
@@ -0,0 +1,19 @@
+package com.baeldung.instanceofalternative.enumallt;
+
+public enum DinosaurEnum {
+ Anatotitan {
+ @Override
+ public String move() {
+ return "running";
+ }
+ },
+ Euraptor {
+ @Override
+ public String move() {
+ return "flying";
+ }
+ };
+
+ public abstract String move();
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Anatotitan.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Anatotitan.java
new file mode 100644
index 0000000000..ce59b58ad7
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Anatotitan.java
@@ -0,0 +1,15 @@
+package com.baeldung.instanceofalternative.model;
+
+public class Anatotitan extends Dinosaur {
+ // polymorphism
+ @Override
+ public String move() {
+ return "running";
+ }
+
+ // non-polymorphism
+ public String run() {
+ return "running";
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Dinosaur.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Dinosaur.java
new file mode 100644
index 0000000000..38055054f5
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Dinosaur.java
@@ -0,0 +1,9 @@
+package com.baeldung.instanceofalternative.model;
+
+public class Dinosaur {
+
+ public String move() {
+ return "default movement";
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Euraptor.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Euraptor.java
new file mode 100644
index 0000000000..1de5257a0d
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/model/Euraptor.java
@@ -0,0 +1,15 @@
+package com.baeldung.instanceofalternative.model;
+
+public class Euraptor extends Dinosaur {
+ // polymorphism
+ @Override
+ public String move() {
+ return "flying";
+ }
+
+ // non-polymorphism
+ public String flies() {
+ return "flying";
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Anatotitan.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Anatotitan.java
new file mode 100644
index 0000000000..84d93e7350
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Anatotitan.java
@@ -0,0 +1,14 @@
+package com.baeldung.instanceofalternative.visitorspattern;
+
+public class Anatotitan implements Dino {
+
+ String run() {
+ return "running";
+ }
+
+ @Override
+ public String move(Visitor dinobehave) {
+ return dinobehave.visit(this);
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Dino.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Dino.java
new file mode 100644
index 0000000000..ef33baf2a4
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Dino.java
@@ -0,0 +1,7 @@
+package com.baeldung.instanceofalternative.visitorspattern;
+
+public interface Dino {
+
+ String move(Visitor dinoMove);
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/DinoVisitorImpl.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/DinoVisitorImpl.java
new file mode 100644
index 0000000000..6fd71374fa
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/DinoVisitorImpl.java
@@ -0,0 +1,15 @@
+package com.baeldung.instanceofalternative.visitorspattern;
+
+public class DinoVisitorImpl implements Visitor {
+
+ @Override
+ public String visit(Anatotitan anatotitan) {
+ return anatotitan.run();
+ }
+
+ @Override
+ public String visit(Euraptor euraptor) {
+ return euraptor.flies();
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Euraptor.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Euraptor.java
new file mode 100644
index 0000000000..fdce1e6c0b
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Euraptor.java
@@ -0,0 +1,14 @@
+package com.baeldung.instanceofalternative.visitorspattern;
+
+public class Euraptor implements Dino {
+
+ String flies() {
+ return "flying";
+ }
+
+ @Override
+ public String move(Visitor dinobehave) {
+ return dinobehave.visit(this);
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Visitor.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Visitor.java
new file mode 100644
index 0000000000..75fada3533
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/instanceof_alternatives/visitorspattern/Visitor.java
@@ -0,0 +1,9 @@
+package com.baeldung.instanceofalternative.visitorspattern;
+
+public interface Visitor {
+
+ String visit(Anatotitan anatotitan);
+
+ String visit(Euraptor euraptor);
+
+}
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/EnumUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/EnumUnitTest.java
new file mode 100644
index 0000000000..73faa2a1ef
--- /dev/null
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/EnumUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.instanceoftest;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.baeldung.instanceofalternative.enumallt.*;
+
+public class EnumUnitTest {
+ @Test
+ public void givenADinosaurSpecie_whenUsingEnum_thenGetMovementOfEuraptor() {
+
+ assertEquals("flying", moveDinosaurUsingEnum(DinosaurEnum.Euraptor));
+ }
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingEnum_thenGetMovementOfAnatotitan() {
+ assertEquals("running", moveDinosaurUsingEnum(DinosaurEnum.Anatotitan));
+ }
+
+ public static String moveDinosaurUsingEnum(DinosaurEnum dinosaurenum) {
+ return dinosaurenum.move();
+
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/ExampleSetupUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/ExampleSetupUnitTest.java
new file mode 100644
index 0000000000..c42f77849b
--- /dev/null
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/ExampleSetupUnitTest.java
@@ -0,0 +1,35 @@
+package com.baeldung.instanceoftest;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.baeldung.instanceofalternative.model.*;
+
+public class ExampleSetupUnitTest {
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingInstancof_thenGetMovementOfAnatotitan() {
+
+ assertEquals("running", moveDinosaurUsingInstanceof(new Anatotitan()));
+ }
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingInstanceof_thenGetMovementOfEuraptor() {
+ assertEquals("flying", moveDinosaurUsingInstanceof(new Euraptor()));
+ }
+
+ public static String moveDinosaurUsingInstanceof(Dinosaur dinosaur) {
+
+ if (dinosaur instanceof Anatotitan) {
+
+ Anatotitan anatotitan = (Anatotitan) dinosaur;
+ return anatotitan.run();
+ } else if (dinosaur instanceof Euraptor) {
+ Euraptor euraptor = (Euraptor) dinosaur;
+ return euraptor.flies();
+ }
+ return "";
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/GetClassUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/GetClassUnitTest.java
new file mode 100644
index 0000000000..6a4886c8a3
--- /dev/null
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/GetClassUnitTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.instanceoftest;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+import com.baeldung.instanceofalternative.model.*;
+
+public class GetClassUnitTest {
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingGetClass_thenGetMovementOfAnatotitan() {
+
+ assertEquals("running", moveDinosaurUsingGetClass(new Anatotitan()));
+ }
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingGetClass_thenGetMovementOfEuraptor() {
+ assertEquals("flying", moveDinosaurUsingGetClass(new Euraptor()));
+ }
+
+ public static String moveDinosaurUsingGetClass(Dinosaur dinosaur) {
+
+ if (dinosaur.getClass()
+ .equals(Anatotitan.class)) {
+
+ Anatotitan anatotitan = (Anatotitan) dinosaur;
+ return anatotitan.run();
+ } else if (dinosaur.getClass()
+ .equals(Euraptor.class)) {
+ Euraptor euraptor = (Euraptor) dinosaur;
+ return euraptor.flies();
+ }
+ return "";
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/PolymorphismUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/PolymorphismUnitTest.java
new file mode 100644
index 0000000000..960ed34c82
--- /dev/null
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/PolymorphismUnitTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.instanceoftest;
+
+import static org.junit.Assert.*;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.baeldung.instanceofalternative.model.*;
+
+public class PolymorphismUnitTest {
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingPolymorphism_thenGetMovementOfAnatotitan() {
+
+ assertEquals("running", moveDinosaurUsingPolymorphism(new Anatotitan()));
+ }
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingPolymorphism_thenGetMovementOfEuraptor() {
+ assertEquals("flying", moveDinosaurUsingPolymorphism(new Euraptor()));
+ }
+
+ public static String moveDinosaurUsingPolymorphism(Dinosaur dinosaur) {
+ return dinosaur.move();
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/VisitorsPatternUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/VisitorsPatternUnitTest.java
new file mode 100644
index 0000000000..287f7df798
--- /dev/null
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/instanceof_alternative_test/VisitorsPatternUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.instanceoftest;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.baeldung.instanceofalternative.visitorspattern.*;
+
+public class VisitorsPatternUnitTest {
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingVisitorPattern_thenGetMovementOfAnatotitan() {
+
+ assertEquals("running", moveDinosaurUsingVisitorPattern((Dino) new Anatotitan()));
+ }
+
+ @Test
+ public void givenADinosaurSpecie_whenUsingVisitorPattern_thenGetMovementOfEuraptor() {
+
+ assertEquals("flying", moveDinosaurUsingVisitorPattern((Dino) new Euraptor()));
+ }
+
+ public static String moveDinosaurUsingVisitorPattern(Dino dinosaur) {
+ Visitor visitor = new DinoVisitorImpl();
+
+ return dinosaur.move(visitor);
+ }
+
+}
diff --git a/core-java-modules/core-java-17/README.md b/core-java-modules/core-java-17/README.md
index 9f39b0289f..1af860b7c4 100644
--- a/core-java-modules/core-java-17/README.md
+++ b/core-java-modules/core-java-17/README.md
@@ -6,3 +6,4 @@
- [New Features in Java 17](https://www.baeldung.com/java-17-new-features)
- [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators)
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
+- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Address.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Address.java
new file mode 100644
index 0000000000..b654ffe2c5
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Address.java
@@ -0,0 +1,40 @@
+package com.baeldung.java8to17;
+
+public class Address {
+
+ private String street;
+ private String city;
+ private String pin;
+
+ public Address(String street, String city, String pin) {
+ super();
+ this.street = street;
+ this.city = city;
+ this.pin = pin;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getPin() {
+ return pin;
+ }
+
+ public void setPin(String pin) {
+ this.pin = pin;
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Circle.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Circle.java
new file mode 100644
index 0000000000..1e346653cf
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Circle.java
@@ -0,0 +1,4 @@
+package com.baeldung.java8to17;
+
+public record Circle(double radius) implements Shape {
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Person.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Person.java
new file mode 100644
index 0000000000..a6c9f50fc8
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Person.java
@@ -0,0 +1,30 @@
+package com.baeldung.java8to17;
+
+public class Person {
+
+ private String name;
+ private Address address;
+
+ public Person(String name, Address address) {
+ super();
+ this.name = name;
+ this.address = address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Rectangle.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Rectangle.java
new file mode 100644
index 0000000000..79d2f0358b
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Rectangle.java
@@ -0,0 +1,4 @@
+package com.baeldung.java8to17;
+
+public record Rectangle(double length, double width) implements Shape {
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Shape.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Shape.java
new file mode 100644
index 0000000000..60b5193468
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Shape.java
@@ -0,0 +1,5 @@
+package com.baeldung.java8to17;
+
+public interface Shape {
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Student.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Student.java
new file mode 100644
index 0000000000..056bc4b7d5
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/java8to17/Student.java
@@ -0,0 +1,5 @@
+package com.baeldung.java8to17;
+
+public record Student(int rollNo, String name) {
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/java17/Java8to17ExampleUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/java17/Java8to17ExampleUnitTest.java
new file mode 100644
index 0000000000..950fc70988
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/java17/Java8to17ExampleUnitTest.java
@@ -0,0 +1,87 @@
+package com.baeldung.java17;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import com.baeldung.java8to17.Address;
+import com.baeldung.java8to17.Circle;
+import com.baeldung.java8to17.Person;
+import com.baeldung.java8to17.Rectangle;
+import com.baeldung.java8to17.Student;
+
+public class Java8to17ExampleUnitTest {
+
+ @Test
+ void givenMultiLineText_whenUsingTextBlock_thenStringIsReturned() {
+ String value = """
+ This is a
+ Multi-line
+ Text
+ """;
+
+ assertThat(value).isEqualTo("This is a\nMulti-line\nText\n");
+ }
+
+ @Test
+ void givenString_whenUsingUtilFunctions_thenReturnsExpectedResult() {
+ assertThat(" ".isBlank());
+ assertThat("Twinkle ".repeat(2)).isEqualTo("Twinkle Twinkle ");
+ assertThat("Format Line".indent(4)).isEqualTo(" Format Line\n");
+ assertThat("Line 1 \n Line2".lines()).asList().size().isEqualTo(2);
+ assertThat(" Text with white spaces ".strip()).isEqualTo("Text with white spaces");
+ assertThat("Car, Bus, Train".transform(s1 -> Arrays.asList(s1.split(","))).get(0)).isEqualTo("Car");
+ }
+
+ @Test
+ void givenDataModel_whenUsingRecordType_thenBehavesLikeDTO() {
+ Student student = new Student(10, "Priya");
+ Student student2 = new Student(10, "Priya");
+
+ assertThat(student.rollNo()).isEqualTo(10);
+ assertThat(student.name()).isEqualTo("Priya");
+ assertThat(student.equals(student2));
+ assertThat(student.hashCode()).isEqualTo(student2.hashCode());
+ }
+
+ @Test
+ void givenObject_whenThrowingNPE_thenReturnsHelpfulMessage() {
+ Person student = new Person("Lakshmi", new Address("35, West Street", null, null));
+
+ Exception exception = assertThrows(NullPointerException.class, () -> {
+ student.getAddress().getCity().toLowerCase();
+ });
+
+ assertThat(exception.getMessage()).isEqualTo(
+ "Cannot invoke \"String.toLowerCase()\" because the return value of \"com.baeldung.java8to17.Address.getCity()\" is null");
+ }
+
+ @Test
+ void givenGenericObject_whenUsingPatternMatching_thenReturnsTargetType() {
+ String city = null;
+ Object obj = new Address("35, West Street", "Chennai", "6000041");
+
+ if (obj instanceof Address address) {
+ city = address.getCity();
+ }
+
+ assertThat(city).isEqualTo("Chennai");
+ }
+
+ @Test
+ void givenGenericObject_whenUsingSwitchExpression_thenPatternMatchesRightObject() {
+ Object shape = new Rectangle(10, 20);
+
+ double circumference = switch (shape) {
+ case Rectangle r -> 2 * r.length() + 2 * r.width();
+ case Circle c -> 2 * c.radius() * Math.PI;
+ default -> throw new IllegalArgumentException("Unknown shape");
+ };
+
+ assertThat(circumference).isEqualTo(60);
+ }
+
+}
diff --git a/core-java-modules/core-java-19/README.md b/core-java-modules/core-java-19/README.md
new file mode 100644
index 0000000000..6a9c6c7fdd
--- /dev/null
+++ b/core-java-modules/core-java-19/README.md
@@ -0,0 +1,3 @@
+## Relevant Articles
+- [Record Patterns in Java 19](https://www.baeldung.com/java-19-record-patterns)
+- [Structured Concurrency in Java 19](https://www.baeldung.com/java-structured-concurrency)
diff --git a/core-java-modules/core-java-19/pom.xml b/core-java-modules/core-java-19/pom.xml
new file mode 100644
index 0000000000..096b13e679
--- /dev/null
+++ b/core-java-modules/core-java-19/pom.xml
@@ -0,0 +1,33 @@
+
+
+ 4.0.0
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+ core-java-19
+
+
+ 19
+ 19
+ UTF-8
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 19
+ 19
+ --enable-preview
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/GPSPoint.java b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/GPSPoint.java
new file mode 100644
index 0000000000..961575c88d
--- /dev/null
+++ b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/GPSPoint.java
@@ -0,0 +1,3 @@
+package com.baeldung.features.records;
+
+public record GPSPoint (double lat, double lng) { }
\ No newline at end of file
diff --git a/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/ILocation.java b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/ILocation.java
new file mode 100644
index 0000000000..00851c8d5e
--- /dev/null
+++ b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/ILocation.java
@@ -0,0 +1,9 @@
+package com.baeldung.features.records;
+
+public sealed interface ILocation permits Location {
+ default String getName() {
+ return switch (this) {
+ case Location(var name, var ignored) -> name;
+ };
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/Location.java b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/Location.java
new file mode 100644
index 0000000000..fb50fbe645
--- /dev/null
+++ b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/Location.java
@@ -0,0 +1,5 @@
+package com.baeldung.features.records;
+
+public record Location(String name, GPSPoint gpsPoint) implements ILocation {
+}
+
diff --git a/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/LocationWrapper.java b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/LocationWrapper.java
new file mode 100644
index 0000000000..e7ddfef5f0
--- /dev/null
+++ b/core-java-modules/core-java-19/src/main/java/com/baeldung/features/records/LocationWrapper.java
@@ -0,0 +1,3 @@
+package com.baeldung.features.records;
+
+public record LocationWrapper(T t, String description) { }
diff --git a/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP405RecordPatternsUnitTest.java b/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP405RecordPatternsUnitTest.java
new file mode 100644
index 0000000000..10ad33b411
--- /dev/null
+++ b/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP405RecordPatternsUnitTest.java
@@ -0,0 +1,99 @@
+package com.baeldung.features;
+
+import com.baeldung.features.records.GPSPoint;
+import com.baeldung.features.records.Location;
+import com.baeldung.features.records.LocationWrapper;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+
+public class JEP405RecordPatternsUnitTest {
+
+ Object object = new Location("Home", new GPSPoint(1.0, 2.0));
+
+ @Test
+ void givenObject_whenTestInstanceOfAndCastIdiom_shouldMatchNewInstanceOf() {
+ // old Code
+ if (object instanceof Location) {
+ Location l = (Location) object;
+ assertThat(l).isInstanceOf(Location.class);
+ }
+ // new code
+ if (object instanceof Location l) {
+ assertThat(l).isInstanceOf(Location.class);
+ }
+ }
+
+ @Test
+ void givenObject_whenTestDestruct_shouldMatch() {
+ // when
+ if (object instanceof Location(var name, var gpsPoint)) {
+ // then
+ assertThat(name).isEqualTo("Home");
+ assertThat(gpsPoint).isInstanceOf(GPSPoint.class);
+ }
+
+ if (object instanceof Location(var name, GPSPoint(var lat, var lng))) {
+ assertThat(lat).isEqualTo(1.0);
+ assertThat(lng).isEqualTo(2.0);
+ }
+ }
+
+ @Test
+ void givenObjectIsNull_whenTestNullCheck_shouldNotMatch() {
+ Location l = null;
+ if (l instanceof Location location) {
+ assertThat(location).isNotNull();
+ }
+ }
+
+
+ @Test
+ void givenObject_whenTestGenericTypeInstanceOf_shouldMatch() {
+ LocationWrapper locationWrapper = new LocationWrapper<>(new Location("Home", new GPSPoint(1.0, 2.0)), "Description");
+ if (locationWrapper instanceof LocationWrapper(var ignored, var description)) {
+ assertThat(description).isEqualTo("Description");
+ }
+ }
+
+
+ @Test
+ void givenObject_whenTestSwitchExpressionWithTypePattern_shouldMatch() {
+ String result = switch (object) {
+ case Location l -> l.name();
+ default -> "default";
+ };
+ assertThat(result).isEqualTo("Home");
+ Double result2 = switch (object) {
+ case Location(var name, GPSPoint(var lat, var lng)) -> lat;
+ default -> 0.0;
+ };
+ assertThat(result2).isEqualTo(1.0);
+ }
+
+ @Test
+ void givenObject_whenTestGuardedSwitchExpressionWithTypePattern_shouldMatchAndGuard() {
+ String result = switch (object) {
+ case Location(var name, var ignored) when name.equals("Home") -> "Test";
+ case Location(var name, var ignored) -> name;
+ default -> "default";
+ };
+ assertThat(result).isEqualTo("Test");
+
+ String otherResult = switch (new Location("Other", new GPSPoint(1.0, 2.0))) {
+ case Location(var name, var ignored) when name.equals("Home") -> "Test";
+ case Location(var name, var ignored) -> name;
+ default -> "default";
+ };
+ assertThat(otherResult).isEqualTo("Other");
+
+ Object noLocation = new GPSPoint(1.0, 2.0);
+ String noLocationResult = switch (noLocation) {
+ case Location(var name, var ignored) when name.equals("Home") -> "Test";
+ case Location(var name, var ignored) -> name;
+ default -> "default";
+ };
+ assertThat(noLocationResult).isEqualTo("default");
+ }
+}
diff --git a/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java b/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java
new file mode 100644
index 0000000000..64cd84ba01
--- /dev/null
+++ b/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java
@@ -0,0 +1,122 @@
+package com.baeldung.features;
+
+import jdk.incubator.concurrent.StructuredTaskScope;
+import org.junit.jupiter.api.Test;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.concurrent.*;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
+
+public class JEP428StructuredConcurrencyUnitTest {
+
+ private static final String ERROR_MESSAGE = "Failed to get the result";
+
+ @Test
+ public void givenStructuredConcurrency_whenThrowingException_thenCorrect() {
+ assertThatThrownBy(() -> {
+ try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+ Future shelter = scope.fork(this::getShelter);
+ Future> dogs = scope.fork(this::getDogsWithException);
+ scope.throwIfFailed(e -> new RuntimeException(ERROR_MESSAGE));
+ scope.join();
+ Response response = new Response(shelter.resultNow(), dogs.resultNow());
+
+ assertThat(response).isNotNull();
+ assertThat(response.shelter()).isNotNull();
+ assertThat(response.dogs()).isNotNull();
+ assertThat(response.dogs().size()).isEqualTo(2);
+ }
+ }).isInstanceOf(RuntimeException.class)
+ .hasMessage(ERROR_MESSAGE);
+ }
+
+ @Test
+ public void givenStructuredConcurrency_whenSlowTasksReachesDeadline_thenCorrect() {
+ assertThatThrownBy(() -> {
+ try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+ Future shelter = scope.fork(this::getShelter);
+ Future> dogs = scope.fork(this::getDogsSlowly);
+ scope.throwIfFailed(e -> new RuntimeException(ERROR_MESSAGE));
+ scope.join();
+ scope.joinUntil(Instant.now().plusMillis(50));
+ Response response = new Response(shelter.resultNow(), dogs.resultNow());
+
+ assertThat(response).isNotNull();
+ assertThat(response.shelter()).isNotNull();
+ assertThat(response.dogs()).isNotNull();
+ assertThat(response.dogs().size()).isEqualTo(2);
+
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }).isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void givenStructuredConcurrency_whenResultNow_thenCorrect() {
+ try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+ Future shelter = scope.fork(this::getShelter);
+ Future> dogs = scope.fork(this::getDogs);
+ scope.join();
+
+ Response response = new Response(shelter.resultNow(), dogs.resultNow());
+
+ assertThat(response).isNotNull();
+ assertThat(response.shelter()).isNotNull();
+ assertThat(response.dogs()).isNotNull();
+ assertThat(response.dogs().size()).isEqualTo(2);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void givenUnstructuredConcurrency_whenGet_thenCorrect() {
+ Future shelter;
+ Future> dogs;
+ try (ExecutorService executorService = Executors.newFixedThreadPool(3)) {
+ shelter = executorService.submit(this::getShelter);
+ dogs = executorService.submit(this::getDogs);
+ Shelter theShelter = shelter.get(); // Join the shelter
+ List theDogs = dogs.get(); // Join the dogs
+ Response response = new Response(theShelter, theDogs);
+
+ assertThat(response).isNotNull();
+ assertThat(response.shelter()).isNotNull();
+ assertThat(response.dogs()).isNotNull();
+ assertThat(response.dogs().size()).isEqualTo(2);
+
+ } catch (ExecutionException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Shelter getShelter() {
+ return new Shelter("Shelter");
+ }
+
+ private List getDogs() {
+ return List.of(new Dog("Buddy"), new Dog("Simba"));
+ }
+
+ private List getDogsWithException() {
+ throw new RuntimeException(ERROR_MESSAGE);
+ }
+
+ private List getDogsSlowly() throws InterruptedException {
+ Thread.sleep(1500);
+ throw new RuntimeException(ERROR_MESSAGE);
+ }
+
+ record Shelter(String name) {
+ }
+
+ record Dog(String name) {
+ }
+
+ record Response(Shelter shelter, List dogs) {
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/README.md b/core-java-modules/core-java-8-2/README.md
index c0bc63f21f..cad4a4f1fa 100644
--- a/core-java-modules/core-java-8-2/README.md
+++ b/core-java-modules/core-java-8-2/README.md
@@ -10,4 +10,5 @@ This module contains articles about Java 8 core features
- [Interface With Default Methods vs Abstract Class](https://www.baeldung.com/java-interface-default-method-vs-abstract-class)
- [Convert Between Byte Array and UUID in Java](https://www.baeldung.com/java-byte-array-to-uuid)
- [Create a Simple “Rock-Paper-Scissors” Game in Java](https://www.baeldung.com/java-rock-paper-scissors)
+- [VarArgs vs Array Input Parameters in Java](https://www.baeldung.com/varargs-vs-array)
- [[<-- Prev]](/core-java-modules/core-java-8)
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/argsVsvarargs/StringArrayAndVarargs.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/argsVsvarargs/StringArrayAndVarargs.java
new file mode 100644
index 0000000000..dc9137646f
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/argsVsvarargs/StringArrayAndVarargs.java
@@ -0,0 +1,19 @@
+package com.baeldung.argsVsvarargs;
+
+public class StringArrayAndVarargs {
+ public static void capitalizeNames(String[] args) {
+ for(int i = 0; i < args.length; i++){
+ args[i] = args[i].toUpperCase();
+ }
+
+ }
+
+ public static String[] firstLetterOfWords(String... args) {
+ String[] firstLetter = new String[args.length];
+ for(int i = 0; i < args.length; i++){
+ firstLetter[i] = String.valueOf(args[i].charAt(0));
+ }
+ return firstLetter;
+ }
+
+}
diff --git a/core-java-modules/core-java-8-2/src/test/java/com/baeldung/argsVsvarargs/StringArrayAndVarargsUnitTest.java b/core-java-modules/core-java-8-2/src/test/java/com/baeldung/argsVsvarargs/StringArrayAndVarargsUnitTest.java
new file mode 100644
index 0000000000..f917373229
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/test/java/com/baeldung/argsVsvarargs/StringArrayAndVarargsUnitTest.java
@@ -0,0 +1,24 @@
+package com.baeldung.argsVsvarargs;
+
+import static com.baeldung.argsVsvarargs.StringArrayAndVarargs.capitalizeNames;
+import static com.baeldung.argsVsvarargs.StringArrayAndVarargs.firstLetterOfWords;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class StringArrayAndVarargsUnitTest {
+
+ @Test
+ void whenCheckingArgumentClassName_thenNameShouldBeStringArray() {
+ String[] names = {"john", "ade", "kofi", "imo"};
+ assertNotNull(names);
+ assertEquals("java.lang.String[]", names.getClass().getTypeName());
+ capitalizeNames(names);
+ }
+
+ @Test
+ void whenCheckingReturnedObjectClass_thenClassShouldBeStringArray() {
+ assertEquals(String[].class, firstLetterOfWords("football", "basketball", "volleyball").getClass());
+ assertEquals(3, firstLetterOfWords("football", "basketball", "volleyball").length);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/README.md b/core-java-modules/core-java-8/README.md
index ff4ceaf6db..6061f3318d 100644
--- a/core-java-modules/core-java-8/README.md
+++ b/core-java-modules/core-java-8/README.md
@@ -11,4 +11,5 @@ This module contains articles about Java 8 core features
- [Finding Min/Max in an Array with Java](https://www.baeldung.com/java-array-min-max)
- [Internationalization and Localization in Java 8](https://www.baeldung.com/java-8-localization)
- [Generalized Target-Type Inference in Java](https://www.baeldung.com/java-generalized-target-type-inference)
+- [Monads in Java](https://www.baeldung.com/java-monads)
- [[More -->]](/core-java-modules/core-java-8-2)
diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/monad/MonadSamples.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/monad/MonadSamples.java
new file mode 100644
index 0000000000..87b7fe697e
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/monad/MonadSamples.java
@@ -0,0 +1,82 @@
+package com.baeldung.monad;
+
+import java.util.Optional;
+import java.util.function.Function;
+
+class MonadBaseExample {
+
+ public double multiplyBy2(double n) {
+ return n * 2;
+ }
+
+ public double divideBy2(double n) {
+ return n / 2;
+ }
+
+ public double add3(double n) {
+ return n + 3;
+ }
+
+ public double subtract1(double n) {
+ return n - 1;
+ }
+
+}
+
+class MonadSample1 extends MonadBaseExample {
+
+ public double apply(double n) {
+ return subtract1(add3(divideBy2(multiplyBy2(multiplyBy2(2)))));
+ }
+}
+
+class MonadSample2 extends MonadBaseExample {
+ public double apply(double n) {
+ double n1 = multiplyBy2(n);
+ double n2 = multiplyBy2(n1);
+ double n3 = divideBy2(n2);
+ double n4 = add3(n3);
+ return subtract1(n4);
+ }
+}
+
+class MonadSample3 extends MonadBaseExample {
+
+ public double apply(double n) {
+ return Optional.of(n)
+ .flatMap(value -> Optional.of(multiplyBy2(value)))
+ .flatMap(value -> Optional.of(multiplyBy2(value)))
+ .flatMap(value -> Optional.of(divideBy2(value)))
+ .flatMap(value -> Optional.of(add3(value)))
+ .flatMap(value -> Optional.of(subtract1(value)))
+ .get();
+ }
+
+}
+
+ class MonadSample4 extends MonadBaseExample {
+ public boolean leftIdentity() {
+ Function> mapping = value -> Optional.of(value + 1);
+ return Optional.of(3).flatMap(mapping).equals(mapping.apply(3));
+ }
+
+ public boolean rightIdentity() {
+ return Optional.of(3).flatMap(Optional::of).equals(Optional.of(3));
+ }
+
+ public boolean associativity() {
+ Function> mapping = value -> Optional.of(value + 1);
+ Optional leftSide = Optional.of(3).flatMap(mapping).flatMap(Optional::of);
+ Optional rightSide = Optional.of(3).flatMap(v -> mapping.apply(v).flatMap(Optional::of));
+ return leftSide.equals(rightSide);
+ }
+
+ }
+
+class MonadSample5 extends MonadBaseExample {
+ public boolean fail() {
+ Function> mapping = value -> Optional.of(value == null ? -1 : value + 1);
+ return Optional.ofNullable((Integer) null).flatMap(mapping).equals(mapping.apply(null));
+ }
+}
+
diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/monad/MonadSampleUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/monad/MonadSampleUnitTest.java
new file mode 100644
index 0000000000..c851f5f750
--- /dev/null
+++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/monad/MonadSampleUnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.monad;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MonadSampleUnitTest {
+
+ @Test
+ public void whenNotUsingMonad_shouldBeOk() {
+ MonadSample1 test = new MonadSample1();
+ Assert.assertEquals(6.0, test.apply(2), 0.000);
+ }
+
+ @Test
+ public void whenNotUsingMonadButUsingTempVars_shouldBeOk() {
+ MonadSample2 test = new MonadSample2();
+ Assert.assertEquals(6.0, test.apply(2), 0.000);
+ }
+
+ @Test
+ public void whenUsingMonad_shouldBeOk() {
+ MonadSample3 test = new MonadSample3();
+ Assert.assertEquals(6.0, test.apply(2), 0.000);
+ }
+
+ @Test
+ public void whenTestingMonadProperties_shouldBeOk() {
+ MonadSample4 test = new MonadSample4();
+ Assert.assertEquals(true, test.leftIdentity());
+ Assert.assertEquals(true, test.rightIdentity());
+ Assert.assertEquals(true, test.associativity());
+ }
+
+ @Test
+ public void whenBreakingMonadProperties_shouldBeFalse() {
+ MonadSample5 test = new MonadSample5();
+ Assert.assertEquals(false, test.fail());
+ }
+}
diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java
index aad7cf49eb..d0a325a155 100644
--- a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java
+++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarningsNames.java
@@ -17,7 +17,7 @@ public class ClassWithSuppressWarningsNames implements Serializable {
list.add(Integer.valueOf(value));
}
- @SuppressWarnings("deprecated")
+ @SuppressWarnings("deprecation")
void suppressDeprecatedWarning() {
ClassWithSuppressWarningsNames cls = new ClassWithSuppressWarningsNames();
cls.deprecatedMethod(); // no warning here
diff --git a/core-java-modules/core-java-arrays-convert/README.md b/core-java-modules/core-java-arrays-convert/README.md
index b28b97cb09..4365fd12f9 100644
--- a/core-java-modules/core-java-arrays-convert/README.md
+++ b/core-java-modules/core-java-arrays-convert/README.md
@@ -6,3 +6,4 @@ This module contains articles about arrays conversion in Java
- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array)
- [Converting Between Stream and Array in Java](https://www.baeldung.com/java-stream-to-array)
- [Convert a Byte Array to a Numeric Representation in Java](https://www.baeldung.com/java-byte-array-to-number)
+- [Converting a String Array Into an int Array in Java](https://www.baeldung.com/java-convert-string-array-to-int-array)
diff --git a/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/StringArrayToIntArrayUnitTest.java b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/StringArrayToIntArrayUnitTest.java
new file mode 100644
index 0000000000..3675778f90
--- /dev/null
+++ b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/StringArrayToIntArrayUnitTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.array.conversions;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+
+public class StringArrayToIntArrayUnitTest {
+ private final String[] stringArray = new String[] { "1", "2", "3", "4", "5", "6", "42" };
+ private final int[] expected = new int[] { 1, 2, 3, 4, 5, 6, 42 };
+
+ private final String[] stringArrayWithInvalidNum = new String[] { "1", "2", "hello", "4", "world", "6", "42" };
+ private final int[] expectedWithInvalidInput = new int[] { 1, 2, Integer.MIN_VALUE, 4, Integer.MIN_VALUE, 6, 42 };
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Test
+ void givenStringArray_whenUseStreamApi_shouldGetExpectedIntArray() {
+ int[] result = Arrays.stream(stringArray).mapToInt(Integer::parseInt).toArray();
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void givenStringArrayWithInvalidNum_whenUseStreamApi_shouldGetExpectedIntArray() {
+ int[] result = Arrays.stream(stringArrayWithInvalidNum).mapToInt(s -> {
+ try {
+ return Integer.parseInt(s);
+ } catch (NumberFormatException ex) {
+ logger.warn("Invalid number format detected: {}, use Int.MinValue as the fallback", s);
+ return Integer.MIN_VALUE;
+ }
+ }).toArray();
+ assertArrayEquals(expectedWithInvalidInput, result);
+ }
+
+ @Test
+ void givenStringArray_whenConvertInLoop_shouldGetExpectedIntArray() {
+ int[] result = new int[stringArray.length];
+ for (int i = 0; i < stringArray.length; i++) {
+ result[i] = Integer.parseInt(stringArray[i]);
+ }
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void givenStringArrayWithInvalidNum_whenConvertInLoop_shouldGetExpectedIntArray() {
+ int[] result = new int[stringArrayWithInvalidNum.length];
+ for (int i = 0; i < stringArrayWithInvalidNum.length; i++) {
+ try {
+ result[i] = Integer.parseInt(stringArrayWithInvalidNum[i]);
+ } catch (NumberFormatException exception) {
+ logger.warn("Invalid number format detected: [{}], use Int.MinValue as the fallback", stringArrayWithInvalidNum[i]);
+ result[i] = Integer.MIN_VALUE;
+ }
+ }
+
+ assertArrayEquals(expectedWithInvalidInput, result);
+ }
+}
diff --git a/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/isobjectarray/CheckObjectIsArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/isobjectarray/CheckObjectIsArrayUnitTest.java
new file mode 100644
index 0000000000..ed38ab0765
--- /dev/null
+++ b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/isobjectarray/CheckObjectIsArrayUnitTest.java
@@ -0,0 +1,78 @@
+package com.baeldung.array.isobjectarray;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Array;
+
+import org.junit.jupiter.api.Test;
+
+public class CheckObjectIsArrayUnitTest {
+ private static final Object ARRAY_INT = new int[] { 1, 2, 3, 4, 5 };
+ private static final Object ARRAY_PERSON = new Person[] { new Person("Jackie Chan", "Hong Kong"), new Person("Tom Hanks", "United States") };
+
+ boolean isArray(Object obj) {
+ return obj instanceof Object[] || obj instanceof boolean[] || obj instanceof byte[] || obj instanceof short[] || obj instanceof char[] || obj instanceof int[] || obj instanceof long[] || obj instanceof float[] || obj instanceof double[];
+ }
+
+ @Test
+ void givenAnArrayObject_whenUsingInstanceof_getExpectedResult() {
+ assertTrue(ARRAY_PERSON instanceof Object[]);
+ assertFalse(ARRAY_INT instanceof Object[]);
+ assertTrue(ARRAY_INT instanceof int[]);
+ }
+
+ @Test
+ void givenAnArrayObject_whenUsingOurIsArray_getExpectedResult() {
+ assertTrue(isArray(ARRAY_PERSON));
+ assertTrue(isArray(ARRAY_INT));
+ }
+
+ @Test
+ void givenAnArrayObject_whenUsingClassIsArray_getExpectedResult() {
+ assertTrue(ARRAY_INT.getClass()
+ .isArray());
+ assertTrue(ARRAY_PERSON.getClass()
+ .isArray());
+
+ assertEquals(Person.class, ARRAY_PERSON.getClass()
+ .getComponentType());
+ assertEquals(int.class, ARRAY_INT.getClass()
+ .getComponentType());
+
+ }
+
+ @Test
+ void givenAnArrayObject_whenUsingArrayGet_getExpectedElement() {
+ if (ARRAY_PERSON.getClass()
+ .isArray() && ARRAY_PERSON.getClass()
+ .getComponentType() == Person.class) {
+ Person person = (Person) Array.get(ARRAY_PERSON, 1);
+ assertEquals("Tom Hanks", person.getName());
+ }
+ if (ARRAY_INT.getClass()
+ .isArray() && ARRAY_INT.getClass()
+ .getComponentType() == int.class) {
+ assertEquals(2, ((int) Array.get(ARRAY_INT, 1)));
+ }
+ }
+}
+
+class Person {
+ private String name;
+ private String Location;
+
+ public Person(String name, String location) {
+ this.name = name;
+ this.Location = location;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getLocation() {
+ return Location;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-2/README.md b/core-java-modules/core-java-collections-2/README.md
index d482ed7773..5a9bae8f9f 100644
--- a/core-java-modules/core-java-collections-2/README.md
+++ b/core-java-modules/core-java-collections-2/README.md
@@ -13,3 +13,4 @@
- [Getting the Size of an Iterable in Java](https://www.baeldung.com/java-iterable-size)
- [Java Null-Safe Streams from Collections](https://www.baeldung.com/java-null-safe-streams-from-collections)
- [Differences Between Iterator and Iterable and How to Use Them?](https://www.baeldung.com/java-iterator-vs-iterable)
+- More articles: [[<-- prev]](/core-java-modules/core-java-collections) [[next -->]](/core-java-modules/core-java-collections-3)
diff --git a/core-java-modules/core-java-collections-3/README.md b/core-java-modules/core-java-collections-3/README.md
index 4249d8ad30..4c0657da2d 100644
--- a/core-java-modules/core-java-collections-3/README.md
+++ b/core-java-modules/core-java-collections-3/README.md
@@ -6,7 +6,7 @@
- [Time Comparison of Arrays.sort(Object[]) and Arrays.sort(int[])](https://www.baeldung.com/arrays-sortobject-vs-sortint)
- [Java ArrayList vs Vector](https://www.baeldung.com/java-arraylist-vs-vector)
-- [Differences Between HashMap and Hashtable](https://www.baeldung.com/hashmap-hashtable-differences)
+- [Differences Between HashMap and Hashtable in Java](https://www.baeldung.com/hashmap-hashtable-differences)
- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall)
- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
- [Fail-Safe Iterator vs Fail-Fast Iterator](https://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator)
diff --git a/core-java-modules/core-java-collections-4/README.md b/core-java-modules/core-java-collections-4/README.md
index cdb457e342..460af21179 100644
--- a/core-java-modules/core-java-collections-4/README.md
+++ b/core-java-modules/core-java-collections-4/README.md
@@ -7,7 +7,11 @@
- [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap)
- [Java Deque vs. Stack](https://www.baeldung.com/java-deque-vs-stack)
- [Collection.toArray(new T[0]) or .toArray(new T[size])](https://www.baeldung.com/java-collection-toarray-methods)
-- [Create an Empty Map in Java](https://www.baeldung.com/java-create-empty-map)
- [Sorting Objects in a List by Date](https://www.baeldung.com/java-sort-list-by-date)
- [Fixed Size Queue Implementations in Java](https://www.baeldung.com/java-fixed-size-queue)
- [Difference Between Java Enumeration and Iterator](https://www.baeldung.com/java-enumeration-vs-iterator)
+- [Sort Collection of Objects by Multiple Fields in Java](https://www.baeldung.com/java-sort-collection-multiple-fields)
+- [Guide to Java PriorityQueue](https://www.baeldung.com/java-priorityqueue)
+- [Java Generics PECS – Producer Extends Consumer Super](https://www.baeldung.com/java-generics-pecs)
+- [Reversing a Stack in Java](https://www.baeldung.com/java-reversing-a-stack)
+- More articles: [[<-- prev]](/core-java-modules/core-java-collections-3)
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-4/pom.xml b/core-java-modules/core-java-collections-4/pom.xml
index 51e2d6e0ee..e88d5a6740 100644
--- a/core-java-modules/core-java-collections-4/pom.xml
+++ b/core-java-modules/core-java-collections-4/pom.xml
@@ -25,6 +25,12 @@
commons-lang3
${commons-lang3.version}
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit-platform.version}
+ test
+
@@ -32,4 +38,4 @@
3.12.0
-
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/ProducerExtendsConsumerSupers.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/ProducerExtendsConsumerSupers.java
new file mode 100644
index 0000000000..3c4b136b09
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/ProducerExtendsConsumerSupers.java
@@ -0,0 +1,59 @@
+package com.baeldung.collections.pecs;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.baeldung.collections.pecs.model.Customer;
+import com.baeldung.collections.pecs.model.Operator;
+import com.baeldung.collections.pecs.model.User;
+
+public class ProducerExtendsConsumerSupers {
+
+ public void producerExtends() {
+ List operators = Arrays.asList(new Operator("sam"), new Operator("daniel"));
+ List customers = Arrays.asList(new Customer("arys"), new Customer("cristiana"));
+
+ // sendEmails(operators); --> will not compile!
+ sendEmailsFixed(operators);
+ sendEmailsFixed(customers);
+ }
+
+ private void sendEmails(List users) {
+ for (User user : users) {
+ System.out.println("sending email to " + user);
+ }
+ }
+
+ private void sendEmailsFixed(List extends User> users) {
+ for (User user : users) {
+ System.out.println("sending email to " + user);
+ }
+ }
+
+ public void consumerSupers() {
+ List allOperators = Arrays.asList(new Operator("tom"));
+ List allUsers = Arrays.asList(new Operator("tom"), new Customer("spencer"));
+
+ // addUsersFromMarketingDepartment(allUsers); --> will not compile!
+ addUsersFromMarketingDepartmentFixed(allOperators);
+ addUsersFromMarketingDepartmentFixed(allUsers);
+ }
+
+ private void addUsersFromMarketingDepartment(List users) {
+ users.add(new Operator("john doe"));
+ users.add(new Operator("jane doe"));
+ }
+
+ private void addUsersFromMarketingDepartmentFixed(List super Operator> users) {
+ users.add(new Operator("john doe"));
+ users.add(new Operator("jane doe"));
+ }
+
+ private void addUsersAndSendEmails(List users) {
+ users.add(new Operator("john doe"));
+ for (User user : users) {
+ System.out.println("sending email to: " + user);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/Customer.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/Customer.java
new file mode 100644
index 0000000000..b3e97deddb
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/Customer.java
@@ -0,0 +1,7 @@
+package com.baeldung.collections.pecs.model;
+
+public class Customer extends User {
+ public Customer(String name) {
+ super(name);
+ }
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/Operator.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/Operator.java
new file mode 100644
index 0000000000..e998088496
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/Operator.java
@@ -0,0 +1,7 @@
+package com.baeldung.collections.pecs.model;
+
+public class Operator extends User {
+ public Operator(String name) {
+ super(name);
+ }
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/User.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/User.java
new file mode 100644
index 0000000000..a0d9d6a9b7
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/pecs/model/User.java
@@ -0,0 +1,9 @@
+package com.baeldung.collections.pecs.model;
+
+public class User {
+ private final String name;
+
+ public User(String name) {
+ this.name = name;
+ }
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/priorityqueue/ColoredNumber.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/priorityqueue/ColoredNumber.java
new file mode 100644
index 0000000000..554a13d642
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/priorityqueue/ColoredNumber.java
@@ -0,0 +1,27 @@
+package com.baeldung.collections.priorityqueue;
+
+public final class ColoredNumber {
+ private int value;
+ private String color;
+
+ public ColoredNumber(int value, String color) {
+ this.value = value;
+ this.color = color;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/priorityqueue/ColoredNumberComparable.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/priorityqueue/ColoredNumberComparable.java
new file mode 100644
index 0000000000..0e9a5ec498
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/priorityqueue/ColoredNumberComparable.java
@@ -0,0 +1,44 @@
+package com.baeldung.collections.priorityqueue;
+
+public final class ColoredNumberComparable implements Comparable {
+ private int value;
+ private String color;
+
+ public ColoredNumberComparable(int value, String color) {
+ this.value = value;
+ this.color = color;
+ }
+
+ @Override
+ public int compareTo(ColoredNumberComparable o) {
+ // (both numbers are red) or (both numbers are not red)
+ if ((this.color.equals("red") && o.color.equals("red")) ||
+ (!this.color.equals("red") && !o.color.equals("red"))) {
+ return Integer.compare(this.value, o.value);
+ }
+ // only the first number is red
+ else if (this.color.equals("red")) {
+ return -1;
+ }
+ // only the second number is red
+ else {
+ return 1;
+ }
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/stackreversal/ReverseStackUsingQueue.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/stackreversal/ReverseStackUsingQueue.java
new file mode 100644
index 0000000000..6851ed7e88
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/stackreversal/ReverseStackUsingQueue.java
@@ -0,0 +1,42 @@
+package com.baeldung.collections.stackreversal;
+
+import com.baeldung.collections.sorting.Employee;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Stack;
+
+public class ReverseStackUsingQueue {
+ public Stack reverseIntegerStack(Stack inputStack) {
+ Queue queue = new LinkedList<>();
+ while (!inputStack.isEmpty()) {
+ queue.add(inputStack.pop());
+ }
+ while (!queue.isEmpty()) {
+ inputStack.add(queue.remove());
+ }
+ return inputStack;
+ }
+
+ public Stack reverseStringStack(Stack inputStack) {
+ Queue queue = new LinkedList<>();
+ while (!inputStack.isEmpty()) {
+ queue.add(inputStack.pop());
+ }
+ while (!queue.isEmpty()) {
+ inputStack.add(queue.remove());
+ }
+ return inputStack;
+ }
+
+ public Stack reverseEmployeeStack(Stack inputStack) {
+ Queue employeeQ = new LinkedList<>();
+ while (!inputStack.isEmpty()) {
+ employeeQ.add(inputStack.pop());
+ }
+ while (!employeeQ.isEmpty()) {
+ inputStack.add(employeeQ.remove());
+ }
+ return inputStack;
+ }
+}
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/stackreversal/ReverseStackUsingRecursion.java b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/stackreversal/ReverseStackUsingRecursion.java
new file mode 100644
index 0000000000..8dbe0c39a6
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/collections/stackreversal/ReverseStackUsingRecursion.java
@@ -0,0 +1,29 @@
+package com.baeldung.collections.stackreversal;
+
+import java.util.Stack;
+
+public class ReverseStackUsingRecursion {
+ public Stack reverseIntegerStack(Stack inputStack) {
+ reverseStack(inputStack);
+ return inputStack;
+ }
+
+ private void reverseStack(Stack stack) {
+ if (stack.isEmpty()) {
+ return;
+ }
+ int top = stack.pop();
+ reverseStack(stack);
+ insertBottom(stack, top);
+ }
+
+ private void insertBottom(Stack stack, int value) {
+ if (stack.isEmpty()) {
+ stack.add(value);
+ } else {
+ int top = stack.pop();
+ insertBottom(stack, value);
+ stack.add(top);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java
index 3b595472e0..7d4ec8249c 100644
--- a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java
@@ -2,9 +2,7 @@ package com.baeldung.collections.comparation;
import org.junit.jupiter.api.Test;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java
index aa6b7fa923..00a188737d 100644
--- a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java
@@ -2,10 +2,8 @@ package com.baeldung.collections.comparation;
import org.junit.jupiter.api.Test;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
-import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/priorityqueue/PriorityQueueComparatorUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/priorityqueue/PriorityQueueComparatorUnitTest.java
new file mode 100644
index 0000000000..db10fa1ae8
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/priorityqueue/PriorityQueueComparatorUnitTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.collections.priorityqueue;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.PriorityQueue;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class PriorityQueueComparatorUnitTest {
+
+ @Test
+ void givenIntegerQueue_defaultComparator_followsNaturalOrdering() {
+ PriorityQueue integerQueue = new PriorityQueue<>();
+ PriorityQueue integerQueueWithComparator = new PriorityQueue<>((Integer c1, Integer c2) -> Integer.compare(c1, c2));
+
+ integerQueueWithComparator.add(3);
+ integerQueue.add(3);
+
+ integerQueueWithComparator.add(2);
+ integerQueue.add(2);
+
+ integerQueueWithComparator.add(1);
+ integerQueue.add(1);
+
+ assertThat(integerQueue.poll()).isEqualTo(1).isEqualTo(integerQueueWithComparator.poll());
+ assertThat(integerQueue.poll()).isEqualTo(2).isEqualTo(integerQueueWithComparator.poll());
+ assertThat(integerQueue.poll()).isEqualTo(3).isEqualTo(integerQueueWithComparator.poll());
+ }
+
+ @Test
+ void givenIntegerQueue_reverseOrderComparator_followsInverseNaturalOrdering() {
+ PriorityQueue reversedQueue = new PriorityQueue<>(Collections.reverseOrder());
+
+ reversedQueue.add(1);
+ reversedQueue.add(2);
+ reversedQueue.add(3);
+
+ assertThat(reversedQueue.poll()).isEqualTo(3);
+ assertThat(reversedQueue.poll()).isEqualTo(2);
+ assertThat(reversedQueue.poll()).isEqualTo(1);
+ }
+
+ @Test
+ void givenNotComparableQueue_classCastException() {
+ assertThatThrownBy(() -> {
+ PriorityQueue queue = new PriorityQueue<>();
+ queue.add(new ColoredNumber(3, "red"));
+ queue.add(new ColoredNumber(2, "blue"));
+ }).isInstanceOf(ClassCastException.class);
+ }
+
+ @Test
+ void givenCustomOrderingQueue_orderIsCorrect() {
+ PriorityQueue queue = new PriorityQueue<>();
+ queue.add(new ColoredNumberComparable(10, "red"));
+ queue.add(new ColoredNumberComparable(20, "red"));
+ queue.add(new ColoredNumberComparable(1, "blue"));
+ queue.add(new ColoredNumberComparable(2, "blue"));
+
+ ColoredNumberComparable first = queue.poll();
+ assertThat(first.getColor()).isEqualTo("red");
+ assertThat(first.getValue()).isEqualTo(10);
+
+ queue.poll();
+
+ ColoredNumberComparable third = queue.poll();
+ assertThat(third.getColor()).isEqualTo("blue");
+ assertThat(third.getValue()).isEqualTo(1);
+ }
+
+}
+
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/EmployeeSortingByDateUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/EmployeeSortingByDateUnitTest.java
index 250fb7b62b..de2f3d8ca7 100644
--- a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/EmployeeSortingByDateUnitTest.java
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/EmployeeSortingByDateUnitTest.java
@@ -10,7 +10,7 @@ import java.util.Date;
import java.util.List;
import org.apache.commons.lang.time.DateUtils;
import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
public class EmployeeSortingByDateUnitTest {
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/multiple/ComparatorsUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/multiple/ComparatorsUnitTest.java
index 4608730567..e1297456be 100644
--- a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/multiple/ComparatorsUnitTest.java
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/sorting/multiple/ComparatorsUnitTest.java
@@ -5,8 +5,9 @@ import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
-import org.junit.Test;
+
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
public class ComparatorsUnitTest {
@Test
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/stackreversal/StackReversalUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/stackreversal/StackReversalUnitTest.java
new file mode 100644
index 0000000000..ccadc4e7d3
--- /dev/null
+++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/stackreversal/StackReversalUnitTest.java
@@ -0,0 +1,66 @@
+package com.baeldung.stackreversal;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.baeldung.collections.sorting.Employee;
+import com.baeldung.collections.stackreversal.ReverseStackUsingQueue;
+import com.baeldung.collections.stackreversal.ReverseStackUsingRecursion;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class StackReversalUnitTest {
+ @Test
+ public void whenIntegerStack_thenReturnReversedIntegerStack(){
+ ReverseStackUsingQueue reverseStack = new ReverseStackUsingQueue();
+ Stack originalStack = generateStackFromGivenList(Arrays.stream(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).boxed().collect(Collectors.toList()), new Stack());
+ Stack reverseList = generateStackFromGivenList(Arrays.stream(new int[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}).boxed().collect(Collectors.toList()), new Stack());
+ assertEquals(reverseStack.reverseIntegerStack(originalStack), reverseList);
+ }
+
+ @Test
+ public void whenStringStack_thenReturnReversedStringStack(){
+ ReverseStackUsingQueue stackReversal = new ReverseStackUsingQueue();
+ List listOfWords = Arrays.asList(new String[]{"Hello", "I", "am", "reversing", "a", "stack"});
+ List listOfWordsReversed = new ArrayList<>(listOfWords);
+ Collections.reverse(listOfWordsReversed);
+ Stack originalStack = generateStackFromGivenList(listOfWords, new Stack());
+ Stack reversedStack = generateStackFromGivenList(listOfWordsReversed, new Stack());
+ assertEquals(stackReversal.reverseStringStack(originalStack), reversedStack);
+ }
+
+ @Test
+ public void whenEmployeeStack_thenReturnReversedEmployeeStack(){
+ ReverseStackUsingQueue stackReversal = new ReverseStackUsingQueue();
+ Employee employee1 = new Employee("John Doe", new Date());
+ Employee employee2 = new Employee("John Nash", new Date());
+ Employee employee3 = new Employee("Ryan Howard", new Date());
+ List employeeList = new ArrayList<>();
+ employeeList.add(employee1);
+ employeeList.add(employee2);
+ employeeList.add(employee3);
+ List employeeReversed = new ArrayList<>(employeeList);
+ Collections.reverse(employeeReversed);
+ Stack originalStack = generateStackFromGivenList(employeeList, new Stack());
+ Stack reverseStack = generateStackFromGivenList(employeeReversed, new Stack());
+ assertEquals(stackReversal.reverseEmployeeStack(originalStack), reverseStack);
+ }
+
+ @Test
+ public void givenIntegerStack_whenStackReversed_thenReturnReversedRecursion(){
+ ReverseStackUsingRecursion reverseStack = new ReverseStackUsingRecursion();
+ Stack originalStack = generateStackFromGivenList(Arrays.stream(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).boxed().collect(Collectors.toList()), new Stack());
+ Stack reversedStack = generateStackFromGivenList(Arrays.stream(new int[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}).boxed().collect(Collectors.toList()), new Stack());
+ assertEquals(reverseStack.reverseIntegerStack(originalStack), reversedStack);
+ }
+
+ private Stack generateStackFromGivenList(List elements, Stack stack){
+ int start = 0;
+ while (start < elements.size()){
+ stack.add(elements.get(start++));
+ }
+ return stack;
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/README.md b/core-java-modules/core-java-collections-5/README.md
new file mode 100644
index 0000000000..0d9b12b842
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/README.md
@@ -0,0 +1,7 @@
+=========
+
+## Core Java Collections Cookbooks and Examples
+
+### Relevant Articles:
+- [Introduction to Roaring Bitmap](https://www.baeldung.com/java-roaring-bitmap-intro)
+- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
diff --git a/core-java-modules/core-java-collections-5/pom.xml b/core-java-modules/core-java-collections-5/pom.xml
new file mode 100644
index 0000000000..67c9f7120c
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+ core-java-collections-5
+ 0.0.1-SNAPSHOT
+ core-java-collections-5
+ jar
+
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit-platform.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.version}
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+ ${junit.version}
+ test
+
+
+ org.roaringbitmap
+ RoaringBitmap
+ ${roaringbitmap.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh.version}
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh.version}
+
+
+
+
+ 5.9.2
+ 0.9.38
+ 1.36
+
+
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/roaringbitmap/BitSetsBenchmark.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/roaringbitmap/BitSetsBenchmark.java
new file mode 100644
index 0000000000..4968afb752
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/roaringbitmap/BitSetsBenchmark.java
@@ -0,0 +1,82 @@
+package com.baeldung.roaringbitmap;
+
+import java.util.BitSet;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.roaringbitmap.RoaringBitmap;
+
+@State(Scope.Thread)
+public class BitSetsBenchmark {
+ private RoaringBitmap rb1;
+ private BitSet bs1;
+ private RoaringBitmap rb2;
+ private BitSet bs2;
+ private final static int SIZE = 10_000_000;
+
+ @Setup
+ public void setup() {
+ rb1 = new RoaringBitmap();
+ bs1 = new BitSet(SIZE);
+ rb2 = new RoaringBitmap();
+ bs2 = new BitSet(SIZE);
+ for (int i = 0; i < SIZE / 2; i++) {
+ rb1.add(i);
+ bs1.set(i);
+ }
+ for (int i = SIZE / 2; i < SIZE; i++) {
+ rb2.add(i);
+ bs2.set(i);
+ }
+ }
+
+ @Benchmark
+ public RoaringBitmap roaringBitmapUnion() {
+ return RoaringBitmap.or(rb1, rb2);
+ }
+
+ @Benchmark
+ public BitSet bitSetUnion() {
+ BitSet result = (BitSet) bs1.clone();
+ result.or(bs2);
+ return result;
+ }
+
+ @Benchmark
+ public RoaringBitmap roaringBitmapIntersection() {
+ return RoaringBitmap.and(rb1, rb2);
+ }
+
+ @Benchmark
+ public BitSet bitSetIntersection() {
+ BitSet result = (BitSet) bs1.clone();
+ result.and(bs2);
+ return result;
+ }
+
+ @Benchmark
+ public RoaringBitmap roaringBitmapDifference() {
+ return RoaringBitmap.andNot(rb1, rb2);
+ }
+
+ @Benchmark
+ public BitSet bitSetDifference() {
+ BitSet result = (BitSet) bs1.clone();
+ result.andNot(bs2);
+ return result;
+ }
+
+ @Benchmark
+ public RoaringBitmap roaringBitmapXOR() {
+ return RoaringBitmap.xor(rb1, rb2);
+ }
+
+ @Benchmark
+ public BitSet bitSetXOR() {
+ BitSet result = (BitSet) bs1.clone();
+ result.xor(bs2);
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/roaringbitmap/BitSetsBenchmarkRunner.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/roaringbitmap/BitSetsBenchmarkRunner.java
new file mode 100644
index 0000000000..49d556df7e
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/roaringbitmap/BitSetsBenchmarkRunner.java
@@ -0,0 +1,9 @@
+package com.baeldung.roaringbitmap;
+
+import java.io.IOException;
+
+public class BitSetsBenchmarkRunner {
+ public static void main(String... args) throws IOException {
+ org.openjdk.jmh.Main.main(args);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/roaringbitmap/RoaringBitmapBenchmarkUnitTest.java b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/roaringbitmap/RoaringBitmapBenchmarkUnitTest.java
new file mode 100644
index 0000000000..07170512d9
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/roaringbitmap/RoaringBitmapBenchmarkUnitTest.java
@@ -0,0 +1,45 @@
+package com.baeldung.roaringbitmap;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.roaringbitmap.RoaringBitmap;
+
+class RoaringBitmapBenchmarkUnitTest {
+ @Test
+ public void givenTwoRoaringBitmap_whenUsingOr_thenWillGetSetsUnion() {
+ RoaringBitmap expected = RoaringBitmap.bitmapOf(1, 2, 3, 4, 5, 6, 7, 8);
+ RoaringBitmap A = RoaringBitmap.bitmapOf(1, 2, 3, 4, 5);
+ RoaringBitmap B = RoaringBitmap.bitmapOf(4, 5, 6, 7, 8);
+ RoaringBitmap union = RoaringBitmap.or(A, B);
+ assertEquals(expected, union);
+ }
+
+ @Test
+ public void givenTwoRoaringBitmap_whenUsingAnd_thenWillGetSetsIntersection() {
+ RoaringBitmap expected = RoaringBitmap.bitmapOf(4, 5);
+ RoaringBitmap A = RoaringBitmap.bitmapOfRange(1, 6);
+ RoaringBitmap B = RoaringBitmap.bitmapOf(4, 5, 6, 7, 8);
+ RoaringBitmap intersection = RoaringBitmap.and(A, B);
+ assertEquals(expected, intersection);
+ }
+
+ @Test
+ public void givenTwoRoaringBitmap_whenUsingAndNot_thenWillGetSetsDifference() {
+ RoaringBitmap expected = RoaringBitmap.bitmapOf(1, 2, 3);
+ RoaringBitmap A = new RoaringBitmap();
+ A.add(1L, 6L);
+ RoaringBitmap B = RoaringBitmap.bitmapOf(4, 5, 6, 7, 8);
+ RoaringBitmap difference = RoaringBitmap.andNot(A, B);
+ assertEquals(expected, difference);
+ }
+
+ @Test
+ public void givenTwoRoaringBitmap_whenUsingXOR_thenWillGetSetsSymmetricDifference() {
+ RoaringBitmap expected = RoaringBitmap.bitmapOf(1, 2, 3, 6, 7, 8);
+ RoaringBitmap A = RoaringBitmap.bitmapOfRange(1, 6);
+ RoaringBitmap B = RoaringBitmap.bitmapOfRange(4, 9);
+ RoaringBitmap xor = RoaringBitmap.xor(A, B);
+ assertEquals(expected, xor);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-array-list/README.md b/core-java-modules/core-java-collections-array-list/README.md
index d24f7492bb..e3d41d8f88 100644
--- a/core-java-modules/core-java-collections-array-list/README.md
+++ b/core-java-modules/core-java-collections-array-list/README.md
@@ -9,3 +9,7 @@ This module contains articles about the Java ArrayList collection
- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist)
- [Removing an Element From an ArrayList](https://www.baeldung.com/java-arraylist-remove-element)
- [The Capacity of an ArrayList vs the Size of an Array in Java](https://www.baeldung.com/java-list-capacity-array-size)
+- [Case-Insensitive Searching in ArrayList](https://www.baeldung.com/java-arraylist-case-insensitive-search)
+- [Storing Data Triple in a List in Java](https://www.baeldung.com/java-list-storing-triple)
+- [Convert an ArrayList of Object to an ArrayList of String Elements](https://www.baeldung.com/java-object-list-to-strings)
+- [Initialize an ArrayList with Zeroes or Null in Java](https://www.baeldung.com/java-arraylist-with-zeroes-or-null)
diff --git a/core-java-modules/core-java-collections-array-list/pom.xml b/core-java-modules/core-java-collections-array-list/pom.xml
index 6b040739e8..e3a115854c 100644
--- a/core-java-modules/core-java-collections-array-list/pom.xml
+++ b/core-java-modules/core-java-collections-array-list/pom.xml
@@ -5,6 +5,33 @@
4.0.0
core-java-collections-array-list
0.1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${maven-compiler-plugin.source}
+ ${maven-compiler-plugin.target}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${surefire.plugin.version}
+
+
+ --add-opens java.base/java.util=ALL-UNNAMED
+
+
+
+
+
+
+ 16
+ 16
+ 3.0.0-M3
+
core-java-collections-array-list
jar
@@ -20,6 +47,12 @@
commons-collections4
${commons-collections4.version}
+
+ com.google.guava
+ guava
+ 31.1-jre
+ test
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/defaultarraylistcapacity/DefaultArrayListCapacity.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/defaultarraylistcapacity/DefaultArrayListCapacity.java
new file mode 100644
index 0000000000..34f202a4dd
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/defaultarraylistcapacity/DefaultArrayListCapacity.java
@@ -0,0 +1,20 @@
+package com.baeldung.defaultarraylistcapacity;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+
+public class DefaultArrayListCapacity {
+
+ public static int getDefaultCapacity(ArrayList> arrayList) throws Exception {
+
+ if (arrayList == null) {
+ return 0;
+ }
+
+ Field field = ArrayList.class.getDeclaredField("elementData");
+ field.setAccessible(true);
+
+ return ((Object[]) field.get(arrayList)).length;
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/initializearraylistwithnullorzeros/InitializeArrayListWithNullOrZeros.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/initializearraylistwithnullorzeros/InitializeArrayListWithNullOrZeros.java
new file mode 100644
index 0000000000..66862791aa
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/initializearraylistwithnullorzeros/InitializeArrayListWithNullOrZeros.java
@@ -0,0 +1,15 @@
+package com.baeldung.initializearraylistwithnullorzeros;
+
+import java.util.ArrayList;
+
+public class InitializeArrayListWithNullOrZeros {
+
+ public static void main(String[] args) {
+
+ ArrayList arrayList = new ArrayList<>();
+ for (int i = 0; i< 10; i++) {
+ arrayList.add(null);
+ }
+ }
+}
+
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/ignorecase/IgnoreCaseSearchUtil.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/ignorecase/IgnoreCaseSearchUtil.java
new file mode 100644
index 0000000000..38532ef031
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/ignorecase/IgnoreCaseSearchUtil.java
@@ -0,0 +1,14 @@
+package com.baeldung.list.ignorecase;
+
+import java.util.List;
+
+public class IgnoreCaseSearchUtil {
+ public static boolean ignoreCaseContains(List theList, String searchStr) {
+ for (String s : theList) {
+ if (searchStr.equalsIgnoreCase(s)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/ignorecase/IgnoreCaseStringList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/ignorecase/IgnoreCaseStringList.java
new file mode 100644
index 0000000000..a27c2650ed
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/ignorecase/IgnoreCaseStringList.java
@@ -0,0 +1,29 @@
+package com.baeldung.list.ignorecase;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class IgnoreCaseStringList extends ArrayList {
+
+ public IgnoreCaseStringList() {
+
+ }
+
+ public IgnoreCaseStringList(Collection extends String> c) {
+ super(c);
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ String searchStr = (String) o;
+ // Using Stream API:
+ // return this.stream().anyMatch(searchStr::equalsIgnoreCase);
+ for (String s : this) {
+ if (searchStr.equalsIgnoreCase(s)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/listofobjectstolistofstring/Node.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/listofobjectstolistofstring/Node.java
new file mode 100644
index 0000000000..3e2c5693de
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/listofobjectstolistofstring/Node.java
@@ -0,0 +1,17 @@
+package com.baeldung.listofobjectstolistofstring;
+
+public class Node {
+
+ private final int x;
+ private final int y;
+
+ public Node(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public String toString() {
+ return "Node (" + "x=" + x + ", y=" + y + ')';
+ }
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/listofobjectstolistofstring/User.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/listofobjectstolistofstring/User.java
new file mode 100644
index 0000000000..eb9298bce0
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/listofobjectstolistofstring/User.java
@@ -0,0 +1,14 @@
+package com.baeldung.listofobjectstolistofstring;
+
+public class User {
+ private final String fullName;
+
+ public User(String fullName) {
+ this.fullName = fullName;
+ }
+
+ @Override
+ public String toString() {
+ return "User (" + "full name='" + fullName + ')';
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/triple/Triple.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/triple/Triple.java
new file mode 100644
index 0000000000..b19266ad21
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/triple/Triple.java
@@ -0,0 +1,26 @@
+package com.baeldung.triple;
+
+public class Triple {
+
+ private final L left;
+ private final M middle;
+ private final R right;
+
+ public Triple(L left, M middle, R right) {
+ this.left = left;
+ this.middle = middle;
+ this.right = right;
+ }
+
+ public L getLeft() {
+ return left;
+ }
+
+ public M getMiddle() {
+ return middle;
+ }
+
+ public R getRight() {
+ return right;
+ }
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/defaultarraylistcapacity/DefaultArrayListCapacityUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/defaultarraylistcapacity/DefaultArrayListCapacityUnitTest.java
new file mode 100644
index 0000000000..0690e93879
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/defaultarraylistcapacity/DefaultArrayListCapacityUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.defaultarraylistcapacity;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.Test;
+
+public class DefaultArrayListCapacityUnitTest {
+
+ @Test
+ void givenEmptyArrayList_whenGetDefaultCapacity_thenReturnZero() throws Exception {
+
+ ArrayList myList = new ArrayList<>();
+ int defaultCapacity = DefaultArrayListCapacity.getDefaultCapacity(myList);
+
+ assertEquals(0, defaultCapacity);
+
+ }
+
+ @Test
+ void givenEmptyArrayList_whenAddItemAndGetDefaultCapacity_thenReturn10() throws Exception {
+
+ ArrayList myList = new ArrayList<>();
+ myList.add("ITEM 1");
+
+ int defaultCapacity = DefaultArrayListCapacity.getDefaultCapacity(myList);
+
+ assertEquals(10, defaultCapacity);
+
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/initializearraylistwithnullorzeros/InitializeArrayListWithNullOrZerosUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/initializearraylistwithnullorzeros/InitializeArrayListWithNullOrZerosUnitTest.java
new file mode 100644
index 0000000000..00987fa198
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/initializearraylistwithnullorzeros/InitializeArrayListWithNullOrZerosUnitTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.initializearraylistwithnullorzeros;
+
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class InitializeArrayListWithNullOrZerosUnitTest {
+
+ @Test
+ public void whenInitializingListWithNCopies_thenListIsCorrectlyPopulated() {
+ // when
+ ArrayList list = IntStream.of(new int[10])
+ .boxed()
+ .collect(Collectors.toCollection(ArrayList::new));
+
+ // then
+ Assertions.assertEquals(10, list.size());
+ Assertions.assertTrue(list.stream().allMatch(elem -> elem == 0));
+ }
+
+ @Test
+ public void whenInitializingListWithStream_thenListIsCorrectlyPopulated() {
+
+ // when
+ ArrayList listWithZeros = Stream.generate(() -> 0)
+ .limit(10).collect(Collectors.toCollection(ArrayList::new));
+
+ ArrayList listWithNulls = Stream.generate(() -> null)
+ .limit(10).collect(Collectors.toCollection(ArrayList::new));
+
+ // then
+ Assertions.assertEquals(10, listWithZeros.size());
+ Assertions.assertTrue(listWithZeros.stream().allMatch(elem -> elem == 0));
+
+ Assertions.assertEquals(10, listWithNulls.size());
+ Assertions.assertTrue(listWithNulls.stream().allMatch(Objects::isNull));
+ }
+
+ @Test public void whenInitializingListWithIntStream_thenListIsCorrectlyPopulated() {
+ // when
+ ArrayList list = IntStream.of(new int[10])
+ .boxed()
+ .collect(Collectors.toCollection(ArrayList::new));
+
+ // then
+ Assertions.assertEquals(10, list.size());
+ Assertions.assertTrue(list.stream().allMatch(elem -> elem == 0)); }
+
+ @Test
+ public void whenInitializingListWithAsList_thenListIsCorrectlyPopulated() {
+ // when
+ Integer[] integers = new Integer[10];
+ Arrays.fill(integers, 0);
+ List integerList = new ArrayList<>(Arrays.asList(integers));
+
+ // then
+ Assertions.assertEquals(10, integerList.size());
+ Assertions.assertTrue(integerList.stream().allMatch(elem -> elem == 0));
+ }
+
+ @Test
+ public void whenInitializingListWithVector_thenListIsCorrectlyPopulated() {
+ // when
+ List integerList = new Vector<>() {{setSize(10);}};
+
+ // then
+ Assertions.assertEquals(10, integerList.size());
+ Assertions.assertTrue(integerList.stream().allMatch(Objects::isNull));
+ }
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/list/ignorecase/IgnoreCaseContainsUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/list/ignorecase/IgnoreCaseContainsUnitTest.java
new file mode 100644
index 0000000000..5ca9bb1028
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/list/ignorecase/IgnoreCaseContainsUnitTest.java
@@ -0,0 +1,45 @@
+package com.baeldung.list.ignorecase;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class IgnoreCaseContainsUnitTest {
+ private static final List LANGUAGES = Arrays.asList("Java", "Python", "Kotlin", "Ruby", "Javascript", "Go");
+
+ @Test
+ void givenStringList_whenCallTheStandardContains_shouldReturnFalse() {
+ String searchStr = "jAvA";
+ boolean result = LANGUAGES.contains(searchStr);
+ assertFalse(result);
+ }
+
+ @Test
+ void givenStringList_whenSearchIgnoreCaseUsingStreamAPI_shouldReturnTrue() {
+ String searchStr = "koTliN";
+ boolean result = LANGUAGES.stream().anyMatch(searchStr::equalsIgnoreCase);
+ assertTrue(result);
+ }
+
+ @Test
+ void givenStringList_whenUsingUtilClass_shouldReturnTrue() {
+ String searchStr = "ruBY";
+ boolean result = IgnoreCaseSearchUtil.ignoreCaseContains(LANGUAGES, searchStr);
+ assertTrue(result);
+ }
+
+ @Test
+ void givenStringList_whenUsingIgnoreCaseStringList_shouldReturnTrue() {
+ String searchStr = "pYtHoN";
+ List ignoreCaseList = new IgnoreCaseStringList(LANGUAGES);
+ boolean result = ignoreCaseList.contains(searchStr);
+ assertTrue(result);
+
+ boolean resultContainAll = ignoreCaseList.containsAll(Arrays.asList("pYtHon", "jAvA", "koTliN", "ruBY"));
+ assertTrue(resultContainAll);
+ }
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listofobjectstolistofstring/ConvertObjectListToStringListUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listofobjectstolistofstring/ConvertObjectListToStringListUnitTest.java
new file mode 100644
index 0000000000..1d393a2945
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listofobjectstolistofstring/ConvertObjectListToStringListUnitTest.java
@@ -0,0 +1,92 @@
+package com.baeldung.listofobjectstolistofstring;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class ConvertObjectListToStringListUnitTest {
+
+ @Test
+ public void givenObjectList_whenForEachUsedToConvert_thenReturnSuccess() {
+ List outputList = new ArrayList<>(objectListWithNull().size());
+ for (Object obj : objectListWithNull()) {
+ outputList.add(Objects.toString(obj, null));
+ }
+ Assert.assertEquals(expectedStringListWithNull(), outputList);
+ }
+
+ @Test
+ public void givenObjectList_whenUsingStreamsToConvert_thenReturnSuccess() {
+ List outputList;
+ outputList = objectListWithNull().stream()
+ .map((obj) -> Objects.toString(obj, null))
+ .collect(Collectors.toList());
+ Assert.assertEquals(expectedStringListWithNull(), outputList);
+
+ }
+
+ @Test
+ public void givenObjectList_whenUsingStreamsUnmodifiableListToConvert_thenReturnSuccess() {
+ List outputList;
+ outputList = objectListWithNull().stream()
+ .filter(Objects::nonNull)
+ .map((obj) -> Objects.toString(obj, null))
+ .collect(Collectors.toUnmodifiableList());
+ Assert.assertEquals(expectedStringListWithoutNull(), outputList);
+
+ }
+
+ @Test
+ public void givenObjectList_whenUsingGuavaTransform_thenReturnSuccess() {
+ List outputList;
+ outputList = Lists.transform(objectListWithNull(), obj -> Objects.toString(obj, null));
+ Assert.assertEquals(expectedStringListWithNull(), outputList);
+ }
+
+ @Test
+ public void givenObjectListWithNoNull_whenUsingToList_thenReturnSuccess() {
+ List outputList;
+ outputList = objectListWithoutNull().stream()
+ .map((obj) -> Objects.toString(obj, null))
+ .toList();
+ Assert.assertEquals(expectedStringListWithoutNull(), outputList);
+ }
+
+ private List expectedStringListWithNull() {
+ List listOfStrings = new ArrayList<>();
+ listOfStrings.add("1");
+ listOfStrings.add("true");
+ listOfStrings.add("hello");
+ listOfStrings.add(Double.toString(273773.98));
+ listOfStrings.add(null);
+ listOfStrings.add(new Node(2, 4).toString());
+ listOfStrings.add(new User("John Doe").toString());
+ return listOfStrings;
+ }
+
+ private List objectListWithNull() {
+ List listOfStrings = new ArrayList<>();
+ listOfStrings.add(1);
+ listOfStrings.add(true);
+ listOfStrings.add("hello");
+ listOfStrings.add(Double.valueOf(273773.98));
+ listOfStrings.add(null);
+ listOfStrings.add(new Node(2, 4));
+ listOfStrings.add(new User("John Doe"));
+ return listOfStrings;
+ }
+
+ private List expectedStringListWithoutNull() {
+ return List.of("1", "true", "hello", Double.toString(273773.98), new Node(2, 4).toString(), new User("John Doe").toString());
+ }
+
+ private List objectListWithoutNull() {
+ return List.of(1, true, "hello", Double.valueOf(273773.98), new Node(2, 4), new User("John Doe"));
+ }
+}
diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/triple/TripleInListUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/triple/TripleInListUnitTest.java
new file mode 100644
index 0000000000..2196ae687f
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/triple/TripleInListUnitTest.java
@@ -0,0 +1,105 @@
+package com.baeldung.triple;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.Test;
+
+public class TripleInListUnitTest {
+
+ enum OP {
+ PLUS("+"), MINUS("-"), MULTIPLY("x");
+ final String opSign;
+
+ OP(String x) {
+ this.opSign = x;
+ }
+ }
+
+ private String createQuestion(Long num1, OP operator, Long num2) {
+ long result;
+ switch (operator) {
+ case PLUS:
+ result = num1 + num2;
+ break;
+ case MINUS:
+ result = num1 - num2;
+ break;
+ case MULTIPLY:
+ result = num1 * num2;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown operator");
+ }
+ return String.format("%d %s %d = ? ( answer: %d )", num1, operator.opSign, num2, result);
+ }
+
+ private static final List EXPECTED_QUESTIONS = Arrays.asList(
+ "100 - 42 = ? ( answer: 58 )",
+ "100 + 42 = ? ( answer: 142 )",
+ "100 x 42 = ? ( answer: 4200 )");
+
+ @Test
+ void givenTripleValues_whenStoreAsList_thenTypeIsNotSafe() {
+
+ List myTriple1 = new ArrayList(3);
+ myTriple1.add(100L);
+ myTriple1.add(OP.MINUS);
+ myTriple1.add(42L);
+
+ List myTriple2 = new ArrayList(3);
+ myTriple2.add(100L);
+ myTriple2.add(OP.PLUS);
+ myTriple2.add(42L);
+
+ List myTriple3 = new ArrayList(3);
+ myTriple3.add(100L);
+ myTriple3.add(OP.MULTIPLY);
+ myTriple3.add(42L);
+
+ List listOfTriples = new ArrayList<>(Arrays.asList(myTriple1, myTriple2, myTriple3));
+
+ List oopsTriple = new ArrayList(3);
+ oopsTriple.add("Oops");
+ oopsTriple.add(911L);
+ oopsTriple.add("The type is wrong");
+
+ listOfTriples.add(oopsTriple);
+ assertEquals(4, listOfTriples.size());
+
+ List questions = listOfTriples.stream()
+ .filter(
+ triple -> triple.size() == 3
+ && triple.get(0) instanceof Long
+ && triple.get(1) instanceof OP
+ && triple.get(2) instanceof Long
+ ).map(triple -> {
+ Long left = (Long) triple.get(0);
+ OP op = (OP) triple.get(1);
+ Long right = (Long) triple.get(2);
+ return createQuestion(left, op, right);
+ }).collect(Collectors.toList());
+
+ assertEquals(EXPECTED_QUESTIONS, questions);
+ }
+
+ @Test
+ void givenTripleValues_whenUsingTheTripleClass_thenTypeIsSafeAndNeat() {
+ Triple triple1 = new Triple<>(100L, OP.MINUS, 42L);
+ Triple triple2 = new Triple<>(100L, OP.PLUS, 42L);
+ Triple triple3 = new Triple<>(100L, OP.MULTIPLY, 42L);
+ Triple tripleOops = new Triple<>("Oops", 911L, "The type is wrong");
+
+ List> listOfTriples = new ArrayList<>(Arrays.asList(triple1, triple2, triple3));
+ // listOfTriples.add(tripleOops); // Compiler error: "java: incompatible types ... "
+
+ List questions = listOfTriples.stream()
+ .map(triple -> createQuestion(triple.getLeft(), triple.getMiddle(), triple.getRight()))
+ .collect(Collectors.toList());
+
+ assertEquals(EXPECTED_QUESTIONS, questions);
+ }
+}
diff --git a/core-java-modules/core-java-collections-conversions-2/README.md b/core-java-modules/core-java-collections-conversions-2/README.md
index 075f2b8736..904e876032 100644
--- a/core-java-modules/core-java-collections-conversions-2/README.md
+++ b/core-java-modules/core-java-collections-conversions-2/README.md
@@ -9,4 +9,6 @@ This module contains articles about conversions among Collection types and array
- [Converting List to Map With a Custom Supplier](https://www.baeldung.com/list-to-map-supplier)
- [Arrays.asList vs new ArrayList(Arrays.asList())](https://www.baeldung.com/java-arrays-aslist-vs-new-arraylist)
- [Iterate Over a Set in Java](https://www.baeldung.com/java-iterate-set)
+- [Convert a List of Integers to a List of Strings](https://www.baeldung.com/java-convert-list-integers-to-list-strings)
+- [Combining Two Lists Into a Map in Java](https://www.baeldung.com/java-combine-two-lists-into-map)
- More articles: [[<-- prev]](../core-java-collections-conversions)
diff --git a/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/combine2liststomap/CombineTwoListsInAMapUnitTest.java b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/combine2liststomap/CombineTwoListsInAMapUnitTest.java
new file mode 100644
index 0000000000..501ec16a21
--- /dev/null
+++ b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/combine2liststomap/CombineTwoListsInAMapUnitTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.combine2liststomap;
+
+import static java.lang.Math.min;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.junit.jupiter.api.Test;
+
+public class CombineTwoListsInAMapUnitTest {
+ private static final List KEY_LIST = Arrays.asList("Number One", "Number Two", "Number Three", "Number Four", "Number Five");
+ private static final List VALUE_LIST = Arrays.asList(1, 2, 3, 4, 5);
+ private static final Map EXPECTED_MAP = new HashMap() {{
+ put("Number One", 1);
+ put("Number Two", 2);
+ put("Number Three", 3);
+ put("Number Four", 4);
+ put("Number Five", 5);
+ }};
+
+ @Test
+ void givenTwoLists_whenUsingLoopAndListGet_shouldGetExpectedMap() {
+ Map result = new HashMap<>();
+ int size = KEY_LIST.size();
+ if (KEY_LIST.size() != VALUE_LIST.size()) {
+ // throw an exception or print a warning
+ size = min(KEY_LIST.size(), VALUE_LIST.size());
+ }
+ for (int i = 0; i < size; i++) {
+ result.put(KEY_LIST.get(i), VALUE_LIST.get(i));
+ }
+ assertEquals(EXPECTED_MAP, result);
+ }
+
+ @Test
+ void givenTwoLists_whenUsingStreamApiAndListGet_shouldGetExpectedMap() {
+ Map result = IntStream.range(0, KEY_LIST.size())
+ .boxed()
+ .collect(Collectors.toMap(KEY_LIST::get, VALUE_LIST::get));
+ assertEquals(EXPECTED_MAP, result);
+ }
+
+ @Test
+ void givenTwoLists_whenUsingIterators_shouldGetExpectedMap() {
+ Map result = new HashMap<>();
+
+ Iterator ik = KEY_LIST.iterator();
+ Iterator iv = VALUE_LIST.iterator();
+ while (ik.hasNext() && iv.hasNext()) {
+ result.put(ik.next(), iv.next());
+ }
+
+ assertEquals(EXPECTED_MAP, result);
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/intlisttostrlist/IntListToStringListUnitTest.java b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/intlisttostrlist/IntListToStringListUnitTest.java
new file mode 100644
index 0000000000..0990ef2b74
--- /dev/null
+++ b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/intlisttostrlist/IntListToStringListUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.intlisttostrlist;
+
+
+import com.google.common.base.Functions;
+import com.google.common.collect.Lists;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class IntListToStringListUnitTest {
+ private final static List INTEGER_LIST = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
+ private final static List EXPECTED_LIST = Arrays.asList("1", "2", "3", "4", "5", "6", "7");
+
+
+ @Test
+ void givenAnIntegerList_whenUsingStreamMap_shouldGetExpectedStringList() {
+ List result = INTEGER_LIST.stream().map(i -> i.toString()).collect(Collectors.toList());
+ assertEquals(EXPECTED_LIST, result);
+ }
+
+ @Test
+ void givenAnIntegerList_whenUsingGuava_shouldGetExpectedStringList() {
+ List result = Lists.transform(INTEGER_LIST, Functions.toStringFunction());
+ assertEquals(EXPECTED_LIST, result);
+ }
+
+ @Test
+ void givenAnIntegerList_whenUsingLoop_shouldGetExpectedStringList() {
+ List result = new ArrayList<>();
+ for (Integer i : INTEGER_LIST) {
+ result.add(i.toString());
+ }
+ assertEquals(EXPECTED_LIST, result);
+ }
+}
diff --git a/core-java-modules/core-java-collections-list-3/README.md b/core-java-modules/core-java-collections-list-3/README.md
index bcc8b3f3ed..40ebaf7693 100644
--- a/core-java-modules/core-java-collections-list-3/README.md
+++ b/core-java-modules/core-java-collections-list-3/README.md
@@ -12,4 +12,5 @@ This module contains articles about the Java List collection
- [How to Count Duplicate Elements in Arraylist](https://www.baeldung.com/java-count-duplicate-elements-arraylist)
- [Finding the Differences Between Two Lists in Java](https://www.baeldung.com/java-lists-difference)
- [List vs. ArrayList in Java](https://www.baeldung.com/java-list-vs-arraylist)
+- [Set vs List in Java](https://www.baeldung.com/java-set-vs-list)
- [[<-- Prev]](/core-java-modules/core-java-collections-list-2)
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/listandset/ListAndSetUnitTest.java b/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/listandset/ListAndSetUnitTest.java
similarity index 86%
rename from core-java-modules/core-java-collections-4/src/test/java/com/baeldung/listandset/ListAndSetUnitTest.java
rename to core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/listandset/ListAndSetUnitTest.java
index c57c1f96b8..43154c8e17 100644
--- a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/listandset/ListAndSetUnitTest.java
+++ b/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/listandset/ListAndSetUnitTest.java
@@ -1,10 +1,15 @@
-package com.baeldung.listandset;
+package com.baeldung.list.listandset;
-import org.junit.Test;
-import org.junit.Assert;
-import java.util.*;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
public class ListAndSetUnitTest {
diff --git a/core-java-modules/core-java-collections-list-4/README.md b/core-java-modules/core-java-collections-list-4/README.md
index 6966b60756..e5f2e8c718 100644
--- a/core-java-modules/core-java-collections-list-4/README.md
+++ b/core-java-modules/core-java-collections-list-4/README.md
@@ -11,5 +11,6 @@ This module contains articles about the Java List collection
- [Difference Between Arrays.asList() and List.of()](https://www.baeldung.com/java-arrays-aslist-vs-list-of)
- [How to Store HashMap Inside a List](https://www.baeldung.com/java-hashmap-inside-list)
- [Convert a List to a Comma-Separated String](https://www.baeldung.com/java-list-comma-separated-string)
-- [Set vs List in Java](https://www.baeldung.com/java-set-vs-list)
+- [Inserting an Object in an ArrayList at a Specific Position](https://www.baeldung.com/java-insert-object-arraylist-specific-position)
+- [Iterate Through Two ArrayLists Simultaneously](https://www.baeldung.com/iterate-through-two-arraylists-simultaneously)
- [[<-- Prev]](/core-java-modules/core-java-collections-list-3)
diff --git a/core-java-modules/core-java-collections-list-5/README.md b/core-java-modules/core-java-collections-list-5/README.md
new file mode 100644
index 0000000000..d8cd989600
--- /dev/null
+++ b/core-java-modules/core-java-collections-list-5/README.md
@@ -0,0 +1,7 @@
+## Core Java Collections List (Part 5)
+
+This module contains articles about the Java List collection
+
+### Relevant Articles:
+- [Java List Interface](https://www.baeldung.com/java-list-interface)
+- [Finding All Duplicates in a List in Java](https://www.baeldung.com/java-list-find-duplicates)
diff --git a/core-java-modules/core-java-collections-list-5/pom.xml b/core-java-modules/core-java-collections-list-5/pom.xml
new file mode 100644
index 0000000000..0807f7612c
--- /dev/null
+++ b/core-java-modules/core-java-collections-list-5/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+ core-java-collections-list-5
+ 0.1.0-SNAPSHOT
+ core-java-collections-list-5
+ jar
+
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+ commons-lang
+ commons-lang
+ ${commons-lang.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+ 2.2
+ 3.12.0
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-list-5/src/main/java/com/baeldung/listduplicate/ListDuplicate.java b/core-java-modules/core-java-collections-list-5/src/main/java/com/baeldung/listduplicate/ListDuplicate.java
new file mode 100644
index 0000000000..5e3e845916
--- /dev/null
+++ b/core-java-modules/core-java-collections-list-5/src/main/java/com/baeldung/listduplicate/ListDuplicate.java
@@ -0,0 +1,69 @@
+package com.baeldung.listduplicate;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class ListDuplicate {
+ public List listDuplicateUsingSet(List list) {
+ List duplicates = new ArrayList<>();
+ Set set = new HashSet<>();
+ for (Integer i : list) {
+ if (set.contains(i)) {
+ duplicates.add(i);
+ } else {
+ set.add(i);
+ }
+ }
+ return duplicates;
+ }
+
+ public List listDuplicateUsingMap(List list) {
+ List duplicates = new ArrayList<>();
+ Map frequencyMap = new HashMap<>();
+ for (Integer number : list) {
+ frequencyMap.put(number, frequencyMap.getOrDefault(number, 0) + 1);
+ }
+ for (int number : frequencyMap.keySet()) {
+ if (frequencyMap.get(number) != 1) {
+ duplicates.add(number);
+ }
+ }
+ return duplicates;
+ }
+
+ public List listDuplicateUsingFilterAndSetAdd(List list) {
+ Set elements = new HashSet();
+ return list.stream()
+ .filter(n -> !elements.add(n))
+ .collect(Collectors.toList());
+ }
+
+ public List listDuplicateUsingCollectionsFrequency(List list) {
+ List duplicates = new ArrayList<>();
+ Set set = list.stream()
+ .filter(i -> Collections.frequency(list, i) > 1)
+ .collect(Collectors.toSet());
+ duplicates.addAll(set);
+ return duplicates;
+ }
+
+ public List listDuplicateUsingMapAndCollectorsGroupingBy(List list) {
+ List duplicates = new ArrayList<>();
+ Set set = list.stream()
+ .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
+ .entrySet()
+ .stream()
+ .filter(m -> m.getValue() > 1)
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toSet());
+ duplicates.addAll(set);
+ return duplicates;
+ }
+}
diff --git a/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListUnitTest.java b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListUnitTest.java
new file mode 100644
index 0000000000..2222bc5a6f
--- /dev/null
+++ b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListUnitTest.java
@@ -0,0 +1,126 @@
+package com.baeldung.java.list;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+public class ListUnitTest {
+
+ @Test
+ public void givenAFruitList_whenAddNewFruit_thenFruitIsAdded(){
+ List fruits = new ArrayList<>();
+ assertEquals("Unexpected number of fruits in the list, should have been 0", 0, fruits.size());
+
+ fruits.add("Apple");
+ assertEquals("Unexpected number of fruits in the list, should have been 1", 1, fruits.size());
+ }
+
+ @Test
+ public void givenAFruitList_whenContainsFruit_thenFruitIsInTheList(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple");
+ assertTrue("Apple should be in the fruit list", fruits.contains("Apple"));
+ assertFalse("Banana should not be in the fruit list", fruits.contains("Banana"));
+ }
+
+ @Test
+ public void givenAnEmptyFruitList_whenEmptyCheck_thenListIsEmpty(){
+ List fruits = new ArrayList<>();
+ assertTrue("Fruit list should be empty", fruits.isEmpty());
+
+ fruits.add("Apple");
+ assertFalse("Fruit list should not be empty", fruits.isEmpty());
+ }
+
+ @Test
+ public void givenAFruitList_whenIterateOverIt_thenFruitsAreInOrder(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple"); // fruit at index 0
+ fruits.add("Orange");// fruit at index 1
+ fruits.add("Banana");// fruit at index 2
+ int index = 0;
+ for (Iterator it = fruits.listIterator(); it.hasNext(); ) {
+ String fruit = it.next();
+ assertEquals("Fruits should be in order", fruits.get(index++), fruit);
+ }
+ }
+
+ @Test
+ public void givenAFruitList_whenRemoveFruit_thenFruitIsRemoved(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple");
+ fruits.add("Orange");
+ assertEquals("Unexpected number of fruits in the list, should have been 2", 2, fruits.size());
+
+ fruits.remove("Apple");
+ assertEquals("Unexpected number of fruits in the list, should have been 1", 1, fruits.size());
+ }
+
+ @Test
+ public void givenAFruitList_whenSetFruit_thenFruitIsUpdated(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple");
+ fruits.add("Orange");
+
+ fruits.set(0, "Banana");
+ assertEquals("Fruit at index 0 should be Banana", "Banana", fruits.get(0));
+ }
+
+ @Test
+ public void givenAFruitList_whenSort_thenFruitsAreSorted(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple");
+ fruits.add("Orange");
+ fruits.add("Banana");
+
+ fruits.sort(Comparator.naturalOrder());
+
+ assertEquals("Fruit at index 0 should be Apple", "Apple", fruits.get(0));
+ assertEquals("Fruit at index 1 should be Banana", "Banana", fruits.get(1));
+ assertEquals("Fruit at index 2 should be Orange", "Orange", fruits.get(2));
+ }
+
+ @Test
+ public void givenAFruitList_whenSublist_thenWeGetASublist(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple");
+ fruits.add("Orange");
+ fruits.add("Banana");
+
+ List fruitsSublist = fruits.subList(0, 2);
+ assertEquals("Unexpected number of fruits in the sublist, should have been 2", 2, fruitsSublist.size());
+
+ assertEquals("Fruit at index 0 should be Apple", "Apple", fruitsSublist.get(0));
+ assertEquals("Fruit at index 1 should be Orange", "Orange", fruitsSublist.get(1));
+ }
+
+ @Test
+ public void givenAFruitList_whenToArray_thenWeGetAnArray(){
+ List fruits = new ArrayList<>();
+
+ fruits.add("Apple");
+ fruits.add("Orange");
+ fruits.add("Banana");
+
+ String[] fruitsArray = fruits.toArray(new String[0]);
+ assertEquals("Unexpected number of fruits in the array, should have been 3", 3, fruitsArray.length);
+
+ assertEquals("Fruit at index 0 should be Apple", "Apple", fruitsArray[0]);
+ assertEquals("Fruit at index 1 should be Orange", "Orange", fruitsArray[1]);
+ assertEquals("Fruit at index 2 should be Banana", "Banana", fruitsArray[2]);
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/listduplicate/ListDuplicateUnitTest.java b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/listduplicate/ListDuplicateUnitTest.java
new file mode 100644
index 0000000000..0d81387aea
--- /dev/null
+++ b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/listduplicate/ListDuplicateUnitTest.java
@@ -0,0 +1,68 @@
+package com.baeldung.listduplicate;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ListDuplicateUnitTest {
+ private static ListDuplicate listDuplicate;
+
+ @BeforeClass
+ public static void setup() {
+ listDuplicate = new ListDuplicate();
+ }
+
+ @Test
+ public void givenList_whenUsingSet_thenReturnDuplicateElements() {
+ List list = Arrays.asList(1, 2, 3, 3, 4, 4, 5);
+ List duplicates = listDuplicate.listDuplicateUsingSet(list);
+ Assert.assertEquals(duplicates.size(), 2);
+ Assert.assertEquals(duplicates.contains(3), true);
+ Assert.assertEquals(duplicates.contains(4), true);
+ Assert.assertEquals(duplicates.contains(1), false);
+ }
+
+ @Test
+ public void givenList_whenUsingFrequencyMap_thenReturnDuplicateElements() {
+ List list = Arrays.asList(1, 2, 3, 3, 4, 4, 5);
+ List duplicates = listDuplicate.listDuplicateUsingMap(list);
+ Assert.assertEquals(duplicates.size(), 2);
+ Assert.assertEquals(duplicates.contains(3), true);
+ Assert.assertEquals(duplicates.contains(4), true);
+ Assert.assertEquals(duplicates.contains(1), false);
+ }
+
+ @Test
+ public void givenList_whenUsingFilterAndSetAdd_thenReturnDuplicateElements() {
+ List list = Arrays.asList(1, 2, 3, 3, 4, 4, 5);
+ List duplicates = listDuplicate.listDuplicateUsingFilterAndSetAdd(list);
+ Assert.assertEquals(duplicates.size(), 2);
+ Assert.assertEquals(duplicates.contains(3), true);
+ Assert.assertEquals(duplicates.contains(4), true);
+ Assert.assertEquals(duplicates.contains(1), false);
+ }
+
+ @Test
+ public void givenList_whenUsingCollectionsFrequency_thenReturnDuplicateElements() {
+ List list = Arrays.asList(1, 2, 3, 3, 4, 4, 5);
+ List duplicates = listDuplicate.listDuplicateUsingCollectionsFrequency(list);
+ Assert.assertEquals(duplicates.size(), 2);
+ Assert.assertEquals(duplicates.contains(3), true);
+ Assert.assertEquals(duplicates.contains(4), true);
+ Assert.assertEquals(duplicates.contains(1), false);
+ }
+
+ @Test
+ public void givenList_whenUsingMapAndCollectorsGroupingBy_thenReturnDuplicateElements() {
+ List list = Arrays.asList(1, 2, 3, 3, 4, 4, 5);
+ List duplicates = listDuplicate.listDuplicateUsingCollectionsFrequency(list);
+ Assert.assertEquals(duplicates.size(), 2);
+ Assert.assertEquals(duplicates.contains(3), true);
+ Assert.assertEquals(duplicates.contains(4), true);
+ Assert.assertEquals(duplicates.contains(1), false);
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-maps-2/pom.xml b/core-java-modules/core-java-collections-maps-2/pom.xml
index da51adac53..1e526ef892 100644
--- a/core-java-modules/core-java-collections-maps-2/pom.xml
+++ b/core-java-modules/core-java-collections-maps-2/pom.xml
@@ -61,4 +61,4 @@
8.1.0
-
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-5/README.md b/core-java-modules/core-java-collections-maps-5/README.md
index a131c669c6..e1817c7ba4 100644
--- a/core-java-modules/core-java-collections-maps-5/README.md
+++ b/core-java-modules/core-java-collections-maps-5/README.md
@@ -9,4 +9,5 @@
- [Java IdentityHashMap Class and Its Use Cases](https://www.baeldung.com/java-identityhashmap)
- [How to Invert a Map in Java](https://www.baeldung.com/java-invert-map)
- [Implementing a Map with Multiple Keys in Java](https://www.baeldung.com/java-multiple-keys-map)
+- [Difference Between Map.ofEntries() and Map.of()](https://www.baeldung.com/map-ofentries-and-map-of)
- More articles: [[<-- prev]](../core-java-collections-maps-4)
diff --git a/core-java-modules/core-java-collections-maps-5/pom.xml b/core-java-modules/core-java-collections-maps-5/pom.xml
index ba7083e42e..f12e044b23 100644
--- a/core-java-modules/core-java-collections-maps-5/pom.xml
+++ b/core-java-modules/core-java-collections-maps-5/pom.xml
@@ -34,6 +34,19 @@
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 9
+ 9
+
+
+
+
+
5.2.5.RELEASE
diff --git a/core-java-modules/core-java-collections-maps-5/src/test/java/com/baeldung/map/mapofvsmapofentries/MapOfEntriesVsMapOfUnitTest.java b/core-java-modules/core-java-collections-maps-5/src/test/java/com/baeldung/map/mapofvsmapofentries/MapOfEntriesVsMapOfUnitTest.java
new file mode 100644
index 0000000000..f8a8e33139
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-5/src/test/java/com/baeldung/map/mapofvsmapofentries/MapOfEntriesVsMapOfUnitTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.map.mapofvsmapofentries;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class MapOfEntriesVsMapOfUnitTest {
+
+ @Test
+ void mapOf() {
+ // Use Map.of() to create an empty immutable map
+ Map map = Map.of();
+ assertNotNull(map);
+
+ // Use Map.of() to create an immutable map with one entry
+ Map mapWithEntry = Map.of(1L, "value1");
+ assertNotNull(mapWithEntry);
+ assertThat(mapWithEntry.size()).isEqualTo(1);
+ assertThat(mapWithEntry.get(1L)).isEqualTo("value1");
+
+ // Test if map is immutable
+ try {
+ mapWithEntry.put(2L, "value2");
+ } catch (UnsupportedOperationException e) {
+ assertThat(e).isInstanceOf(UnsupportedOperationException.class);
+ }
+ }
+
+ @Test
+ void mapOfEntries() {
+ // Use Map.ofEntries() to create an empty immutable map
+ Map map = Map.ofEntries();
+ assertNotNull(map);
+
+ // Use Map.ofEntries() to create an immutable map with two entries.
+ Map longUserMap = Map.ofEntries(Map.entry(1L, "User A"), Map.entry(2L, "User B"));
+ assertNotNull(longUserMap);
+ assertThat(longUserMap.size()).isEqualTo(2);
+ assertThat(longUserMap.get(1L)).isEqualTo("User A");
+ assertThat(longUserMap.get(2L)).isEqualTo("User B");
+
+ // Test if map is immutable
+ try {
+ longUserMap.put(3L, "User C");
+ } catch (UnsupportedOperationException e) {
+ assertThat(e).isInstanceOf(UnsupportedOperationException.class);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-6/README.md b/core-java-modules/core-java-collections-maps-6/README.md
new file mode 100644
index 0000000000..fc12a1bb25
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-6/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles
+- [Copying All Keys and Values From One Hashmap Onto Another Without Replacing Existing Keys and Values](https://www.baeldung.com/java-copy-hashmap-no-changes)
diff --git a/core-java-modules/core-java-collections-maps-6/pom.xml b/core-java-modules/core-java-collections-maps-6/pom.xml
new file mode 100644
index 0000000000..9910d08691
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-6/pom.xml
@@ -0,0 +1,20 @@
+
+
+ core-java-collections-maps-6
+ 0.1.0-SNAPSHOT
+ core-java-collections-maps-6
+ jar
+
+ core-java-modules
+ com.baeldung.core-java-modules
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+
+ 5.2.5.RELEASE
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-maps-6/src/main/java/com/baeldung/map/hashmapcopy/CopyingAHashMapToAnother.java b/core-java-modules/core-java-collections-maps-6/src/main/java/com/baeldung/map/hashmapcopy/CopyingAHashMapToAnother.java
new file mode 100644
index 0000000000..77a6402a75
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-6/src/main/java/com/baeldung/map/hashmapcopy/CopyingAHashMapToAnother.java
@@ -0,0 +1,47 @@
+package com.baeldung.map.hashmapcopy;
+
+import java.util.Map;
+
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.Maps;
+
+public class CopyingAHashMapToAnother {
+ public Map copyByIteration(Map sourceMap, Map targetMap) {
+ for (Map.Entry entry : sourceMap.entrySet()) {
+ if (!targetMap.containsKey(entry.getKey())) {
+ targetMap.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return targetMap;
+ }
+
+ public Map copyUsingPutAll(Map sourceMap, Map targetMap) {
+ sourceMap.keySet()
+ .removeAll(targetMap.keySet());
+ targetMap.putAll(sourceMap);
+ return targetMap;
+ }
+
+ public Map copyUsingPutIfAbsent(Map sourceMap, Map targetMap) {
+ for (Map.Entry entry : sourceMap.entrySet()) {
+ targetMap.putIfAbsent(entry.getKey(), entry.getValue());
+ }
+ return targetMap;
+ }
+
+ public Map copyUsingPutIfAbsentForEach(Map sourceMap, Map targetMap) {
+ sourceMap.forEach(targetMap::putIfAbsent);
+ return targetMap;
+ }
+
+ public Map copyUsingMapMerge(Map sourceMap, Map targetMap) {
+ sourceMap.forEach((key, value) -> targetMap.merge(key, value, (oldVal, newVal) -> oldVal));
+ return targetMap;
+ }
+
+ public Map copyUsingGuavaMapDifference(Map sourceMap, Map targetMap) {
+ MapDifference differenceMap = Maps.difference(sourceMap, targetMap);
+ targetMap.putAll(differenceMap.entriesOnlyOnLeft());
+ return targetMap;
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/hashmapcopy/CopyHashMapIntoAnotherUnitTest.java b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/hashmapcopy/CopyHashMapIntoAnotherUnitTest.java
new file mode 100644
index 0000000000..b11f470eb3
--- /dev/null
+++ b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/hashmapcopy/CopyHashMapIntoAnotherUnitTest.java
@@ -0,0 +1,68 @@
+package com.baeldung.map.hashmapcopy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baeldung.map.hashmapcopy.CopyingAHashMapToAnother;
+
+public class CopyHashMapIntoAnotherUnitTest {
+ @Test
+ public void givenSourceAndTargetMapsWhenIteratedOverThenCopyingSuccess(){
+ CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
+ Assert.assertEquals(generateExpectedResultMap(), obj.copyByIteration(generateSourceMap(), generateTargetMap()));
+ }
+
+ @Test
+ public void givenSourceAndTargetMapsWhenUsedPutAllThenCopyingSuccess(){
+ CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
+ Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingPutAll(generateSourceMap(), generateTargetMap()));
+ }
+
+ @Test
+ public void givenSourceAndTargetMapsWhenUsedPutIfAbsentThenCopyingSuccess(){
+ CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
+ Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingPutIfAbsent(generateSourceMap(), generateTargetMap()));
+ Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingPutIfAbsentForEach(generateSourceMap(), generateTargetMap()));
+ }
+
+ @Test
+ public void givenSourceAndTargetMapsWhenUsedMapMergeThenCopyingSuccess(){
+ CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
+ Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingMapMerge(generateSourceMap(), generateTargetMap()));
+ }
+
+ @Test
+ public void givenSourceAndTargetMapsWhenMapDifferenceUsedThenCopyingSuccess(){
+ CopyingAHashMapToAnother obj = new CopyingAHashMapToAnother();
+ Assert.assertEquals(generateExpectedResultMap(), obj.copyUsingGuavaMapDifference(generateSourceMap(), generateTargetMap()));
+ }
+
+ private Map generateSourceMap(){
+ Map sourceMap = new HashMap<>();
+ sourceMap.put("India", "Delhi");
+ sourceMap.put("United States", "Washington D.C.");
+ sourceMap.put("United Kingdom", "London DC");
+ return sourceMap;
+ }
+
+ private Map generateTargetMap(){
+ Map targetMap = new HashMap<>();
+ targetMap.put("Zimbabwe", "Harare");
+ targetMap.put("Norway", "Oslo");
+ targetMap.put("United Kingdom", "London");
+ return targetMap;
+ }
+
+ private Map generateExpectedResultMap(){
+ Map resultMap = new HashMap<>();
+ resultMap.put("India", "Delhi");
+ resultMap.put("United States", "Washington D.C.");
+ resultMap.put("United Kingdom", "London");
+ resultMap.put("Zimbabwe", "Harare");
+ resultMap.put("Norway", "Oslo");
+ return resultMap;
+ }
+}
diff --git a/core-java-modules/core-java-collections-maps/README.md b/core-java-modules/core-java-collections-maps/README.md
index 15cb32fbe8..034c71ba9a 100644
--- a/core-java-modules/core-java-collections-maps/README.md
+++ b/core-java-modules/core-java-collections-maps/README.md
@@ -12,4 +12,5 @@ This module contains articles about Map data structures in Java.
- [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps)
- [Guide to Apache Commons MultiValuedMap](https://www.baeldung.com/apache-commons-multi-valued-map)
- [The Java HashMap Under the Hood](https://www.baeldung.com/java-hashmap-advanced)
+- [Create an Empty Map in Java](https://www.baeldung.com/java-create-empty-map)
- More articles: [[next -->]](/core-java-modules/core-java-collections-maps-2)
diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml
index 34b878df53..3a1bf0d8a1 100644
--- a/core-java-modules/core-java-collections-maps/pom.xml
+++ b/core-java-modules/core-java-collections-maps/pom.xml
@@ -20,6 +20,12 @@
commons-collections4
${commons-collections4.version}
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit-platform.version}
+ test
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/maps/initialize/EmptyMapInitializer.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/EmptyMapInitializer.java
similarity index 97%
rename from core-java-modules/core-java-collections-4/src/main/java/com/baeldung/maps/initialize/EmptyMapInitializer.java
rename to core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/EmptyMapInitializer.java
index 78819cc21e..106de799e7 100644
--- a/core-java-modules/core-java-collections-4/src/main/java/com/baeldung/maps/initialize/EmptyMapInitializer.java
+++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/EmptyMapInitializer.java
@@ -1,7 +1,5 @@
-package com.baeldung.maps.initialize;
+package com.baeldung.map;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -10,6 +8,9 @@ import java.util.NavigableMap;
import java.util.SortedMap;
import java.util.TreeMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
public class EmptyMapInitializer {
public static Map articleMap;
diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/maps/initialize/EmptyMapInitializerUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/EmptyMapInitializerUnitTest.java
similarity index 96%
rename from core-java-modules/core-java-collections-4/src/test/java/com/baeldung/maps/initialize/EmptyMapInitializerUnitTest.java
rename to core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/EmptyMapInitializerUnitTest.java
index 57183734cb..94a70cdd5d 100644
--- a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/maps/initialize/EmptyMapInitializerUnitTest.java
+++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/EmptyMapInitializerUnitTest.java
@@ -1,11 +1,12 @@
-package com.baeldung.maps.initialize;
-
-import java.util.Map;
-import org.junit.Test;
+package com.baeldung.map;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.util.Map;
+
+import org.junit.Test;
+
public class EmptyMapInitializerUnitTest {
@Test(expected=UnsupportedOperationException.class)
diff --git a/core-java-modules/core-java-collections-set-2/README.md b/core-java-modules/core-java-collections-set-2/README.md
index 48c70084ca..a11329365a 100644
--- a/core-java-modules/core-java-collections-set-2/README.md
+++ b/core-java-modules/core-java-collections-set-2/README.md
@@ -2,3 +2,5 @@
- [Using Streams to Collect Into a TreeSet](https://www.baeldung.com/java-stream-collect-into-treeset)
- [A Guide to LinkedHashSet in Java](https://www.baeldung.com/java-linkedhashset)
+- [Sorting a HashSet in Java](https://www.baeldung.com/java-sort-hashset)
+- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set)
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-set-2/pom.xml b/core-java-modules/core-java-collections-set-2/pom.xml
index d3f54554e0..b1aadb0c22 100644
--- a/core-java-modules/core-java-collections-set-2/pom.xml
+++ b/core-java-modules/core-java-collections-set-2/pom.xml
@@ -15,6 +15,12 @@
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit-platform.version}
+ test
+
diff --git a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/hashset/sorting/HashSetUnitTest.java b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/hashset/sorting/HashSetUnitTest.java
new file mode 100644
index 0000000000..ebb400570f
--- /dev/null
+++ b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/hashset/sorting/HashSetUnitTest.java
@@ -0,0 +1,55 @@
+package com.baeldung.hashset.sorting;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+public class HashSetUnitTest {
+
+ @Test
+ void givenHashSet_whenUsingCollectionsSort_thenHashSetSorted() {
+ HashSet numberHashSet = new HashSet<>();
+ numberHashSet.add(2);
+ numberHashSet.add(1);
+ numberHashSet.add(4);
+ numberHashSet.add(3);
+ // converting HashSet to arraylist
+ ArrayList arrayList = new ArrayList<>(numberHashSet);
+ // sorting the list
+ Collections.sort(arrayList);
+ assertThat(arrayList).containsExactly(1, 2, 3, 4);
+ }
+
+ @Test
+ void givenHashSet_whenUsingTreeSet_thenHashSetSorted() {
+ HashSet numberHashSet = new HashSet<>();
+ numberHashSet.add(2);
+ numberHashSet.add(1);
+ numberHashSet.add(4);
+ numberHashSet.add(3);
+ // TreeSet gets the value of hashSet
+ TreeSet treeSet = new TreeSet<>();
+ treeSet.addAll(numberHashSet);
+ assertThat(treeSet).containsExactly(1, 2, 3, 4);
+ }
+
+ @Test
+ void givenHashSet_whenUsingStream_thenHashSetSorted() {
+ HashSet numberHashSet = new HashSet<>();
+ numberHashSet.add(200);
+ numberHashSet.add(100);
+ numberHashSet.add(400);
+ numberHashSet.add(300);
+ HashSet sortedHashSet = numberHashSet.stream().sorted()
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ assertThat(sortedHashSet).containsExactly(100, 200, 300, 400);
+ }
+
+}
diff --git a/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/donerunnables/RunnableCompletionCheckerWithThreadPoolExecutor.java b/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/donerunnables/RunnableCompletionCheckerWithThreadPoolExecutor.java
index 17a13a1c19..aba75c5a3d 100644
--- a/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/donerunnables/RunnableCompletionCheckerWithThreadPoolExecutor.java
+++ b/core-java-modules/core-java-concurrency-2/src/main/java/com/baeldung/donerunnables/RunnableCompletionCheckerWithThreadPoolExecutor.java
@@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory;
public class RunnableCompletionCheckerWithThreadPoolExecutor {
- private static final Logger LOGGER = LoggerFactory.getLogger(RunnableCompletionCheckerWithCompletableFuture.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(RunnableCompletionCheckerWithThreadPoolExecutor.class);
private static final int NUMBER_OF_RUNNABLES = 5;
private static final int PAUSE_MILLIS = 1000;
private static final int NUMBER_OF_THREADS = 5;
diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
index ef6b7ee8c8..09dfe575e6 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
+++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
@@ -1,7 +1,7 @@
package com.baeldung.concurrent.atomic;
public class SafeCounterWithLock {
- private volatile int counter;
+ private int counter;
int getValue() {
return counter;
diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
index 8b2aebba7c..e1117dd842 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
+++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
@@ -10,12 +10,6 @@ public class SafeCounterWithoutLock {
}
void increment() {
- while(true) {
- int existingValue = getValue();
- int newValue = existingValue + 1;
- if(counter.compareAndSet(existingValue, newValue)) {
- return;
- }
- }
+ counter.incrementAndGet();
}
}
diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
index c3c44b40cf..9b4b628d0f 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
+++ b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
@@ -17,8 +17,8 @@ public class ThreadSafeCounterIntegrationTest {
SafeCounterWithLock safeCounter = new SafeCounterWithLock();
IntStream.range(0, 1000)
- .forEach(count -> service.submit(safeCounter::increment));
- service.awaitTermination(100, TimeUnit.MILLISECONDS);
+ .forEach(count -> service.execute(safeCounter::increment));
+ shutdownAndAwaitTermination(service);
assertEquals(1000, safeCounter.getValue());
}
@@ -29,10 +29,30 @@ public class ThreadSafeCounterIntegrationTest {
SafeCounterWithoutLock safeCounter = new SafeCounterWithoutLock();
IntStream.range(0, 1000)
- .forEach(count -> service.submit(safeCounter::increment));
- service.awaitTermination(100, TimeUnit.MILLISECONDS);
+ .forEach(count -> service.execute(safeCounter::increment));
+ shutdownAndAwaitTermination(service);
assertEquals(1000, safeCounter.getValue());
}
+
+ private void shutdownAndAwaitTermination(ExecutorService pool) {
+ // Disable new tasks from being submitted
+ pool.shutdown();
+ try {
+ // Wait a while for existing tasks to terminate
+ if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS)) {
+ // Cancel currently executing tasks forcefully
+ pool.shutdownNow();
+ // Wait a while for tasks to respond to being cancelled
+ if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS))
+ System.err.println("Pool did not terminate");
+ }
+ } catch (InterruptedException ex) {
+ // (Re-)Cancel if current thread also interrupted
+ pool.shutdownNow();
+ // Preserve interrupt status
+ Thread.currentThread().interrupt();
+ }
+ }
}
diff --git a/core-java-modules/core-java-concurrency-basic-2/README.md b/core-java-modules/core-java-concurrency-basic-2/README.md
index c9f1c11a89..455ff52081 100644
--- a/core-java-modules/core-java-concurrency-basic-2/README.md
+++ b/core-java-modules/core-java-concurrency-basic-2/README.md
@@ -11,4 +11,5 @@ This module contains articles about basic Java concurrency
- [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time)
- [How to Get the Number of Threads in a Java Process](https://www.baeldung.com/java-get-number-of-threads)
- [Set the Name of a Thread in Java](https://www.baeldung.com/java-set-thread-name)
+- [Thread vs. Single Thread Executor Service](https://www.baeldung.com/java-single-thread-executor-service)
- [[<-- Prev]](../core-java-concurrency-basic)[[Next -->]](../core-java-concurrency-basic-3)
diff --git a/core-java-modules/core-java-concurrency-basic-3/README.md b/core-java-modules/core-java-concurrency-basic-3/README.md
index 477f37e00a..46480c6b01 100644
--- a/core-java-modules/core-java-concurrency-basic-3/README.md
+++ b/core-java-modules/core-java-concurrency-basic-3/README.md
@@ -5,4 +5,5 @@ This module contains articles about basic Java concurrency.
### Relevant Articles:
- [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception)
+- [Thread.sleep() vs Awaitility.await()](https://www.baeldung.com/java-thread-sleep-vs-awaitility-await)
- [[<-- Prev]](../core-java-concurrency-basic-2)
diff --git a/core-java-modules/core-java-concurrency-basic-3/pom.xml b/core-java-modules/core-java-concurrency-basic-3/pom.xml
index 7771d1200c..7289877550 100644
--- a/core-java-modules/core-java-concurrency-basic-3/pom.xml
+++ b/core-java-modules/core-java-concurrency-basic-3/pom.xml
@@ -24,4 +24,16 @@
+
+ 4.2.0
+
+
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/RequestProcessor.java b/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/RequestProcessor.java
new file mode 100644
index 0000000000..9557a27f2a
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/RequestProcessor.java
@@ -0,0 +1,35 @@
+package com.baeldung.concurrent;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class RequestProcessor {
+
+ private Map requestStatuses = new HashMap<>();
+
+ public String processRequest() {
+ String requestId = UUID.randomUUID().toString();
+ requestStatuses.put(requestId, "PROCESSING");
+
+ ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+ executorService.schedule((() -> {
+ requestStatuses.put(requestId, "DONE");
+ }), getRandomNumberBetween(500, 2000), TimeUnit.MILLISECONDS);
+
+ return requestId;
+ }
+
+ public String getStatus(String requestId) {
+ return requestStatuses.get(requestId);
+ }
+
+ private int getRandomNumberBetween(int min, int max) {
+ Random random = new Random();
+ return random.nextInt(max - min) + min;
+ }
+}
diff --git a/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/RequestProcessorUnitTest.java b/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/RequestProcessorUnitTest.java
new file mode 100644
index 0000000000..c437b08b34
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-basic-3/src/test/java/com/baeldung/concurrent/RequestProcessorUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.concurrent;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.concurrent.TimeUnit;
+
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+@DisplayName("Request processor")
+public class RequestProcessorUnitTest {
+
+ RequestProcessor requestProcessor = new RequestProcessor();
+
+ @Test
+ @DisplayName("Wait for completion using Thread.sleep")
+ void whenWaitingWithThreadSleep_thenStatusIsDone() throws InterruptedException {
+ String requestId = requestProcessor.processRequest();
+
+ Thread.sleep(2000);
+
+ assertEquals("DONE", requestProcessor.getStatus(requestId));
+ }
+
+ @Test
+ @DisplayName("Wait for completion using Awaitility")
+ void whenWaitingWithAwaitility_thenStatusIsDone() {
+ String requestId = requestProcessor.processRequest();
+
+ Awaitility.await()
+ .atMost(2, TimeUnit.SECONDS)
+ .pollDelay(500, TimeUnit.MILLISECONDS)
+ .until(() -> requestProcessor.getStatus(requestId), not(equalTo("PROCESSING")));
+
+ assertEquals("DONE", requestProcessor.getStatus(requestId));
+ }
+
+}
diff --git a/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
similarity index 95%
rename from core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
index 16d9aa4c9f..cd77069979 100644
--- a/core-java-modules/core-java-concurrency-simple/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
+++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
@@ -1,14 +1,15 @@
package com.baeldung.concurrent.executorservice;
+
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
public class DelayedCallable implements Callable {
-
+
private String name;
private long period;
private CountDownLatch latch;
-
+
public DelayedCallable(String name, long period, CountDownLatch latch) {
this(name, period);
this.latch = latch;
@@ -23,11 +24,11 @@ public class DelayedCallable implements Callable {
try {
Thread.sleep(period);
-
+
if (latch != null) {
latch.countDown();
}
-
+
} catch (InterruptedException ex) {
// handle exception
ex.printStackTrace();
@@ -36,4 +37,4 @@ public class DelayedCallable implements Callable {
return name;
}
-}
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
similarity index 90%
rename from core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
index cd8b015be2..8e08914c3c 100644
--- a/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
+++ b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
@@ -1,15 +1,24 @@
package com.baeldung.concurrent.executorservice;
+import static junit.framework.TestCase.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.*;
-
-import static junit.framework.TestCase.assertTrue;
-
public class WaitingForThreadsToFinishManualTest {
private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishManualTest.class);
@@ -26,18 +35,18 @@ public class WaitingForThreadsToFinishManualTest {
Thread.currentThread().interrupt();
}
}
-
+
@Test
public void givenMultipleThreads_whenUsingCountDownLatch_thenMainShoudWaitForAllToFinish() {
ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
-
+
try {
long startTime = System.currentTimeMillis();
// create a CountDownLatch that waits for the 2 threads to finish
CountDownLatch latch = new CountDownLatch(2);
-
+
for (int i = 0; i < 2; i++) {
WORKER_THREAD_POOL.submit(() -> {
try {
@@ -69,13 +78,13 @@ public class WaitingForThreadsToFinishManualTest {
ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
List> callables = Arrays.asList(
- new DelayedCallable("fast thread", 100),
+ new DelayedCallable("fast thread", 100),
new DelayedCallable("slow thread", 3000));
try {
long startProcessingTime = System.currentTimeMillis();
List> futures = WORKER_THREAD_POOL.invokeAll(callables);
-
+
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
try {
@@ -100,7 +109,7 @@ public class WaitingForThreadsToFinishManualTest {
} catch (ExecutionException | InterruptedException ex) {
ex.printStackTrace();
- }
+ }
}
@Test
@@ -109,7 +118,7 @@ public class WaitingForThreadsToFinishManualTest {
CompletionService service = new ExecutorCompletionService<>(WORKER_THREAD_POOL);
List> callables = Arrays.asList(
- new DelayedCallable("fast thread", 100),
+ new DelayedCallable("fast thread", 100),
new DelayedCallable("slow thread", 3000));
for (Callable callable : callables) {
@@ -142,4 +151,4 @@ public class WaitingForThreadsToFinishManualTest {
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
}
}
-}
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-collections-2/README.md b/core-java-modules/core-java-concurrency-collections-2/README.md
index 692c218395..c812ed4284 100644
--- a/core-java-modules/core-java-concurrency-collections-2/README.md
+++ b/core-java-modules/core-java-concurrency-collections-2/README.md
@@ -3,4 +3,5 @@
- [Introduction to Lock Striping](https://www.baeldung.com/java-lock-stripping)
- [Guide to the Java TransferQueue](http://www.baeldung.com/java-transfer-queue)
- [Java Concurrent HashSet Equivalent to ConcurrentHashMap](https://www.baeldung.com/java-concurrent-hashset-concurrenthashmap)
+- [Reading and Writing With a ConcurrentHashMap](https://www.baeldung.com/concurrenthashmap-reading-and-writing)
- [[<-- Prev]](/core-java-modules/core-java-concurrency-collections)
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java
index ceb53ce077..28231a15a8 100644
--- a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java
+++ b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java
@@ -19,7 +19,7 @@ import org.openjdk.jmh.annotations.Warmup;
@Warmup(iterations = 0)
public class ConcurrentAccessBenchmark {
static final int SLOTS = 4;
- static final int THREADS = 10000;
+ static final int TASKS = 10000;
static final int BUCKETS = Runtime.getRuntime().availableProcessors() * SLOTS;
SingleLock singleLock = new SingleLock();
StripedLock stripedLock = new StripedLock(BUCKETS);
@@ -28,27 +28,27 @@ public class ConcurrentAccessBenchmark {
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public Map singleLockHashMap() throws InterruptedException {
- return singleLock.doWork(new HashMap(), THREADS, SLOTS);
+ return singleLock.doWork(new HashMap(), TASKS, SLOTS);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public Map stripedLockHashMap() throws InterruptedException {
- return stripedLock.doWork(new HashMap(), THREADS, SLOTS);
+ return stripedLock.doWork(new HashMap(), TASKS, SLOTS);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public Map singleLockConcurrentHashMap() throws InterruptedException {
- return singleLock.doWork(new ConcurrentHashMap(), THREADS, SLOTS);
+ return singleLock.doWork(new ConcurrentHashMap(), TASKS, SLOTS);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public Map stripedLockConcurrentHashMap() throws InterruptedException {
- return stripedLock.doWork(new ConcurrentHashMap(), THREADS, SLOTS);
+ return stripedLock.doWork(new ConcurrentHashMap(), TASKS, SLOTS);
}
}
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java
index ec6d3895da..b24f0c8b19 100644
--- a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java
+++ b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java
@@ -7,10 +7,10 @@ import com.google.common.base.Supplier;
public abstract class ConcurrentAccessExperiment {
- public final Map doWork(Map map, int threads, int slots) {
- CompletableFuture>[] requests = new CompletableFuture>[threads * slots];
+ public final Map doWork(Map map, int tasks, int slots) {
+ CompletableFuture>[] requests = new CompletableFuture>[tasks * slots];
- for (int i = 0; i < threads; i++) {
+ for (int i = 0; i < tasks; i++) {
requests[slots * i + 0] = CompletableFuture.supplyAsync(putSupplier(map, i));
requests[slots * i + 1] = CompletableFuture.supplyAsync(getSupplier(map, i));
requests[slots * i + 2] = CompletableFuture.supplyAsync(getSupplier(map, i));
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/concurrenthashmap/ConcurrentHashMapUnitTest.java b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/concurrenthashmap/ConcurrentHashMapUnitTest.java
new file mode 100644
index 0000000000..2ae510b365
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/concurrenthashmap/ConcurrentHashMapUnitTest.java
@@ -0,0 +1,109 @@
+package com.baeldung.concurrenthashmap;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ConcurrentHashMapUnitTest {
+
+ private Map