diff --git a/algorithms-miscellaneous-4/src/main/java/com/baeldung/algorithms/smallestinteger/SmallestMissingPositiveInteger.java b/algorithms-miscellaneous-4/src/main/java/com/baeldung/algorithms/smallestinteger/SmallestMissingPositiveInteger.java
new file mode 100644
index 0000000000..b08eea2a66
--- /dev/null
+++ b/algorithms-miscellaneous-4/src/main/java/com/baeldung/algorithms/smallestinteger/SmallestMissingPositiveInteger.java
@@ -0,0 +1,37 @@
+package com.baeldung.algorithms.smallestinteger;
+
+import java.util.Arrays;
+
+public class SmallestMissingPositiveInteger {
+ public static int searchInSortedArray(int[] input) {
+ for (int i = 0; i < input.length; i++) {
+ if (i != input[i]) {
+ return i;
+ }
+ }
+
+ return input.length;
+ }
+
+ public static int searchInUnsortedArraySortingFirst(int[] input) {
+ Arrays.sort(input);
+ return searchInSortedArray(input);
+ }
+
+ public static int searchInUnsortedArrayBooleanArray(int[] input) {
+ boolean[] flags = new boolean[input.length];
+ for (int number : input) {
+ if (number < flags.length) {
+ flags[number] = true;
+ }
+ }
+
+ for (int i = 0; i < flags.length; i++) {
+ if (!flags[i]) {
+ return i;
+ }
+ }
+
+ return flags.length;
+ }
+}
diff --git a/algorithms-miscellaneous-4/src/test/java/com/baeldung/algorithms/smallestinteger/SmallestMissingPositiveIntegerUnitTest.java b/algorithms-miscellaneous-4/src/test/java/com/baeldung/algorithms/smallestinteger/SmallestMissingPositiveIntegerUnitTest.java
new file mode 100644
index 0000000000..8bb7151b41
--- /dev/null
+++ b/algorithms-miscellaneous-4/src/test/java/com/baeldung/algorithms/smallestinteger/SmallestMissingPositiveIntegerUnitTest.java
@@ -0,0 +1,88 @@
+package com.baeldung.algorithms.smallestinteger;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class SmallestMissingPositiveIntegerUnitTest {
+ @Test
+ void givenArrayWithThreeMissing_whenSearchInSortedArray_thenThree() {
+ int[] input = new int[] {0, 1, 2, 4, 5};
+
+ int result = SmallestMissingPositiveInteger.searchInSortedArray(input);
+
+ assertThat(result).isEqualTo(3);
+ }
+
+ @Test
+ void givenArrayWithOneAndThreeMissing_whenSearchInSortedArray_thenOne() {
+ int[] input = new int[] {0, 2, 4, 5};
+
+ int result = SmallestMissingPositiveInteger.searchInSortedArray(input);
+
+ assertThat(result).isEqualTo(1);
+ }
+
+ @Test
+ void givenArrayWithoutMissingInteger_whenSearchInSortedArray_thenArrayLength() {
+ int[] input = new int[] {0, 1, 2, 3, 4, 5};
+
+ int result = SmallestMissingPositiveInteger.searchInSortedArray(input);
+
+ assertThat(result).isEqualTo(input.length);
+ }
+
+ @Test
+ void givenArrayWithThreeMissing_whenSearchInUnsortedArraySortingFirst_thenThree() {
+ int[] input = new int[] {1, 4, 0, 5, 2};
+
+ int result = SmallestMissingPositiveInteger.searchInUnsortedArraySortingFirst(input);
+
+ assertThat(result).isEqualTo(3);
+ }
+
+ @Test
+ void givenArrayWithOneAndThreeMissing_whenSearchInUnsortedArraySortingFirst_thenOne() {
+ int[] input = new int[] {4, 2, 0, 5};
+
+ int result = SmallestMissingPositiveInteger.searchInUnsortedArraySortingFirst(input);
+
+ assertThat(result).isEqualTo(1);
+ }
+
+ @Test
+ void givenArrayWithoutMissingInteger_whenSearchInUnsortedArraySortingFirst_thenArrayLength() {
+ int[] input = new int[] {4, 5, 1, 3, 0, 2};
+
+ int result = SmallestMissingPositiveInteger.searchInUnsortedArraySortingFirst(input);
+
+ assertThat(result).isEqualTo(input.length);
+ }
+
+ @Test
+ void givenArrayWithThreeMissing_whenSearchInUnsortedArrayBooleanArray_thenThree() {
+ int[] input = new int[] {1, 4, 0, 5, 2};
+
+ int result = SmallestMissingPositiveInteger.searchInUnsortedArrayBooleanArray(input);
+
+ assertThat(result).isEqualTo(3);
+ }
+
+ @Test
+ void givenArrayWithOneAndThreeMissing_whenSearchInUnsortedArrayBooleanArray_thenOne() {
+ int[] input = new int[] {4, 2, 0, 5};
+
+ int result = SmallestMissingPositiveInteger.searchInUnsortedArrayBooleanArray(input);
+
+ assertThat(result).isEqualTo(1);
+ }
+
+ @Test
+ void givenArrayWithoutMissingInteger_whenSearchInUnsortedArrayBooleanArray_thenArrayLength() {
+ int[] input = new int[] {4, 5, 1, 3, 0, 2};
+
+ int result = SmallestMissingPositiveInteger.searchInUnsortedArrayBooleanArray(input);
+
+ assertThat(result).isEqualTo(input.length);
+ }
+}
\ No newline at end of file
diff --git a/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/binarygap/BinaryGap.java b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/binarygap/BinaryGap.java
new file mode 100644
index 0000000000..e31e9870a0
--- /dev/null
+++ b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/binarygap/BinaryGap.java
@@ -0,0 +1,17 @@
+package com.baeldung.algorithms.binarygap;
+
+public class BinaryGap {
+ static int calculateBinaryGap(int n) {
+ return calculateBinaryGap(n >>> Integer.numberOfTrailingZeros(n), 0, 0);
+ }
+
+ static int calculateBinaryGap(int n, int current, int maximum) {
+ if (n == 0) {
+ return maximum;
+ } else if ((n & 1) == 0) {
+ return calculateBinaryGap(n >>> 1, current + 1, maximum);
+ } else {
+ return calculateBinaryGap(n >>> 1, 0, Math.max(maximum, current));
+ }
+ }
+}
diff --git a/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/binarygap/BinaryGapUnitTest.java b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/binarygap/BinaryGapUnitTest.java
new file mode 100644
index 0000000000..304d36e2bb
--- /dev/null
+++ b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/binarygap/BinaryGapUnitTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.algorithms.binarygap;
+
+import static com.baeldung.algorithms.binarygap.BinaryGap.calculateBinaryGap;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class BinaryGapUnitTest {
+
+ @Test public void givenNoOccurrenceOfBoundedZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
+
+ int result = calculateBinaryGap(63);
+ assertEquals(0, result);
+ }
+
+ @Test public void givenTrailingZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
+
+ int result = calculateBinaryGap(40);
+ assertEquals(1, result);
+ }
+
+ @Test public void givenSingleOccurrenceOfBoundedZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
+
+ int result = calculateBinaryGap(9);
+ assertEquals(2, result);
+ }
+
+ @Test public void givenMultipleOccurrenceOfBoundedZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
+
+ int result = calculateBinaryGap(145);
+ assertEquals(3, result);
+ }
+
+}
diff --git a/core-java-modules/README.md b/core-java-modules/README.md
index 55dacca916..fa77846b45 100644
--- a/core-java-modules/README.md
+++ b/core-java-modules/README.md
@@ -5,6 +5,5 @@ This module contains modules about core Java
## Relevant articles:
- [Multi-Module Maven Application with Java Modules](https://www.baeldung.com/maven-multi-module-project-java-jpms)
-- [Guide to Java FileChannel](https://www.baeldung.com/java-filechannel)
- [Understanding the NumberFormatException in Java](https://www.baeldung.com/java-number-format-exception)
- [Will an Error Be Caught by Catch Block in Java?](https://www.baeldung.com/java-error-catch)
diff --git a/core-java-modules/core-java-9-improvements/README.md b/core-java-modules/core-java-9-improvements/README.md
new file mode 100644
index 0000000000..b0baccba7f
--- /dev/null
+++ b/core-java-modules/core-java-9-improvements/README.md
@@ -0,0 +1,17 @@
+## Core Java 9
+
+This module contains articles about the improvements to core Java features introduced with Java 9.
+
+### Relevant Articles:
+
+- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors)
+- [Java 9 Optional API Additions](https://www.baeldung.com/java-9-optional)
+- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods)
+- [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api)
+- [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new)
+- [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture)
+
+#### Relevant articles not in this module:
+
+- [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) (see the [core-java-os](/core-java-os) module)
+
diff --git a/core-java-modules/core-java-9-improvements/pom.xml b/core-java-modules/core-java-9-improvements/pom.xml
new file mode 100644
index 0000000000..aee289c79f
--- /dev/null
+++ b/core-java-modules/core-java-9-improvements/pom.xml
@@ -0,0 +1,73 @@
+
+ 4.0.0
+ core-java-9
+ 0.2-SNAPSHOT
+ core-java-9
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+ com.jayway.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+
+
+ core-java-9
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+
+
+
+
+ apache.snapshots
+ http://repository.apache.org/snapshots/
+
+
+
+
+
+ 3.10.0
+ 1.2.0
+ 1.7.0
+ 1.9
+ 1.9
+ 25.1-jre
+
+
+
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/Java9OptionalTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/Java9OptionalTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java b/core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java
rename to core-java-modules/core-java-9-improvements/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java
diff --git a/core-java-modules/core-java-9-jigsaw/README.md b/core-java-modules/core-java-9-jigsaw/README.md
new file mode 100644
index 0000000000..b1a401d48c
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/README.md
@@ -0,0 +1,11 @@
+## Core Java 9
+
+This module contains articles about Project Jigsaw and the Java Platform Module System (JPMS), introduced with Java 9.
+
+### Relevant Articles:
+
+- [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity)
+- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity)
+- [Java 9 java.lang.Module API](https://www.baeldung.com/java-9-module-api)
+
+
diff --git a/core-java-modules/core-java-9/compile-simple-modules.sh b/core-java-modules/core-java-9-jigsaw/compile-simple-modules.sh
similarity index 100%
rename from core-java-modules/core-java-9/compile-simple-modules.sh
rename to core-java-modules/core-java-9-jigsaw/compile-simple-modules.sh
diff --git a/core-java-modules/core-java-9/compile-student-client.bat b/core-java-modules/core-java-9-jigsaw/compile-student-client.bat
similarity index 100%
rename from core-java-modules/core-java-9/compile-student-client.bat
rename to core-java-modules/core-java-9-jigsaw/compile-student-client.bat
diff --git a/core-java-modules/core-java-9/compile-student-model.bat b/core-java-modules/core-java-9-jigsaw/compile-student-model.bat
similarity index 100%
rename from core-java-modules/core-java-9/compile-student-model.bat
rename to core-java-modules/core-java-9-jigsaw/compile-student-model.bat
diff --git a/core-java-modules/core-java-9/compile-student-service-dbimpl.bat b/core-java-modules/core-java-9-jigsaw/compile-student-service-dbimpl.bat
similarity index 100%
rename from core-java-modules/core-java-9/compile-student-service-dbimpl.bat
rename to core-java-modules/core-java-9-jigsaw/compile-student-service-dbimpl.bat
diff --git a/core-java-modules/core-java-9/compile-student-service.bat b/core-java-modules/core-java-9-jigsaw/compile-student-service.bat
similarity index 100%
rename from core-java-modules/core-java-9/compile-student-service.bat
rename to core-java-modules/core-java-9-jigsaw/compile-student-service.bat
diff --git a/core-java-modules/core-java-9-jigsaw/pom.xml b/core-java-modules/core-java-9-jigsaw/pom.xml
new file mode 100644
index 0000000000..8194ae9d00
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/pom.xml
@@ -0,0 +1,35 @@
+
+ 4.0.0
+ core-java-9-jigsaw
+ 0.2-SNAPSHOT
+ core-java-9
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+ core-java-9-jigsaw
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+
+
+
+ 1.9
+ 1.9
+
+
+
diff --git a/core-java-modules/core-java-9/run-simple-module-app.sh b/core-java-modules/core-java-9-jigsaw/run-simple-module-app.sh
similarity index 100%
rename from core-java-modules/core-java-9/run-simple-module-app.sh
rename to core-java-modules/core-java-9-jigsaw/run-simple-module-app.sh
diff --git a/core-java-modules/core-java-9/run-student-client.bat b/core-java-modules/core-java-9-jigsaw/run-student-client.bat
similarity index 100%
rename from core-java-modules/core-java-9/run-student-client.bat
rename to core-java-modules/core-java-9-jigsaw/run-student-client.bat
diff --git a/core-java-modules/core-java-9/run-student-client.sh b/core-java-modules/core-java-9-jigsaw/run-student-client.sh
similarity index 100%
rename from core-java-modules/core-java-9/run-student-client.sh
rename to core-java-modules/core-java-9-jigsaw/run-student-client.sh
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.client/module-info.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.client/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.client/module-info.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.client/module-info.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.model/module-info.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.model/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.model/module-info.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.model/module-info.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/module-info.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.student.service/module-info.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.student.service/module-info.java
rename to core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service/module-info.java
diff --git a/core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java b/core-java-modules/core-java-9-jigsaw/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java
similarity index 100%
rename from core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java
rename to core-java-modules/core-java-9-jigsaw/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java
diff --git a/core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java b/core-java-modules/core-java-9-jigsaw/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java
similarity index 100%
rename from core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java
rename to core-java-modules/core-java-9-jigsaw/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java
diff --git a/core-java-modules/core-java-9/src/simple-modules/hello.modules/module-info.java b/core-java-modules/core-java-9-jigsaw/src/simple-modules/hello.modules/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/simple-modules/hello.modules/module-info.java
rename to core-java-modules/core-java-9-jigsaw/src/simple-modules/hello.modules/module-info.java
diff --git a/core-java-modules/core-java-9/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java b/core-java-modules/core-java-9-jigsaw/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java
similarity index 100%
rename from core-java-modules/core-java-9/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java
rename to core-java-modules/core-java-9-jigsaw/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java
diff --git a/core-java-modules/core-java-9/src/simple-modules/main.app/module-info.java b/core-java-modules/core-java-9-jigsaw/src/simple-modules/main.app/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/simple-modules/main.app/module-info.java
rename to core-java-modules/core-java-9-jigsaw/src/simple-modules/main.app/module-info.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java b/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java
rename to core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java
diff --git a/core-java-modules/core-java-9-new-features/README.md b/core-java-modules/core-java-9-new-features/README.md
new file mode 100644
index 0000000000..d547b9a221
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/README.md
@@ -0,0 +1,14 @@
+## Core Java 9
+
+This module contains articles about core Java features that have been introduced in Java 9.
+
+### Relevant Articles:
+
+- [Java 9 New Features](https://www.baeldung.com/new-java-9)
+- [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles)
+- [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client)
+- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar)
+- [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation)
+- [Introduction to Java 9 StackWalking API](https://www.baeldung.com/java-9-stackwalking-api)
+- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
+- [Java 9 Reactive Streams](https://www.baeldung.com/java-9-reactive-streams)
diff --git a/core-java-modules/core-java-9/compile-aot.sh b/core-java-modules/core-java-9-new-features/compile-aot.sh
similarity index 100%
rename from core-java-modules/core-java-9/compile-aot.sh
rename to core-java-modules/core-java-9-new-features/compile-aot.sh
diff --git a/core-java-modules/core-java-9/compile-httpclient.bat b/core-java-modules/core-java-9-new-features/compile-httpclient.bat
similarity index 100%
rename from core-java-modules/core-java-9/compile-httpclient.bat
rename to core-java-modules/core-java-9-new-features/compile-httpclient.bat
diff --git a/core-java-modules/core-java-9/compile-modules.sh b/core-java-modules/core-java-9-new-features/compile-modules.sh
similarity index 100%
rename from core-java-modules/core-java-9/compile-modules.sh
rename to core-java-modules/core-java-9-new-features/compile-modules.sh
diff --git a/core-java-modules/core-java-9/logging.sh b/core-java-modules/core-java-9-new-features/logging.sh
similarity index 100%
rename from core-java-modules/core-java-9/logging.sh
rename to core-java-modules/core-java-9-new-features/logging.sh
diff --git a/core-java-modules/core-java-9/mods/logback.xml b/core-java-modules/core-java-9-new-features/mods/logback.xml
similarity index 100%
rename from core-java-modules/core-java-9/mods/logback.xml
rename to core-java-modules/core-java-9-new-features/mods/logback.xml
diff --git a/core-java-modules/core-java-9-new-features/pom.xml b/core-java-modules/core-java-9-new-features/pom.xml
new file mode 100644
index 0000000000..cfdbb285d4
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/pom.xml
@@ -0,0 +1,60 @@
+
+ 4.0.0
+ core-java-9-new-features
+ 0.2-SNAPSHOT
+ core-java-9
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+
+
+ core-java-9-new-features
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+
+
+
+
+ apache.snapshots
+ http://repository.apache.org/snapshots/
+
+
+
+
+
+ 3.10.0
+ 1.2.0
+ 1.9
+ 1.9
+
+
+
diff --git a/core-java-modules/core-java-9/run-aot.sh b/core-java-modules/core-java-9-new-features/run-aot.sh
similarity index 100%
rename from core-java-modules/core-java-9/run-aot.sh
rename to core-java-modules/core-java-9-new-features/run-aot.sh
diff --git a/core-java-modules/core-java-9/run-httpclient.bat b/core-java-modules/core-java-9-new-features/run-httpclient.bat
similarity index 100%
rename from core-java-modules/core-java-9/run-httpclient.bat
rename to core-java-modules/core-java-9-new-features/run-httpclient.bat
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/language/PrivateInterface.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/language/PrivateInterface.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/multireleaseapp/App.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/multireleaseapp/App.java
diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/multireleaseapp/DateHelper.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java
rename to core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/multireleaseapp/DateHelper.java
diff --git a/core-java-modules/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java b/core-java-modules/core-java-9-new-features/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java
similarity index 100%
rename from core-java-modules/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java
rename to core-java-modules/core-java-9-new-features/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/module-info.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.httpclient/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/module-info.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.httpclient/module-info.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/module-info.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.app/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/module-info.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.app/module-info.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.slf4j/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging.slf4j/module-info.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java
diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging/module-info.java b/core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging/module-info.java
similarity index 100%
rename from core-java-modules/core-java-9/src/modules/com.baeldung.logging/module-info.java
rename to core-java-modules/core-java-9-new-features/src/modules/com.baeldung.logging/module-info.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java
diff --git a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java
similarity index 100%
rename from core-java-modules/core-java-9/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java
diff --git a/core-java-modules/core-java-9/.gitignore b/core-java-modules/core-java-9/.gitignore
deleted file mode 100644
index 83c05e60c8..0000000000
--- a/core-java-modules/core-java-9/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-*.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/core-java-modules/core-java-9/README.md b/core-java-modules/core-java-9/README.md
index f4939ae1e1..94f480db67 100644
--- a/core-java-modules/core-java-9/README.md
+++ b/core-java-modules/core-java-9/README.md
@@ -4,28 +4,13 @@ This module contains articles about Java 9 core features
### Relevant Articles:
-- [Java 9 New Features](https://www.baeldung.com/new-java-9)
-- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors)
-- [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity)
-- [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles)
-- [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client)
- [Method Handles in Java](http://www.baeldung.com/java-method-handles)
- [Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue)
- [Optional orElse Optional](http://www.baeldung.com/java-optional-or-else-optional)
- [Iterate Through a Range of Dates in Java](https://www.baeldung.com/java-iterate-date-range)
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set)
-- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar)
-- [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation)
-- [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api)
-- [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new)
-- [Java 9 Reactive Streams](https://www.baeldung.com/java-9-reactive-streams)
-- [Java 9 Optional API Additions](https://www.baeldung.com/java-9-optional)
-- [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture)
-- [Introduction to Java 9 StackWalking API](https://www.baeldung.com/java-9-stackwalking-api)
-- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods)
-- [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api)
-- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity)
-- [Java 9 java.lang.Module API](https://www.baeldung.com/java-9-module-api)
-- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
- [Filtering a Stream of Optionals in Java](https://www.baeldung.com/java-filter-stream-of-optional)
+
+Note: also contains part of the code for the article
+[How to Filter a Collection in Java](https://www.baeldung.com/java-collection-filtering).
diff --git a/core-java-modules/core-java-9/src/main/java/.gitignore b/core-java-modules/core-java-9/src/main/java/.gitignore
deleted file mode 100644
index 83c05e60c8..0000000000
--- a/core-java-modules/core-java-9/src/main/java/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-*.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/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/README.MD b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/README.MD
deleted file mode 100644
index 2f44a2336b..0000000000
--- a/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/README.MD
+++ /dev/null
@@ -1,2 +0,0 @@
-### Relevant Artiles:
-- [Filtering a Stream of Optionals in Java](http://www.baeldung.com/java-filter-stream-of-optional)
diff --git a/core-java-modules/core-java-io/README.md b/core-java-modules/core-java-io/README.md
index 34b2f371e1..2a68e861e8 100644
--- a/core-java-modules/core-java-io/README.md
+++ b/core-java-modules/core-java-io/README.md
@@ -13,22 +13,11 @@ This module contains articles about core Java input and output (IO)
- [Differences Between the Java WatchService API and the Apache Commons IO Monitor Library](http://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library)
- [File Size in Java](http://www.baeldung.com/java-file-size)
- [Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java](http://www.baeldung.com/java-path)
-- [Using Java MappedByteBuffer](http://www.baeldung.com/java-mapped-byte-buffer)
- [How to Copy a File with Java](http://www.baeldung.com/java-copy-file)
- [Java – Append Data to a File](http://www.baeldung.com/java-append-to-file)
- [FileNotFoundException in Java](http://www.baeldung.com/java-filenotfound-exception)
- [How to Read a File in Java](http://www.baeldung.com/reading-file-in-java)
-- [A Guide To NIO2 Asynchronous File Channel](http://www.baeldung.com/java-nio2-async-file-channel)
-- [A Guide To NIO2 FileVisitor](http://www.baeldung.com/java-nio2-file-visitor)
-- [A Guide To NIO2 File Attribute APIs](http://www.baeldung.com/java-nio2-file-attribute)
-- [Introduction to the Java NIO2 File API](http://www.baeldung.com/java-nio-2-file-api)
- [Zipping and Unzipping in Java](http://www.baeldung.com/java-compress-and-uncompress)
-- [Java NIO2 Path API](http://www.baeldung.com/java-nio-2-path)
-- [A Guide to WatchService in Java NIO2](http://www.baeldung.com/java-nio2-watchservice)
-- [Guide to Java NIO2 Asynchronous Channel APIs](http://www.baeldung.com/java-nio-2-async-channels)
-- [A Guide to NIO2 Asynchronous Socket Channel](http://www.baeldung.com/java-nio2-async-socket-channel)
-- [Download a File From an URL in Java](http://www.baeldung.com/java-download-file)
-- [Create a Symbolic Link with Java](http://www.baeldung.com/java-symlink)
- [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter)
- [Read a File into an ArrayList](https://www.baeldung.com/java-file-to-arraylist)
- [Guide to Java OutputStream](https://www.baeldung.com/java-outputstream)
@@ -40,6 +29,5 @@ This module contains articles about core Java input and output (IO)
- [How to Write to a CSV File in Java](https://www.baeldung.com/java-csv)
- [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files)
- [Java InputStream to Byte Array and ByteBuffer](https://www.baeldung.com/convert-input-stream-to-array-of-bytes)
-- [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector)
- [How to Avoid the Java FileNotFoundException When Loading Resources](https://www.baeldung.com/java-classpath-resource-cannot-be-opened)
- [[More -->]](/core-java-modules/core-java-io-2)
diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml
index 3478f71286..393ab5e318 100644
--- a/core-java-modules/core-java-io/pom.xml
+++ b/core-java-modules/core-java-io/pom.xml
@@ -27,12 +27,6 @@
${hsqldb.version}
runtime
-
-
- org.asynchttpclient
- async-http-client
- ${async-http-client.version}
-
com.opencsv
opencsv
@@ -155,7 +149,6 @@
3.0.0-M1
2.4.0
- 2.4.5
1.18
0.1.5
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md
deleted file mode 100644
index b28aae1397..0000000000
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-###Relevant Articles:
-- [Introduction to the Java NIO Selector](http://www.baeldung.com/java-nio-selector)
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java
deleted file mode 100644
index 6964ba80e3..0000000000
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.baeldung.filechannel;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.nio.charset.StandardCharsets;
-
-import org.junit.Test;
-
-public class FileChannelUnitTest {
-
- @Test
- public void givenFile_whenReadWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException {
-
- try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
- FileChannel channel = reader.getChannel();
- ByteArrayOutputStream out = new ByteArrayOutputStream();) {
-
- int bufferSize = 1024;
- if (bufferSize > channel.size()) {
- bufferSize = (int) channel.size();
- }
- ByteBuffer buff = ByteBuffer.allocate(bufferSize);
-
- while (channel.read(buff) > 0) {
- out.write(buff.array(), 0, buff.position());
- buff.clear();
- }
-
- String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);
-
- assertEquals("Hello world", fileContent);
- }
- }
-
- @Test
- public void givenFile_whenReadWithFileChannelUsingFileInputStream_thenCorrect() throws IOException {
-
- try (ByteArrayOutputStream out = new ByteArrayOutputStream();
- FileInputStream fin = new FileInputStream("src/test/resources/test_read.in");
- FileChannel channel = fin.getChannel();) {
-
- int bufferSize = 1024;
- if (bufferSize > channel.size()) {
- bufferSize = (int) channel.size();
- }
- ByteBuffer buff = ByteBuffer.allocate(bufferSize);
-
- while (channel.read(buff) > 0) {
- out.write(buff.array(), 0, buff.position());
- buff.clear();
- }
- String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);
-
- assertEquals("Hello world", fileContent);
- }
- }
-
- @Test
- public void givenFile_whenReadAFileSectionIntoMemoryWithFileChannel_thenCorrect() throws IOException {
-
- try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
- FileChannel channel = reader.getChannel();
- ByteArrayOutputStream out = new ByteArrayOutputStream();) {
-
- MappedByteBuffer buff = channel.map(FileChannel.MapMode.READ_ONLY, 6, 5);
-
- if (buff.hasRemaining()) {
- byte[] data = new byte[buff.remaining()];
- buff.get(data);
- assertEquals("world", new String(data, StandardCharsets.UTF_8));
- }
- }
- }
-
- @Test
- public void whenWriteWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException {
- String file = "src/test/resources/test_write_using_filechannel.txt";
- try (RandomAccessFile writer = new RandomAccessFile(file, "rw");
- FileChannel channel = writer.getChannel();) {
- ByteBuffer buff = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.UTF_8));
-
- channel.write(buff);
-
- // now we verify whether the file was written correctly
- RandomAccessFile reader = new RandomAccessFile(file, "r");
- assertEquals("Hello world", reader.readLine());
- reader.close();
- }
- }
-
- @Test
- public void givenFile_whenWriteAFileUsingLockAFileSectionWithFileChannel_thenCorrect() throws IOException {
- try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "rw");
- FileChannel channel = reader.getChannel();
- FileLock fileLock = channel.tryLock(6, 5, Boolean.FALSE);) {
-
- assertNotNull(fileLock);
- }
- }
-
- @Test
- public void givenFile_whenReadWithFileChannelGetPosition_thenCorrect() throws IOException {
-
- try (ByteArrayOutputStream out = new ByteArrayOutputStream();
- RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
- FileChannel channel = reader.getChannel();) {
-
- int bufferSize = 1024;
- if (bufferSize > channel.size()) {
- bufferSize = (int) channel.size();
- }
- ByteBuffer buff = ByteBuffer.allocate(bufferSize);
-
- while (channel.read(buff) > 0) {
- out.write(buff.array(), 0, buff.position());
- buff.clear();
- }
-
- // the original file is 11 bytes long, so that's where the position pointer should be
- assertEquals(11, channel.position());
-
- channel.position(4);
- assertEquals(4, channel.position());
- }
- }
-
- @Test
- public void whenGetFileSize_thenCorrect() throws IOException {
-
- try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
- FileChannel channel = reader.getChannel();) {
-
- // the original file is 11 bytes long, so that's where the position pointer should be
- assertEquals(11, channel.size());
- }
- }
-
- @Test
- public void whenTruncateFile_thenCorrect() throws IOException {
- String input = "this is a test input";
-
- FileOutputStream fout = new FileOutputStream("src/test/resources/test_truncate.txt");
- FileChannel channel = fout.getChannel();
-
- ByteBuffer buff = ByteBuffer.wrap(input.getBytes());
- channel.write(buff);
- buff.flip();
-
- channel = channel.truncate(5);
- assertEquals(5, channel.size());
-
- fout.close();
- channel.close();
- }
-}
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/README.md b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/README.md
deleted file mode 100644
index 569be82d27..0000000000
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-### Relevant Articles:
-- [Introduction to the Java NIO2 File API](http://www.baeldung.com/java-nio-2-file-api)
-- [Java NIO2 Path API](http://www.baeldung.com/java-nio-2-path)
-- [A Guide To NIO2 Asynchronous File Channel](http://www.baeldung.com/java-nio2-async-file-channel)
-- [Guide to Selenium with JUnit / TestNG](http://www.baeldung.com/java-selenium-with-junit-and-testng)
-- [A Guide to NIO2 Asynchronous Socket Channel](http://www.baeldung.com/java-nio2-async-socket-channel)
-- [A Guide To NIO2 FileVisitor](http://www.baeldung.com/java-nio2-file-visitor)
-- [A Guide To NIO2 File Attribute APIs](http://www.baeldung.com/java-nio2-file-attribute)
-- [How to use the Spring FactoryBean?](http://www.baeldung.com/spring-factorybean)
-- [A Guide to WatchService in Java NIO2](http://www.baeldung.com/java-nio2-watchservice)
-- [Guide to Java NIO2 Asynchronous Channel APIs](http://www.baeldung.com/java-nio-2-async-channels)
diff --git a/core-java-modules/core-java-io/src/test/resources/test_truncate.txt b/core-java-modules/core-java-io/src/test/resources/test_truncate.txt
deleted file mode 100644
index 26d3b38cdd..0000000000
--- a/core-java-modules/core-java-io/src/test/resources/test_truncate.txt
+++ /dev/null
@@ -1 +0,0 @@
-this
\ No newline at end of file
diff --git a/core-java-modules/core-java-io/src/test/resources/test_write_using_filechannel.txt b/core-java-modules/core-java-io/src/test/resources/test_write_using_filechannel.txt
deleted file mode 100644
index 70c379b63f..0000000000
--- a/core-java-modules/core-java-io/src/test/resources/test_write_using_filechannel.txt
+++ /dev/null
@@ -1 +0,0 @@
-Hello world
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-3/README.md b/core-java-modules/core-java-lang-oop-3/README.md
index f8efcb737f..69fb4f5d28 100644
--- a/core-java-modules/core-java-lang-oop-3/README.md
+++ b/core-java-modules/core-java-lang-oop-3/README.md
@@ -15,4 +15,4 @@ This module contains articles about Object-oriented programming (OOP) in Java
- [Java Interfaces](https://www.baeldung.com/java-interfaces)
- [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding)
- [Methods in Java](https://www.baeldung.com/java-methods)
-- [[<-- Prev]](/core-java-modules/core-java-lang-oop-2)
+- [[<-- Prev]](/core-java-modules/core-java-lang-oop-2) [[More -->]](/core-java-modules/core-java-lang-oop-4)
diff --git a/core-java-modules/core-java-lang-oop-4/README.md b/core-java-modules/core-java-lang-oop-4/README.md
new file mode 100644
index 0000000000..fae5b3091b
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-4/README.md
@@ -0,0 +1,6 @@
+## Core Java Lang OOP (Part 4)
+
+This module contains articles about Object-oriented programming (OOP) in Java
+
+### Relevant Articles:
+- [[<-- Prev]](/core-java-modules/core-java-lang-oop-3)
diff --git a/core-java-modules/core-java-lang-oop-4/pom.xml b/core-java-modules/core-java-lang-oop-4/pom.xml
new file mode 100644
index 0000000000..72662a8ea4
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-4/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+ core-java-lang-oop-4
+ 0.1.0-SNAPSHOT
+ core-java-lang-oop-4
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+ org.slf4j
+ log4j-over-slf4j
+ ${org.slf4j.version}
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+ com.h2database
+ h2
+ ${h2.version}
+ test
+
+
+
+
+ core-java-lang-oop-4
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ 3.10.0
+
+
+
diff --git a/core-java-modules/core-java-lang-oop-4/src/main/java/com/baeldung/strictfpUsage/Circle.java b/core-java-modules/core-java-lang-oop-4/src/main/java/com/baeldung/strictfpUsage/Circle.java
new file mode 100644
index 0000000000..a1f08d1bff
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-4/src/main/java/com/baeldung/strictfpUsage/Circle.java
@@ -0,0 +1,5 @@
+package com.baeldung.strictfpUsage;
+
+public strictfp interface Circle {
+ double computeArea(double radius);
+}
diff --git a/core-java-modules/core-java-lang-oop-4/src/main/java/com/baeldung/strictfpUsage/ScientificCalculator.java b/core-java-modules/core-java-lang-oop-4/src/main/java/com/baeldung/strictfpUsage/ScientificCalculator.java
new file mode 100644
index 0000000000..b898c3da3e
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-4/src/main/java/com/baeldung/strictfpUsage/ScientificCalculator.java
@@ -0,0 +1,12 @@
+package com.baeldung.strictfpUsage;
+
+public strictfp class ScientificCalculator {
+
+ public double sum(double value1, double value2) {
+ return value1 + value2;
+ }
+
+ public double diff(double value1, double value2) {
+ return value1 - value2;
+ }
+}
diff --git a/core-java-modules/core-java-lang-oop-4/src/test/java/com/baeldung/strictfpUsage/ScientificCalculatorUnitTest.java b/core-java-modules/core-java-lang-oop-4/src/test/java/com/baeldung/strictfpUsage/ScientificCalculatorUnitTest.java
new file mode 100644
index 0000000000..775c75ca9d
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-4/src/test/java/com/baeldung/strictfpUsage/ScientificCalculatorUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.strictfpUsage;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ScientificCalculatorUnitTest {
+
+ @Test
+ public void whenMethodOfstrictfpClassInvoked_thenIdenticalResultOnAllPlatforms() {
+ ScientificCalculator calculator = new ScientificCalculator();
+ double result = calculator.sum(23e10, 98e17);
+ assertThat(result, is(9.800000230000001E18));
+ result = calculator.diff(Double.MAX_VALUE, 1.56);
+ assertThat(result, is(1.7976931348623157E308));
+ }
+}
diff --git a/core-java-modules/core-java-networking-2/README.md b/core-java-modules/core-java-networking-2/README.md
index 7dc33b5e11..120b111ff5 100644
--- a/core-java-modules/core-java-networking-2/README.md
+++ b/core-java-modules/core-java-networking-2/README.md
@@ -4,10 +4,11 @@ This module contains articles about networking in Java
### Relevant Articles
-- [Checking if a URL Exists in Java](https://www.baeldung.com/java-check-url-exists)
-- [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post)
+- [Checking If a URL Exists in Java](https://www.baeldung.com/java-check-url-exists)
+- [Making a JSON POST Request with HttpURLConnection](https://www.baeldung.com/httpurlconnection-post)
- [Using Curl in Java](https://www.baeldung.com/java-curl)
-- [Do a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request)
-- [Sending Emails with Java](http://www.baeldung.com/java-email)
+- [Do a Simple HTTP Request in Java](https://www.baeldung.com/java-http-request)
+- [Sending Emails with Java](https://www.baeldung.com/java-email)
- [Authentication with HttpUrlConnection](https://www.baeldung.com/java-http-url-connection)
+- [Download a File from an URL in Java](https://www.baeldung.com/java-download-file)
- [[<-- Prev]](/core-java-modules/core-java-networking)
diff --git a/core-java-modules/core-java-networking-2/pom.xml b/core-java-modules/core-java-networking-2/pom.xml
index 2d404a553b..c3a5891066 100644
--- a/core-java-modules/core-java-networking-2/pom.xml
+++ b/core-java-modules/core-java-networking-2/pom.xml
@@ -6,9 +6,10 @@
jar
- com.baeldung.core-java-modules
- core-java-modules
- 1.0.0-SNAPSHOT
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
@@ -27,6 +28,11 @@
mail
${javax.mail.version}
+
+ org.asynchttpclient
+ async-http-client
+ ${async-http-client.version}
+
@@ -36,5 +42,6 @@
4.5.9
1.5.0-b01
+ 2.4.5
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/download/FileDownload.java b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/download/FileDownload.java
similarity index 99%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/download/FileDownload.java
rename to core-java-modules/core-java-networking-2/src/main/java/com/baeldung/download/FileDownload.java
index a099406d4c..ebcf7a70f7 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/download/FileDownload.java
+++ b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/download/FileDownload.java
@@ -4,7 +4,7 @@ import org.apache.commons.io.FileUtils;
import org.asynchttpclient.*;
import java.io.*;
-import java.net.*;
+import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/download/ResumableDownload.java b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/download/ResumableDownload.java
similarity index 100%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/download/ResumableDownload.java
rename to core-java-modules/core-java-networking-2/src/main/java/com/baeldung/download/ResumableDownload.java
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java
similarity index 98%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java
rename to core-java-modules/core-java-networking-2/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java
index 81ac391958..16017ee482 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java
+++ b/core-java-modules/core-java-networking-2/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java
@@ -1,8 +1,10 @@
package com.baeldung.download;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
@@ -11,11 +13,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutionException;
-import javax.xml.bind.DatatypeConverter;
-
-import org.junit.After;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static org.junit.Assert.assertTrue;
public class FileDownloadIntegrationTest {
diff --git a/core-java-modules/core-java-nio-2/README.md b/core-java-modules/core-java-nio-2/README.md
new file mode 100644
index 0000000000..8b29c97385
--- /dev/null
+++ b/core-java-modules/core-java-nio-2/README.md
@@ -0,0 +1,11 @@
+## Core Java NIO
+
+This module contains articles about core Java non-blocking input and output (IO)
+
+## Relevant Articles:
+
+- [A Guide to WatchService in Java NIO2](https://www.baeldung.com/java-nio2-watchservice)
+- [Create a Symbolic Link with Java](https://www.baeldung.com/java-symlink)
+- [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector)
+- [Using Java MappedByteBuffer](https://www.baeldung.com/java-mapped-byte-buffer)
+- [[<-- Prev]](/core-java-modules/core-java-nio)
\ No newline at end of file
diff --git a/core-java-modules/core-java-nio-2/pom.xml b/core-java-modules/core-java-nio-2/pom.xml
new file mode 100644
index 0000000000..c1fa423b38
--- /dev/null
+++ b/core-java-modules/core-java-nio-2/pom.xml
@@ -0,0 +1,17 @@
+
+ 4.0.0
+ core-java-nio-2
+ 0.1.0-SNAPSHOT
+ core-java-nio-2
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/selector/EchoClient.java
similarity index 96%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java
rename to core-java-modules/core-java-nio-2/src/main/java/com/baeldung/selector/EchoClient.java
index 61f339db58..dd0a15ac7e 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java
+++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/selector/EchoClient.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio.selector;
+package com.baeldung.selector;
import java.io.IOException;
import java.net.InetSocketAddress;
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/selector/EchoServer.java
similarity index 98%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java
rename to core-java-modules/core-java-nio-2/src/main/java/com/baeldung/selector/EchoServer.java
index 7c1e291646..8cf2e941fe 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java
+++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/selector/EchoServer.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio.selector;
+package com.baeldung.selector;
import java.io.File;
import java.io.IOException;
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/symlink/SymLinkExample.java
similarity index 93%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java
rename to core-java-modules/core-java-nio-2/src/main/java/com/baeldung/symlink/SymLinkExample.java
index 63ee0f14b1..4c2c47e085 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java
+++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/symlink/SymLinkExample.java
@@ -6,9 +6,11 @@ import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import static java.nio.file.StandardOpenOption.*;
import java.util.stream.IntStream;
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+
public class SymLinkExample {
public void createSymbolicLink(Path link, Path target) throws IOException {
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/watcher/DirectoryWatcherExample.java
similarity index 74%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java
rename to core-java-modules/core-java-nio-2/src/main/java/com/baeldung/watcher/DirectoryWatcherExample.java
index 4c35ffdb22..e8a2a401ab 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java
+++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/watcher/DirectoryWatcherExample.java
@@ -1,13 +1,7 @@
-package com.baeldung.java.nio2.watcher;
+package com.baeldung.watcher;
import java.io.IOException;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardWatchEventKinds;
-import java.nio.file.WatchEvent;
-import java.nio.file.WatchKey;
-import java.nio.file.WatchService;
+import java.nio.file.*;
public class DirectoryWatcherExample {
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java
rename to core-java-modules/core-java-nio-2/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/selector/NioEchoLiveTest.java
similarity index 87%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java
rename to core-java-modules/core-java-nio-2/src/test/java/com/baeldung/selector/NioEchoLiveTest.java
index 0e1afa87a5..39deb798e5 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java
+++ b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/selector/NioEchoLiveTest.java
@@ -1,13 +1,15 @@
-package com.baeldung.java.nio.selector;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
+package com.baeldung.selector;
+import com.baeldung.selector.EchoClient;
+import com.baeldung.selector.EchoServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
public class NioEchoLiveTest {
private Process server;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java
similarity index 100%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java
rename to core-java-modules/core-java-nio-2/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java
index caa7049475..e6723e719c 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java
+++ b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java
@@ -1,13 +1,13 @@
package com.baeldung.symlink;
-import static org.junit.Assert.*;
+import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import org.junit.Test;
+import static org.junit.Assert.*;
public class SymLinkExampleManualTest {
diff --git a/core-java-modules/core-java-io/src/test/resources/fileToRead.txt b/core-java-modules/core-java-nio-2/src/test/resources/fileToRead.txt
similarity index 100%
rename from core-java-modules/core-java-io/src/test/resources/fileToRead.txt
rename to core-java-modules/core-java-nio-2/src/test/resources/fileToRead.txt
diff --git a/core-java-modules/core-java-io/src/test/resources/fileToWriteTo.txt b/core-java-modules/core-java-nio-2/src/test/resources/fileToWriteTo.txt
similarity index 100%
rename from core-java-modules/core-java-io/src/test/resources/fileToWriteTo.txt
rename to core-java-modules/core-java-nio-2/src/test/resources/fileToWriteTo.txt
diff --git a/core-java-modules/core-java-nio/README.md b/core-java-modules/core-java-nio/README.md
index 0683439b86..b64a436957 100644
--- a/core-java-modules/core-java-nio/README.md
+++ b/core-java-modules/core-java-nio/README.md
@@ -6,3 +6,12 @@ This module contains articles about core Java non-blocking input and output (IO)
- [Determine File Creation Date in Java](https://www.baeldung.com/java-file-creation-date)
- [Find the Number of Lines in a File Using Java](https://www.baeldung.com/java-file-number-of-lines)
+- [A Guide to NIO2 Asynchronous File Channel](https://www.baeldung.com/java-nio2-async-file-channel)
+- [A Guide to NIO2 FileVisitor](https://www.baeldung.com/java-nio2-file-visitor)
+- [Guide to Java FileChannel](https://www.baeldung.com/java-filechannel)
+- [A Guide to NIO2 File Attribute APIs](https://www.baeldung.com/java-nio2-file-attribute)
+- [Introduction to the Java NIO2 File API](https://www.baeldung.com/java-nio-2-file-api)
+- [Java NIO2 Path API](https://www.baeldung.com/java-nio-2-path)
+- [Guide to Java NIO2 Asynchronous Channel APIs](https://www.baeldung.com/java-nio-2-async-channels)
+- [A Guide to NIO2 Asynchronous Socket Channel](https://www.baeldung.com/java-nio2-async-socket-channel)
+- [[More -->]](/core-java-modules/core-java-nio-2)
diff --git a/core-java-modules/core-java-nio/pom.xml b/core-java-modules/core-java-nio/pom.xml
index 31433e632f..da8759a956 100644
--- a/core-java-modules/core-java-nio/pom.xml
+++ b/core-java-modules/core-java-nio/pom.xml
@@ -13,4 +13,5 @@
0.0.1-SNAPSHOT
../../parent-java
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java b/core-java-modules/core-java-nio/src/main/java/com/baeldung/filevisitor/FileSearchExample.java
similarity index 97%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java
rename to core-java-modules/core-java-nio/src/main/java/com/baeldung/filevisitor/FileSearchExample.java
index b1b790f541..b49d6eb570 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java
+++ b/core-java-modules/core-java-nio/src/main/java/com/baeldung/filevisitor/FileSearchExample.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.visitor;
+package com.baeldung.filevisitor;
import java.io.IOException;
import java.nio.file.*;
diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java b/core-java-modules/core-java-nio/src/main/java/com/baeldung/filevisitor/FileVisitorImpl.java
similarity index 94%
rename from core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java
rename to core-java-modules/core-java-nio/src/main/java/com/baeldung/filevisitor/FileVisitorImpl.java
index aa769b5091..d86264720f 100644
--- a/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java
+++ b/core-java-modules/core-java-nio/src/main/java/com/baeldung/filevisitor/FileVisitorImpl.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.visitor;
+package com.baeldung.filevisitor;
import java.io.IOException;
import java.nio.file.FileVisitResult;
diff --git a/core-java-modules/core-java-nio/src/main/java/com/baeldung/file/Main.java b/core-java-modules/core-java-nio/src/main/java/com/baeldung/lines/Main.java
similarity index 62%
rename from core-java-modules/core-java-nio/src/main/java/com/baeldung/file/Main.java
rename to core-java-modules/core-java-nio/src/main/java/com/baeldung/lines/Main.java
index d8800dd881..5aa0968ab9 100644
--- a/core-java-modules/core-java-nio/src/main/java/com/baeldung/file/Main.java
+++ b/core-java-modules/core-java-nio/src/main/java/com/baeldung/lines/Main.java
@@ -1,13 +1,13 @@
-package com.baeldung.file;
+package com.baeldung.lines;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingApacheCommonsIO;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingBufferedReader;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingGoogleGuava;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingLineNumberReader;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFileChannel;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFiles;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFilesReadAllLines;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingScanner;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingApacheCommonsIO;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingBufferedReader;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingGoogleGuava;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingLineNumberReader;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFileChannel;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFiles;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFilesReadAllLines;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingScanner;
public class Main {
diff --git a/core-java-modules/core-java-nio/src/main/java/com/baeldung/file/NumberOfLineFinder.java b/core-java-modules/core-java-nio/src/main/java/com/baeldung/lines/NumberOfLineFinder.java
similarity index 99%
rename from core-java-modules/core-java-nio/src/main/java/com/baeldung/file/NumberOfLineFinder.java
rename to core-java-modules/core-java-nio/src/main/java/com/baeldung/lines/NumberOfLineFinder.java
index 3abf82f3fa..b355295dab 100644
--- a/core-java-modules/core-java-nio/src/main/java/com/baeldung/file/NumberOfLineFinder.java
+++ b/core-java-modules/core-java-nio/src/main/java/com/baeldung/lines/NumberOfLineFinder.java
@@ -1,4 +1,4 @@
-package com.baeldung.file;
+package com.baeldung.lines;
import java.io.BufferedReader;
import java.io.File;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoClient.java
similarity index 98%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoClient.java
index ebab715306..f42f5cdeca 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoClient.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.async;
+package com.baeldung.async;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoIntegrationTest.java
similarity index 95%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoIntegrationTest.java
index 3cfac0e90f..42053cea96 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoIntegrationTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.async;
+package com.baeldung.async;
import org.junit.After;
import org.junit.Before;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoServer.java
similarity index 98%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoServer.java
index 01873b344a..b3f8151b7e 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoServer.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.async;
+package com.baeldung.async;
import java.io.File;
import java.io.IOException;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoServer2.java
similarity index 98%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoServer2.java
index 663fc4f2ed..15b98cbf6e 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/async/AsyncEchoServer2.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.async;
+package com.baeldung.async;
import java.io.File;
import java.io.IOException;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/asyncfilechannel/AsyncFileChannelIntegrationTest.java
similarity index 98%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/asyncfilechannel/AsyncFileChannelIntegrationTest.java
index cf37b92565..68f0afec95 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/asyncfilechannel/AsyncFileChannelIntegrationTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.async;
+package com.baeldung.asyncfilechannel;
import org.junit.Test;
@@ -16,7 +16,7 @@ import java.util.concurrent.Future;
import static org.junit.Assert.assertEquals;
-public class AsyncFileIntegrationTest {
+public class AsyncFileChannelIntegrationTest {
@Test
public void givenPath_whenReadsContentWithFuture_thenCorrect() throws IOException, ExecutionException, InterruptedException {
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/attributes/BasicAttribsIntegrationTest.java
similarity index 98%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/attributes/BasicAttribsIntegrationTest.java
index 4b6302e93c..a1f05d107f 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/attributes/BasicAttribsIntegrationTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2.attributes;
+package com.baeldung.attributes;
import org.junit.BeforeClass;
import org.junit.Test;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/file/FileIntegrationTest.java
similarity index 99%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/file/FileIntegrationTest.java
index d1cf81e4ce..1ae84a4dcf 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/file/FileIntegrationTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.nio2;
+package com.baeldung.file;
import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
diff --git a/core-java-modules/core-java-nio/src/test/java/com/baeldung/file/NumberOfLineFinderUnitTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/lines/NumberOfLineFinderUnitTest.java
similarity index 71%
rename from core-java-modules/core-java-nio/src/test/java/com/baeldung/file/NumberOfLineFinderUnitTest.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/lines/NumberOfLineFinderUnitTest.java
index 40ed6d6bba..661b42accd 100644
--- a/core-java-modules/core-java-nio/src/test/java/com/baeldung/file/NumberOfLineFinderUnitTest.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/lines/NumberOfLineFinderUnitTest.java
@@ -1,13 +1,13 @@
-package com.baeldung.file;
+package com.baeldung.lines;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingApacheCommonsIO;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingBufferedReader;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingGoogleGuava;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingLineNumberReader;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFileChannel;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFiles;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFilesReadAllLines;
-import static com.baeldung.file.NumberOfLineFinder.getTotalNumberOfLinesUsingScanner;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingApacheCommonsIO;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingBufferedReader;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingGoogleGuava;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingLineNumberReader;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFileChannel;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFiles;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFilesReadAllLines;
+import static com.baeldung.lines.NumberOfLineFinder.getTotalNumberOfLinesUsingScanner;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/path/PathManualTest.java
similarity index 97%
rename from core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java
rename to core-java-modules/core-java-nio/src/test/java/com/baeldung/path/PathManualTest.java
index 969dff1da2..7017fd42e7 100644
--- a/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java
+++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/path/PathManualTest.java
@@ -1,8 +1,6 @@
-package com.baeldung.java.nio2;
+package com.baeldung.path;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
import java.io.IOException;
import java.net.URI;
@@ -10,7 +8,7 @@ import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
-import org.junit.Test;
+import static org.junit.Assert.*;
public class PathManualTest {
diff --git a/core-java-modules/core-java-nio/src/test/resources/.gitignore b/core-java-modules/core-java-nio/src/test/resources/.gitignore
deleted file mode 100644
index 83c05e60c8..0000000000
--- a/core-java-modules/core-java-nio/src/test/resources/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-*.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/core-java-modules/core-java-nio/src/test/resources/file.txt b/core-java-modules/core-java-nio/src/test/resources/file.txt
new file mode 100644
index 0000000000..558d8bbf35
--- /dev/null
+++ b/core-java-modules/core-java-nio/src/test/resources/file.txt
@@ -0,0 +1 @@
+baeldung.com
\ No newline at end of file
diff --git a/libraries-3/README.md b/libraries-3/README.md
new file mode 100644
index 0000000000..a6c6b190ab
--- /dev/null
+++ b/libraries-3/README.md
@@ -0,0 +1,9 @@
+## Libraries-3
+
+This module contains articles about various Java libraries.
+These are small libraries that are relatively easy to use and do not require any separate module of their own.
+
+The code examples related to different libraries are each in their own module.
+
+Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-modules) we already have separate modules. Please make sure to have a look at the existing modules in such cases.
+
diff --git a/libraries-3/pom.xml b/libraries-3/pom.xml
new file mode 100644
index 0000000000..214e87287d
--- /dev/null
+++ b/libraries-3/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+ libraries-3
+ libraries-3
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ jboss-public-repository-group
+ JBoss Public Repository Group
+ http://repository.jboss.org/nexus/content/groups/public/
+
+ true
+ never
+
+
+ true
+ daily
+
+
+
+
+
+
+ com.beust
+ jcommander
+ ${jcommander.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+ 1.78
+ 1.18.6
+ UTF-8
+ 1.8
+ 1.8
+
+
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/helloworld/HelloWorldApp.java b/libraries-3/src/main/java/com/baeldung/jcommander/helloworld/HelloWorldApp.java
new file mode 100644
index 0000000000..56a74ecf21
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/helloworld/HelloWorldApp.java
@@ -0,0 +1,37 @@
+package com.baeldung.jcommander.helloworld;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+
+public class HelloWorldApp {
+
+ /*
+ * Execute:
+ * mvn exec:java -Dexec.mainClass=com.baeldung.jcommander.helloworld.HelloWorldApp -q \
+ * -Dexec.args="--name JavaWorld"
+ */
+ public static void main(String[] args) {
+ HelloWorldArgs jArgs = new HelloWorldArgs();
+ JCommander helloCmd = JCommander
+ .newBuilder()
+ .addObject(jArgs)
+ .build();
+
+ helloCmd.parse(args);
+ System.out.println("Hello " + jArgs.getName());
+ }
+}
+
+class HelloWorldArgs {
+
+ @Parameter(
+ names = "--name",
+ description = "User name",
+ required = true
+ )
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/UsageBasedBillingApp.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/UsageBasedBillingApp.java
new file mode 100644
index 0000000000..029e7eed01
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/UsageBasedBillingApp.java
@@ -0,0 +1,23 @@
+package com.baeldung.jcommander.usagebilling;
+
+import com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling;
+
+public class UsageBasedBillingApp {
+
+ /*
+ * Entry-point: invokes the cli passing the command-line args
+ *
+ * Invoking "Submit" sub-command:
+ * mvn exec:java \
+ -Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \
+ -Dexec.args="submit --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 --pricing-type PRE_RATED --timestamp 2019-10-03T10:58:00 --quantity 7 --price 24.56"
+ *
+ * Invoking "Fetch" sub-command:
+ * mvn exec:java \
+ -Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \
+ -Dexec.args="fetch --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 subscriptionPQRMN002 subscriptionPQRMN003 --itemized"
+ */
+ public static void main(String[] args) {
+ new UsageBasedBilling().run(args);
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommand.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommand.java
new file mode 100644
index 0000000000..ea6b18af53
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommand.java
@@ -0,0 +1,67 @@
+package com.baeldung.jcommander.usagebilling.cli;
+
+import com.baeldung.jcommander.usagebilling.cli.splitter.ColonParameterSplitter;
+import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator;
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
+import com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+import lombok.Getter;
+
+import java.util.List;
+
+import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.*;
+import static com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService.getDefault;
+
+@Parameters(
+ commandNames = { FETCH_CMD },
+ commandDescription = "Fetch charges for a customer in the current month, can be itemized or aggregated"
+)
+@Getter
+class FetchCurrentChargesCommand {
+
+ FetchCurrentChargesCommand() {
+ }
+
+ private FetchCurrentChargesService service = getDefault();
+
+ @Parameter(names = "--help", help = true)
+ private boolean help;
+
+ @Parameter(
+ names = { "--customer", "-C" },
+ description = "Id of the Customer who's using the services",
+ validateWith = UUIDValidator.class,
+ order = 1,
+ required = true
+ )
+ private String customerId;
+
+ @Parameter(
+ names = { "--subscription", "-S" },
+ description = "Filter charges for specific subscription Ids, includes all subscriptions if no value is specified",
+ variableArity = true,
+ splitter = ColonParameterSplitter.class,
+ order = 2
+ )
+ private List subscriptionIds;
+
+ @Parameter(
+ names = { "--itemized" },
+ description = "Whether the response should contain breakdown by subscription, only aggregate values are returned by default",
+ order = 3
+ )
+ private boolean itemized;
+
+ void fetch() {
+ CurrentChargesRequest req = CurrentChargesRequest.builder()
+ .customerId(customerId)
+ .subscriptionIds(subscriptionIds)
+ .itemized(itemized)
+ .build();
+
+ CurrentChargesResponse response = service.fetch(req);
+ System.out.println(response);
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommand.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommand.java
new file mode 100644
index 0000000000..d3516b19d3
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommand.java
@@ -0,0 +1,96 @@
+package com.baeldung.jcommander.usagebilling.cli;
+
+import com.baeldung.jcommander.usagebilling.cli.converter.ISO8601TimestampConverter;
+import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator;
+import com.baeldung.jcommander.usagebilling.model.UsageRequest;
+import com.baeldung.jcommander.usagebilling.model.UsageRequest.PricingType;
+import com.baeldung.jcommander.usagebilling.service.SubmitUsageService;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+import lombok.Getter;
+
+import java.math.BigDecimal;
+import java.time.Instant;
+
+import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.*;
+import static com.baeldung.jcommander.usagebilling.service.SubmitUsageService.getDefault;
+
+@Parameters(
+ commandNames = { SUBMIT_CMD },
+ commandDescription = "Submit usage for a given customer and subscription, accepts one usage item"
+)
+@Getter
+class SubmitUsageCommand {
+
+ SubmitUsageCommand() {
+ }
+
+ private SubmitUsageService service = getDefault();
+
+ @Parameter(names = "--help", help = true)
+ private boolean help;
+
+ @Parameter(
+ names = { "--customer", "-C" },
+ description = "Id of the Customer who's using the services",
+ validateWith = UUIDValidator.class,
+ order = 1,
+ required = true
+ )
+ private String customerId;
+
+ @Parameter(
+ names = { "--subscription", "-S" },
+ description = "Id of the Subscription that was purchased",
+ order = 2,
+ required = true
+ )
+ private String subscriptionId;
+
+ @Parameter(
+ names = { "--pricing-type", "-P" },
+ description = "Pricing type of the usage reported",
+ order = 3,
+ required = true
+ )
+ private PricingType pricingType;
+
+ @Parameter(
+ names = { "--quantity" },
+ description = "Used quantity; reported quantity is added over the billing period",
+ order = 3,
+ required = true
+ )
+ private Integer quantity;
+
+ @Parameter(
+ names = { "--timestamp" },
+ description = "Timestamp of the usage event, must lie in the current billing period",
+ converter = ISO8601TimestampConverter.class,
+ order = 4,
+ required = true
+ )
+ private Instant timestamp;
+
+ @Parameter(
+ names = { "--price" },
+ description = "If PRE_RATED, unit price to be applied per unit of usage quantity reported",
+ order = 5
+ )
+ private BigDecimal price;
+
+ void submit() {
+
+ UsageRequest req = UsageRequest.builder()
+ .customerId(customerId)
+ .subscriptionId(subscriptionId)
+ .pricingType(pricingType)
+ .quantity(quantity)
+ .timestamp(timestamp)
+ .price(price)
+ .build();
+
+ String reqId = service.submit(req);
+ System.out.println("Generated Request Id for reference: " + reqId);
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/UsageBasedBilling.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/UsageBasedBilling.java
new file mode 100644
index 0000000000..a531a68644
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/UsageBasedBilling.java
@@ -0,0 +1,80 @@
+package com.baeldung.jcommander.usagebilling.cli;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.ParameterException;
+import com.beust.jcommander.UnixStyleUsageFormatter;
+
+public class UsageBasedBilling {
+
+ static final String SUBMIT_CMD = "submit";
+ static final String FETCH_CMD = "fetch";
+
+ private JCommander jCommander;
+ private SubmitUsageCommand submitUsageCmd;
+ private FetchCurrentChargesCommand fetchChargesCmd;
+
+ public UsageBasedBilling() {
+ this.submitUsageCmd = new SubmitUsageCommand();
+ this.fetchChargesCmd = new FetchCurrentChargesCommand();
+ jCommander = JCommander.newBuilder()
+ .addObject(this)
+ .addCommand(submitUsageCmd)
+ .addCommand(fetchChargesCmd)
+ .build();
+
+ setUsageFormatter(SUBMIT_CMD);
+ setUsageFormatter(FETCH_CMD);
+ }
+
+ public void run(String[] args) {
+ String parsedCmdStr;
+ try {
+ jCommander.parse(args);
+ parsedCmdStr = jCommander.getParsedCommand();
+
+ switch (parsedCmdStr) {
+ case SUBMIT_CMD:
+ if (submitUsageCmd.isHelp()) {
+ getSubCommandHandle(SUBMIT_CMD).usage();
+ }
+ System.out.println("Parsing usage request...");
+ submitUsageCmd.submit();
+ break;
+
+ case FETCH_CMD:
+ if (fetchChargesCmd.isHelp()) {
+ getSubCommandHandle(SUBMIT_CMD).usage();
+ }
+ System.out.println("Preparing fetch query...");
+ fetchChargesCmd.fetch();
+
+ break;
+
+ default:
+ System.err.println("Invalid command: " + parsedCmdStr);
+ }
+ } catch (ParameterException e) {
+ System.err.println(e.getLocalizedMessage());
+ parsedCmdStr = jCommander.getParsedCommand();
+ if (parsedCmdStr != null) {
+ getSubCommandHandle(parsedCmdStr).usage();
+ } else {
+ jCommander.usage();
+ }
+ }
+ }
+
+ private JCommander getSubCommandHandle(String command) {
+ JCommander cmd = jCommander.getCommands().get(command);
+
+ if (cmd == null) {
+ System.err.println("Invalid command: " + command);
+ }
+ return cmd;
+ }
+
+ private void setUsageFormatter(String subCommand) {
+ JCommander cmd = getSubCommandHandle(subCommand);
+ cmd.setUsageFormatter(new UnixStyleUsageFormatter(cmd));
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/converter/ISO8601TimestampConverter.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/converter/ISO8601TimestampConverter.java
new file mode 100644
index 0000000000..e54865a811
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/converter/ISO8601TimestampConverter.java
@@ -0,0 +1,33 @@
+package com.baeldung.jcommander.usagebilling.cli.converter;
+
+import com.beust.jcommander.ParameterException;
+import com.beust.jcommander.converters.BaseConverter;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+import static java.lang.String.format;
+
+public class ISO8601TimestampConverter extends BaseConverter {
+
+ private static final DateTimeFormatter TS_FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss");
+
+ public ISO8601TimestampConverter(String optionName) {
+ super(optionName);
+ }
+
+ @Override
+ public Instant convert(String value) {
+ try {
+ return LocalDateTime
+ .parse(value, TS_FORMATTER)
+ .atOffset(ZoneOffset.UTC)
+ .toInstant();
+ } catch (DateTimeParseException e) {
+ throw new ParameterException(getErrorString(value, format("an ISO-8601 formatted timestamp (%s)", TS_FORMATTER.toString())));
+ }
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/splitter/ColonParameterSplitter.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/splitter/ColonParameterSplitter.java
new file mode 100644
index 0000000000..f24c028123
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/splitter/ColonParameterSplitter.java
@@ -0,0 +1,15 @@
+package com.baeldung.jcommander.usagebilling.cli.splitter;
+
+import com.beust.jcommander.converters.IParameterSplitter;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+public class ColonParameterSplitter implements IParameterSplitter {
+
+ @Override
+ public List split(String value) {
+ return asList(value.split(":"));
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/validator/UUIDValidator.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/validator/UUIDValidator.java
new file mode 100644
index 0000000000..a72912f7d0
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/validator/UUIDValidator.java
@@ -0,0 +1,26 @@
+package com.baeldung.jcommander.usagebilling.cli.validator;
+
+import com.beust.jcommander.IParameterValidator;
+import com.beust.jcommander.ParameterException;
+
+import java.util.regex.Pattern;
+
+public class UUIDValidator implements IParameterValidator {
+
+ private static final String UUID_REGEX =
+ "[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}";
+
+ @Override
+ public void validate(String name, String value) throws ParameterException {
+ if (!isValidUUID(value)) {
+ throw new ParameterException(
+ "String parameter " + value + " is not a valid UUID.");
+ }
+ }
+
+ private boolean isValidUUID(String value) {
+ return Pattern
+ .compile(UUID_REGEX)
+ .matcher(value).matches();
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesRequest.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesRequest.java
new file mode 100644
index 0000000000..93dd7a5732
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesRequest.java
@@ -0,0 +1,16 @@
+package com.baeldung.jcommander.usagebilling.model;
+
+import lombok.*;
+
+import java.util.List;
+
+@NoArgsConstructor(access = AccessLevel.PACKAGE)
+@AllArgsConstructor(access = AccessLevel.PACKAGE)
+@Builder
+@Getter
+public class CurrentChargesRequest {
+
+ private String customerId;
+ private List subscriptionIds;
+ private boolean itemized;
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesResponse.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesResponse.java
new file mode 100644
index 0000000000..865a6e4a3d
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesResponse.java
@@ -0,0 +1,56 @@
+package com.baeldung.jcommander.usagebilling.model;
+
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+
+@NoArgsConstructor(access = AccessLevel.PACKAGE)
+@AllArgsConstructor(access = AccessLevel.PACKAGE)
+@Builder
+@Getter
+public class CurrentChargesResponse {
+
+ private String customerId;
+ private BigDecimal amountDue;
+ private List lineItems;
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb
+ .append("Current Month Charges: {")
+ .append("\n\tcustomer: ")
+ .append(this.customerId)
+ .append("\n\ttotalAmountDue: ")
+ .append(this.amountDue.setScale(2, RoundingMode.HALF_UP))
+ .append("\n\tlineItems: [");
+
+ for (LineItem li : this.lineItems) {
+ sb
+ .append("\n\t\t{")
+ .append("\n\t\t\tsubscription: ")
+ .append(li.subscriptionId)
+ .append("\n\t\t\tamount: ")
+ .append(li.amount.setScale(2, RoundingMode.HALF_UP))
+ .append("\n\t\t\tquantity: ")
+ .append(li.quantity)
+ .append("\n\t\t},");
+ }
+
+ sb.append("\n\t]\n}\n");
+ return sb.toString();
+ }
+
+ @NoArgsConstructor(access = AccessLevel.PACKAGE)
+ @AllArgsConstructor(access = AccessLevel.PACKAGE)
+ @Builder
+ @Getter
+ public static class LineItem {
+
+ private String subscriptionId;
+ private BigDecimal amount;
+ private Integer quantity;
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/UsageRequest.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/UsageRequest.java
new file mode 100644
index 0000000000..2785474acf
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/UsageRequest.java
@@ -0,0 +1,50 @@
+package com.baeldung.jcommander.usagebilling.model;
+
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.Instant;
+
+@NoArgsConstructor(access = AccessLevel.PACKAGE)
+@AllArgsConstructor(access = AccessLevel.PACKAGE)
+@Builder
+@Getter
+public class UsageRequest {
+
+ private String customerId;
+ private String subscriptionId;
+ private PricingType pricingType;
+ private Integer quantity;
+ private BigDecimal price;
+ private Instant timestamp;
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb
+ .append("\nUsage: {")
+ .append("\n\tcustomer: ")
+ .append(this.customerId)
+ .append("\n\tsubscription: ")
+ .append(this.subscriptionId)
+ .append("\n\tquantity: ")
+ .append(this.quantity)
+ .append("\n\ttimestamp: ")
+ .append(this.timestamp)
+ .append("\n\tpricingType: ")
+ .append(this.pricingType);
+
+ if (PricingType.PRE_RATED == this.pricingType) {
+ sb
+ .append("\n\tpreRatedAt: ")
+ .append(this.price);
+ }
+
+ sb.append("\n}\n");
+ return sb.toString();
+ }
+
+ public enum PricingType {
+ PRE_RATED, UNRATED
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultFetchCurrentChargesService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultFetchCurrentChargesService.java
new file mode 100644
index 0000000000..6436d49875
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultFetchCurrentChargesService.java
@@ -0,0 +1,68 @@
+package com.baeldung.jcommander.usagebilling.service;
+
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse.LineItem;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import static java.lang.String.format;
+import static java.util.Arrays.asList;
+import static java.util.Arrays.fill;
+import static java.util.Collections.emptyList;
+import static java.util.concurrent.ThreadLocalRandom.current;
+import static java.util.stream.Collectors.toList;
+
+class DefaultFetchCurrentChargesService implements FetchCurrentChargesService {
+
+ @Override
+ public CurrentChargesResponse fetch(CurrentChargesRequest request) {
+ List subscriptions = request.getSubscriptionIds();
+
+ if (subscriptions == null || subscriptions.isEmpty()) {
+ System.out.println("Fetching ALL charges for customer: " + request.getCustomerId());
+ subscriptions = mockSubscriptions();
+
+ } else {
+ System.out.println(format("Fetching charges for customer: %s and subscriptions: %s", request.getCustomerId(), subscriptions));
+ }
+
+ CurrentChargesResponse charges = mockCharges(request.getCustomerId(), subscriptions, request.isItemized());
+ System.out.println("Fetched charges...");
+ return charges;
+ }
+
+ private CurrentChargesResponse mockCharges(String customerId, List subscriptions, boolean itemized) {
+ List lineItems = mockLineItems(subscriptions);
+ BigDecimal amountDue = lineItems
+ .stream()
+ .map(li -> li.getAmount())
+ .reduce(new BigDecimal("0"), BigDecimal::add);
+
+ return CurrentChargesResponse
+ .builder()
+ .customerId(customerId)
+ .lineItems(itemized ? lineItems : emptyList())
+ .amountDue(amountDue)
+ .build();
+ }
+
+ private List mockLineItems(List subscriptions) {
+ return subscriptions
+ .stream()
+ .map(subscription -> LineItem.builder()
+ .subscriptionId(subscription)
+ .quantity(current().nextInt(20))
+ .amount(new BigDecimal(current().nextDouble(1_000)))
+ .build())
+ .collect(toList());
+ }
+
+ private List mockSubscriptions() {
+ String[] subscriptions = new String[5];
+ fill(subscriptions, UUID.randomUUID().toString());
+ return asList(subscriptions);
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultSubmitUsageService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultSubmitUsageService.java
new file mode 100644
index 0000000000..44ac9e9ed7
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultSubmitUsageService.java
@@ -0,0 +1,16 @@
+package com.baeldung.jcommander.usagebilling.service;
+
+import com.baeldung.jcommander.usagebilling.model.UsageRequest;
+
+import java.util.UUID;
+
+class DefaultSubmitUsageService implements SubmitUsageService {
+
+ @Override
+ public String submit(UsageRequest request) {
+ System.out.println("Submitting usage..." + request);
+
+ System.out.println("Submitted usage successfully...");
+ return UUID.randomUUID().toString();
+ }
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/FetchCurrentChargesService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/FetchCurrentChargesService.java
new file mode 100644
index 0000000000..2cc56658ff
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/FetchCurrentChargesService.java
@@ -0,0 +1,13 @@
+package com.baeldung.jcommander.usagebilling.service;
+
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
+import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
+
+public interface FetchCurrentChargesService {
+
+ static FetchCurrentChargesService getDefault() {
+ return new DefaultFetchCurrentChargesService();
+ }
+
+ CurrentChargesResponse fetch(CurrentChargesRequest request);
+}
diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/SubmitUsageService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/SubmitUsageService.java
new file mode 100644
index 0000000000..2a29e6e474
--- /dev/null
+++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/SubmitUsageService.java
@@ -0,0 +1,12 @@
+package com.baeldung.jcommander.usagebilling.service;
+
+import com.baeldung.jcommander.usagebilling.model.UsageRequest;
+
+public interface SubmitUsageService {
+
+ static SubmitUsageService getDefault() {
+ return new DefaultSubmitUsageService();
+ }
+
+ String submit(UsageRequest request);
+}
diff --git a/libraries-3/src/test/java/com/baeldung/jcommander/helloworld/HelloWorldAppUnitTest.java b/libraries-3/src/test/java/com/baeldung/jcommander/helloworld/HelloWorldAppUnitTest.java
new file mode 100644
index 0000000000..48b3ac2896
--- /dev/null
+++ b/libraries-3/src/test/java/com/baeldung/jcommander/helloworld/HelloWorldAppUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.jcommander.helloworld;
+
+import com.beust.jcommander.JCommander;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class HelloWorldAppUnitTest {
+
+ @Test
+ public void whenJCommanderInvokedWithArgs_thenArgsParsed() {
+
+ HelloWorldArgs jArgs = new HelloWorldArgs();
+ JCommander helloCmd = JCommander
+ .newBuilder()
+ .addObject(jArgs)
+ .build();
+
+ // when
+ String[] argv = new String[] {
+ "--name", "JavaWorld"
+ };
+ helloCmd.parse(argv);
+
+ // then
+ assertEquals("JavaWorld", jArgs.getName());
+ }
+}
diff --git a/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommandUnitTest.java b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommandUnitTest.java
new file mode 100644
index 0000000000..b639661c39
--- /dev/null
+++ b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommandUnitTest.java
@@ -0,0 +1,61 @@
+package com.baeldung.jcommander.usagebilling.cli;
+
+import com.beust.jcommander.JCommander;
+import org.junit.Test;
+
+import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
+import static org.junit.Assert.assertThat;
+
+public class FetchCurrentChargesCommandUnitTest {
+
+ private JCommander jc = JCommander.newBuilder()
+ .addObject(new FetchCurrentChargesCommand())
+ .build();
+
+ @Test
+ public void whenParsedMultipleSubscriptionsParameter_thenParameterSubscriptionsIsPopulated() {
+ FetchCurrentChargesCommand cmd = (FetchCurrentChargesCommand) jc
+ .getObjects()
+ .get(0);
+
+ jc.parse(new String[] {
+ "-C", "cb898e7a-f2a0-46d2-9a09-531f1cee1839",
+ "-S", "subscriptionA001",
+ "-S", "subscriptionA002",
+ "-S", "subscriptionA003",
+ });
+
+ assertThat(cmd.getSubscriptionIds(),
+ contains("subscriptionA001", "subscriptionA002", "subscriptionA003"));
+ }
+
+ @Test
+ public void whenParsedSubscriptionsColonSeparatedParameter_thenParameterSubscriptionsIsPopulated() {
+ FetchCurrentChargesCommand cmd = (FetchCurrentChargesCommand) jc
+ .getObjects()
+ .get(0);
+
+ jc.parse(new String[] {
+ "-C", "cb898e7a-f2a0-46d2-9a09-531f1cee1839",
+ "-S", "subscriptionA001:subscriptionA002:subscriptionA003",
+ });
+
+ assertThat(cmd.getSubscriptionIds(),
+ contains("subscriptionA001", "subscriptionA002", "subscriptionA003"));
+ }
+
+ @Test
+ public void whenParsedSubscriptionsWithVariableArity_thenParameterSubscriptionsIsPopulated() {
+ FetchCurrentChargesCommand cmd = (FetchCurrentChargesCommand) jc
+ .getObjects()
+ .get(0);
+
+ jc.parse(new String[] {
+ "-C", "cb898e7a-f2a0-46d2-9a09-531f1cee1839",
+ "-S", "subscriptionA001", "subscriptionA002", "subscriptionA003",
+ });
+
+ assertThat(cmd.getSubscriptionIds(),
+ contains("subscriptionA001", "subscriptionA002", "subscriptionA003"));
+ }
+}
diff --git a/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommandUnitTest.java b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommandUnitTest.java
new file mode 100644
index 0000000000..d6ce132053
--- /dev/null
+++ b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommandUnitTest.java
@@ -0,0 +1,64 @@
+package com.baeldung.jcommander.usagebilling.cli;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.ParameterException;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SubmitUsageCommandUnitTest {
+
+ private JCommander jc = JCommander.newBuilder()
+ .addObject(new SubmitUsageCommand())
+ .build();
+
+ @Test
+ public void whenParsedCustomerParameter_thenParameterOfTypeStringIsPopulated() {
+ jc.parse(new String[] {
+ "--customer", "cb898e7a-f2a0-46d2-9a09-531f1cee1839",
+ "--subscription", "subscriptionPQRMN001",
+ "--pricing-type", "PRE_RATED",
+ "--timestamp", "2019-10-03T10:58:00",
+ "--quantity", "7",
+ "--price", "24.56"
+ });
+
+ SubmitUsageCommand cmd = (SubmitUsageCommand) jc
+ .getObjects()
+ .get(0);
+ assertEquals("cb898e7a-f2a0-46d2-9a09-531f1cee1839", cmd.getCustomerId());
+ }
+
+ @Test
+ public void whenParsedTimestampParameter_thenParameterOfTypeInstantIsPopulated() {
+ jc.parse(new String[] {
+ "--customer", "cb898e7a-f2a0-46d2-9a09-531f1cee1839",
+ "--subscription", "subscriptionPQRMN001",
+ "--pricing-type", "PRE_RATED",
+ "--timestamp", "2019-10-03T10:58:00",
+ "--quantity", "7",
+ "--price", "24.56"
+ });
+
+ SubmitUsageCommand cmd = (SubmitUsageCommand) jc
+ .getObjects()
+ .get(0);
+ assertEquals("2019-10-03T10:58:00Z", cmd
+ .getTimestamp()
+ .toString());
+ }
+
+ @Test(expected = ParameterException.class)
+ public void whenParsedCustomerIdNotUUID_thenParameterException() {
+ jc.parse(new String[] {
+ "--customer", "customer001",
+ "--subscription", "subscriptionPQRMN001",
+ "--pricing-type", "PRE_RATED",
+ "--timestamp", "2019-10-03T10:58:00",
+ "--quantity", "7",
+ "--price", "24.56"
+ });
+ }
+}
diff --git a/lombok/pom.xml b/lombok/pom.xml
index 2acf9e240d..b67320909e 100644
--- a/lombok/pom.xml
+++ b/lombok/pom.xml
@@ -76,7 +76,7 @@
- 1.18.4
+ 1.18.10
1.0.0.Final
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java
new file mode 100644
index 0000000000..74ae51c040
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java
@@ -0,0 +1,24 @@
+package com.baeldung.lombok.accessors.model;
+
+import java.math.BigDecimal;
+
+public class BasicAccount {
+ String name;
+ BigDecimal balance;
+
+ public BigDecimal getBalance() {
+ return this.balance;
+ }
+
+ public void setBalance(BigDecimal newBalance) {
+ this.balance = newBalance;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String accountName) {
+ this.name = accountName;
+ }
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java
new file mode 100644
index 0000000000..8fa9a2e8aa
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java
@@ -0,0 +1,15 @@
+package com.baeldung.lombok.accessors.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Accessors(chain = true)
+@Getter
+@Setter
+public class ChainedAccount {
+ String name;
+ BigDecimal balance;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java
new file mode 100644
index 0000000000..22e85848bd
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java
@@ -0,0 +1,15 @@
+package com.baeldung.lombok.accessors.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Accessors(fluent = true, chain = true)
+@Getter
+@Setter
+public class ChainedFluentAccount {
+ String name;
+ BigDecimal balance;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java
new file mode 100644
index 0000000000..bc5e6ba70e
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java
@@ -0,0 +1,15 @@
+package com.baeldung.lombok.accessors.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Accessors(fluent = true, chain = false)
+@Getter
+@Setter
+public class FluentAccount {
+ String name;
+ BigDecimal balance;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java
new file mode 100644
index 0000000000..e3e3ae620b
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java
@@ -0,0 +1,16 @@
+package com.baeldung.lombok.accessors.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+
+@Accessors(prefix = {"s", "bd"})
+@Getter
+@Setter
+public class PrefixedAccount {
+ String sName;
+ BigDecimal bdBalance;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java
new file mode 100644
index 0000000000..462a9b41ec
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java
@@ -0,0 +1,15 @@
+package com.baeldung.lombok.accessors.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+@Accessors(prefix = {"s", "bd"}, fluent = true)
+@Getter
+@Setter
+public class PrefixedFluentAccount {
+ String sName;
+ BigDecimal bdBalance;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java
new file mode 100644
index 0000000000..89727fef19
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java
@@ -0,0 +1,13 @@
+package com.baeldung.lombok.accessors.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+public class StandardAccount {
+ String name;
+ BigDecimal balance;
+}
diff --git a/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java
new file mode 100644
index 0000000000..679c7d39ef
--- /dev/null
+++ b/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java
@@ -0,0 +1,72 @@
+package com.baeldung.lombok.accessors;
+
+import com.baeldung.lombok.accessors.model.*;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+import static org.junit.Assert.assertEquals;
+
+public class AccessorsUnitTest {
+
+ @Test
+ public void givenBasicAccount_thenUseBasicAccessors() {
+ BasicAccount account = new BasicAccount();
+ account.setBalance(BigDecimal.TEN);
+ account.setName("Basic Accessors");
+
+ assertEquals(BigDecimal.TEN, account.getBalance());
+ assertEquals("Basic Accessors", account.getName());
+ }
+
+ @Test
+ public void givenFluentAccount_thenUseFluentAccessors() {
+ FluentAccount account = new FluentAccount();
+ account.name("Fluent Account");
+ account.balance(BigDecimal.TEN);
+
+ assertEquals(BigDecimal.TEN, account.balance());
+ assertEquals("Fluent Account", account.name());
+ }
+
+ @Test
+ public void givenChainedAccount_thenUseChainedAccessors() {
+ ChainedAccount account = new ChainedAccount();
+ account.setName("Chained Account").setBalance(BigDecimal.TEN);
+
+ assertEquals(BigDecimal.TEN, account.getBalance());
+ assertEquals("Chained Account", account.getName());
+ }
+
+ @Test
+ public void givenChainedFluentAccount_thenUseChainedFluentAccessors() {
+ ChainedFluentAccount account = new ChainedFluentAccount()
+ .name("Fluent Account")
+ .balance(BigDecimal.TEN);
+
+ assertEquals(BigDecimal.TEN, account.balance());
+ assertEquals("Fluent Account", account.name());
+ }
+
+ @Test
+ public void givenPrefixedAccount_thenRemovePrefixFromAccessors() {
+ PrefixedAccount account = new PrefixedAccount();
+ account.setName("Prefixed Fields");
+ account.setBalance(BigDecimal.TEN);
+
+ assertEquals(BigDecimal.TEN, account.getBalance());
+ assertEquals("Prefixed Fields", account.getName());
+ }
+
+ @Test
+ public void givenPrefixedFluentAccount_thenRemovePrefixFromAccessors() {
+ PrefixedFluentAccount account = new PrefixedFluentAccount();
+ account
+ .name("Prefixed Fluent Fields")
+ .balance(BigDecimal.TEN);
+
+ assertEquals(BigDecimal.TEN, account.balance());
+ assertEquals("Prefixed Fluent Fields", account.name());
+ }
+
+}
diff --git a/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Customer.java b/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Customer.java
new file mode 100644
index 0000000000..5997602205
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Customer.java
@@ -0,0 +1,39 @@
+package com.baeldung.fetchMode;
+
+import org.hibernate.annotations.Fetch;
+import org.hibernate.annotations.FetchMode;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+public class Customer {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @OneToMany(mappedBy = "customer")
+ @Fetch(value = FetchMode.SELECT)
+ private Set orders = new HashSet<>();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Set getOrders() {
+ return orders;
+ }
+
+ public void setOrders(Set orders) {
+ this.orders = orders;
+ }
+}
diff --git a/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Order.java b/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Order.java
new file mode 100644
index 0000000000..c031972830
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Order.java
@@ -0,0 +1,50 @@
+package com.baeldung.fetchMode;
+
+import javax.persistence.*;
+
+@Entity
+public class Order {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+
+ @ManyToOne
+ @JoinColumn(name = "customer_id")
+ private Customer customer;
+
+ public Order() {
+
+ }
+
+ public Order(String name, Customer customer) {
+ this.name = name;
+ this.customer = customer;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Customer getCustomer() {
+ return customer;
+ }
+
+ public void setCustomer(Customer customer) {
+ this.customer = customer;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/pom.xml b/pom.xml
index d2433d11b3..6f980a893a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,3 @@
-
@@ -406,7 +405,7 @@
-->
core-java-modules/core-java-text
core-java-modules/core-java-lambdas
-
+
core-java-modules/core-java-arrays
core-java-modules/core-java-arrays-2
@@ -424,6 +423,7 @@
core-java-modules/core-java-io
core-java-modules/core-java-io-files
core-java-modules/core-java-nio
+ core-java-modules/core-java-nio-2
core-java-modules/core-java-security
core-java-modules/core-java-exceptions
core-java-modules/core-java-lang-syntax
@@ -541,6 +541,7 @@
libraries
libraries-2
+ libraries-3
libraries-data
libraries-data-2
libraries-data-db
@@ -601,8 +602,10 @@
rule-engines
rsocket
- rxjava
- rxjava-2
+ rxjava-core
+ rxjava-observables
+ rxjava-operators
+ rxjava-libraries
software-security/sql-injection-samples
tensorflow-java
@@ -719,10 +722,11 @@
spring-boot-parent
spring-boot-property-exp
spring-boot-security
+ spring-boot-springdoc
spring-boot-testing
spring-boot-vue
spring-caching
- spring-boot-libraries
+ spring-boot-libraries
spring-cloud
@@ -919,6 +923,7 @@
spring-boot-keycloak
spring-boot-mvc
spring-boot-property-exp
+ spring-boot-springdoc
spring-boot-vue
spring-cloud
spring-cloud/spring-cloud-archaius/basic-config
@@ -1177,7 +1182,7 @@
core-java-modules/core-java-time-measurements
-->
core-java-modules/core-java-text
-
+
core-java-modules/core-java-arrays
core-java-modules/core-java-arrays-2
@@ -1195,6 +1200,7 @@
core-java-modules/core-java-io
core-java-modules/core-java-io-files
core-java-modules/core-java-nio
+ core-java-modules/core-java-nio-2
core-java-modules/core-java-security
core-java-modules/core-java-exceptions
core-java-modules/core-java-lang-syntax
@@ -1307,6 +1313,7 @@
libraries
+ libraries-3
libraries-data
libraries-data-2
libraries-data-db
@@ -1365,8 +1372,10 @@
rule-engines
rsocket
- rxjava
- rxjava-2
+ rxjava-core
+ rxjava-observables
+ rxjava-operators
+ rxjava-libraries
oauth2-framework-impl
spf4j
spring-boot-performance
@@ -1461,8 +1470,9 @@
spring-boot-parent
spring-boot-property-exp
spring-boot-security
+ spring-boot-springdoc
spring-boot-vue
- spring-caching
+ spring-caching
spring-cloud
spring-cloud-bus
diff --git a/rxjava-2/README.md b/rxjava-2/README.md
deleted file mode 100644
index 87f606a323..0000000000
--- a/rxjava-2/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-## RxJava
-
-This module contains articles about RxJava.
-
-### Relevant articles:
-
-- [RxJava and Error Handling](https://www.baeldung.com/rxjava-error-handling)
-- [RxJava 2 – Flowable](https://www.baeldung.com/rxjava-2-flowable)
-- [RxJava Maybe](https://www.baeldung.com/rxjava-maybe)
-- [Introduction to RxRelay for RxJava](https://www.baeldung.com/rx-relay)
-- [Combining RxJava Completables](https://www.baeldung.com/rxjava-completable)
-- [Converting Synchronous and Asynchronous APIs to Observables using RxJava2](https://www.baeldung.com/rxjava-apis-to-observables)
-- [RxJava Hooks](https://www.baeldung.com/rxjava-hooks)
-- More articles: [[<-- prev]](/rxjava)
diff --git a/rxjava-2/pom.xml b/rxjava-2/pom.xml
deleted file mode 100644
index 47d16ec8dd..0000000000
--- a/rxjava-2/pom.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
- 4.0.0
- rxjava-2
- rxjava-2
- 1.0-SNAPSHOT
-
-
- com.baeldung
- parent-java
- 0.0.1-SNAPSHOT
- ../parent-java
-
-
-
-
- io.reactivex.rxjava2
- rxjava
- ${rx.java2.version}
-
-
- com.jayway.awaitility
- awaitility
- ${awaitility.version}
-
-
- org.assertj
- assertj-core
- ${assertj.version}
-
-
- com.jakewharton.rxrelay2
- rxrelay
- ${rxrelay.version}
-
-
-
- com.github.akarnokd
- rxjava2-extensions
- ${rxjava2.ext.version}
-
-
-
-
- 3.8.0
- 2.2.2
- 1.7.0
- 2.0.0
- 0.20.4
-
-
\ No newline at end of file
diff --git a/rxjava-core/README.md b/rxjava-core/README.md
new file mode 100644
index 0000000000..2773bd9423
--- /dev/null
+++ b/rxjava-core/README.md
@@ -0,0 +1,16 @@
+## RxJava
+
+This module contains articles about RxJava.
+
+### Relevant articles:
+
+- [Dealing with Backpressure with RxJava](https://www.baeldung.com/rxjava-backpressure)
+- [How to Test RxJava?](https://www.baeldung.com/rxjava-testing)
+- [Introduction to RxJava](https://www.baeldung.com/rx-java)
+- [Schedulers in RxJava](https://www.baeldung.com/rxjava-schedulers)
+- [Difference Between Flatmap and Switchmap in RxJava](https://www.baeldung.com/rxjava-flatmap-switchmap)
+- [RxJava and Error Handling](https://www.baeldung.com/rxjava-error-handling)
+- [RxJava Maybe](https://www.baeldung.com/rxjava-maybe)
+- [Combining RxJava Completables](https://www.baeldung.com/rxjava-completable)
+- [RxJava Hooks](https://www.baeldung.com/rxjava-hooks)
+- More articles: [[next -->]](/rxjava-2)
diff --git a/rxjava-core/pom.xml b/rxjava-core/pom.xml
new file mode 100644
index 0000000000..401ad83808
--- /dev/null
+++ b/rxjava-core/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+ rxjava-core
+ 1.0-SNAPSHOT
+ rxjava-core
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ io.reactivex
+ rxjava
+ ${rx.java.version}
+
+
+ io.reactivex.rxjava2
+ rxjava
+ ${rx.java2.version}
+
+
+ com.jayway.awaitility
+ awaitility
+ ${awaitility.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+
+
+
+
+ 3.8.0
+ 1.2.5
+ 1.7.0
+ 2.2.2
+
+
+
\ No newline at end of file
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ComputeFunction.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ComputeFunction.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/ComputeFunction.java
rename to rxjava-core/src/main/java/com/baeldung/rxjava/ComputeFunction.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java
rename to rxjava-core/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ObservableImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ObservableImpl.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/ObservableImpl.java
rename to rxjava-core/src/main/java/com/baeldung/rxjava/ObservableImpl.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ResourceManagement.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ResourceManagement.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/ResourceManagement.java
rename to rxjava-core/src/main/java/com/baeldung/rxjava/ResourceManagement.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/SingleImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/SingleImpl.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/SingleImpl.java
rename to rxjava-core/src/main/java/com/baeldung/rxjava/SingleImpl.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/SubjectImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/SubjectImpl.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/SubjectImpl.java
rename to rxjava-core/src/main/java/com/baeldung/rxjava/SubjectImpl.java
diff --git a/rxjava-2/src/main/resources/logback.xml b/rxjava-core/src/main/resources/logback.xml
similarity index 100%
rename from rxjava-2/src/main/resources/logback.xml
rename to rxjava-core/src/main/resources/logback.xml
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java
similarity index 96%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java
index b79fa9af22..f71d9e8839 100644
--- a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java
+++ b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java
@@ -1,84 +1,84 @@
-package com.baeldung.rxjava;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.After;
-import org.junit.Test;
-
-import io.reactivex.Observable;
-import io.reactivex.plugins.RxJavaPlugins;
-import io.reactivex.schedulers.Schedulers;
-
-public class RxJavaHooksManualTest {
-
- private boolean initHookCalled = false;
- private boolean hookCalled = false;
-
- @Test
- public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() {
-
- RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> {
- initHookCalled = true;
- return scheduler.call();
- });
-
- RxJavaPlugins.setIoSchedulerHandler((scheduler) -> {
- hookCalled = true;
- return scheduler;
- });
-
- Observable.range(1, 10)
- .map(v -> v * 2)
- .subscribeOn(Schedulers.io())
- .test();
- assertTrue(hookCalled && initHookCalled);
- }
-
- @Test
- public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> {
- initHookCalled = true;
- return scheduler.call();
- });
-
- RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> {
- hookCalled = true;
- return scheduler;
- });
-
- Observable.range(1, 15)
- .map(v -> v * 2)
- .subscribeOn(Schedulers.newThread())
- .test();
- assertTrue(hookCalled && initHookCalled);
- }
-
- @Test
- public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() {
-
- RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> {
- initHookCalled = true;
- return scheduler.call();
- });
-
- RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> {
- hookCalled = true;
- return scheduler;
- });
-
- Observable.range(1, 10)
- .map(v -> v * 2)
- .subscribeOn(Schedulers.single())
- .test();
- assertTrue(hookCalled && initHookCalled);
-
- }
-
- @After
- public void reset() {
- hookCalled = false;
- initHookCalled = false;
- RxJavaPlugins.reset();
- }
-}
+package com.baeldung.rxjava;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Test;
+
+import io.reactivex.Observable;
+import io.reactivex.plugins.RxJavaPlugins;
+import io.reactivex.schedulers.Schedulers;
+
+public class RxJavaHooksManualTest {
+
+ private boolean initHookCalled = false;
+ private boolean hookCalled = false;
+
+ @Test
+ public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() {
+
+ RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> {
+ initHookCalled = true;
+ return scheduler.call();
+ });
+
+ RxJavaPlugins.setIoSchedulerHandler((scheduler) -> {
+ hookCalled = true;
+ return scheduler;
+ });
+
+ Observable.range(1, 10)
+ .map(v -> v * 2)
+ .subscribeOn(Schedulers.io())
+ .test();
+ assertTrue(hookCalled && initHookCalled);
+ }
+
+ @Test
+ public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> {
+ initHookCalled = true;
+ return scheduler.call();
+ });
+
+ RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> {
+ hookCalled = true;
+ return scheduler;
+ });
+
+ Observable.range(1, 15)
+ .map(v -> v * 2)
+ .subscribeOn(Schedulers.newThread())
+ .test();
+ assertTrue(hookCalled && initHookCalled);
+ }
+
+ @Test
+ public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() {
+
+ RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> {
+ initHookCalled = true;
+ return scheduler.call();
+ });
+
+ RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> {
+ hookCalled = true;
+ return scheduler;
+ });
+
+ Observable.range(1, 10)
+ .map(v -> v * 2)
+ .subscribeOn(Schedulers.single())
+ .test();
+ assertTrue(hookCalled && initHookCalled);
+
+ }
+
+ @After
+ public void reset() {
+ hookCalled = false;
+ initHookCalled = false;
+ RxJavaPlugins.reset();
+ }
+}
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java
similarity index 96%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java
index dd4287a4a9..cea6cc70f6 100644
--- a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java
+++ b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java
@@ -1,244 +1,244 @@
-package com.baeldung.rxjava;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.After;
-import org.junit.Test;
-
-import io.reactivex.Completable;
-import io.reactivex.Flowable;
-import io.reactivex.Maybe;
-import io.reactivex.Observable;
-import io.reactivex.Single;
-import io.reactivex.flowables.ConnectableFlowable;
-import io.reactivex.observables.ConnectableObservable;
-import io.reactivex.plugins.RxJavaPlugins;
-import io.reactivex.schedulers.Schedulers;
-
-public class RxJavaHooksUnitTest {
-
- private boolean initHookCalled = false;
- private boolean hookCalled = false;
-
- @Test
- public void givenObservable_whenError_shouldExecuteTheHook() {
- RxJavaPlugins.setErrorHandler(throwable -> {
- hookCalled = true;
- });
-
- Observable.error(new IllegalStateException())
- .subscribe();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenCompletable_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnCompletableAssembly(completable -> {
- hookCalled = true;
- return completable;
- });
- Completable.fromSingle(Single.just(1));
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenCompletable_whenSubscribed_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> {
- hookCalled = true;
- return observer;
- });
-
- Completable.fromSingle(Single.just(1))
- .test();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenObservable_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnObservableAssembly(observable -> {
- hookCalled = true;
- return observable;
- });
-
- Observable.range(1, 10);
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenObservable_whenSubscribed_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> {
- hookCalled = true;
- return observer;
- });
-
- Observable.range(1, 10)
- .test();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> {
- hookCalled = true;
- return connectableObservable;
- });
-
- ConnectableObservable.range(1, 10)
- .publish()
- .connect();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenFlowable_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnFlowableAssembly(flowable -> {
- hookCalled = true;
- return flowable;
- });
-
- Flowable.range(1, 10);
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenFlowable_whenSubscribed_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> {
- hookCalled = true;
- return observer;
- });
-
- Flowable.range(1, 10)
- .test();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> {
- hookCalled = true;
- return connectableFlowable;
- });
-
- ConnectableFlowable.range(1, 10)
- .publish()
- .connect();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenParallel_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> {
- hookCalled = true;
- return parallelFlowable;
- });
-
- Flowable.range(1, 10)
- .parallel();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenMaybe_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnMaybeAssembly(maybe -> {
- hookCalled = true;
- return maybe;
- });
-
- Maybe.just(1);
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenMaybe_whenSubscribed_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> {
- hookCalled = true;
- return observer;
- });
-
- Maybe.just(1)
- .test();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenSingle_whenAssembled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnSingleAssembly(single -> {
- hookCalled = true;
- return single;
- });
-
- Single.just(1);
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenSingle_whenSubscribed_shouldExecuteTheHook() {
-
- RxJavaPlugins.setOnSingleSubscribe((single, observer) -> {
- hookCalled = true;
- return observer;
- });
-
- Single.just(1)
- .test();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() {
-
- RxJavaPlugins.setScheduleHandler((runnable) -> {
- hookCalled = true;
- return runnable;
- });
-
- Observable.range(1, 10)
- .map(v -> v * 2)
- .subscribeOn(Schedulers.single())
- .test();
- hookCalled = false;
- Observable.range(1, 10)
- .map(v -> v * 2)
- .subscribeOn(Schedulers.computation())
- .test();
- assertTrue(hookCalled);
- }
-
- @Test
- public void givenComputationScheduler_whenCalled_shouldExecuteTheHooks() {
-
- RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> {
- initHookCalled = true;
- return scheduler.call();
- });
- RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> {
- hookCalled = true;
- return scheduler;
- });
-
- Observable.range(1, 10)
- .map(v -> v * 2)
- .subscribeOn(Schedulers.computation())
- .test();
- assertTrue(hookCalled && initHookCalled);
- }
-
- @After
- public void reset() {
- initHookCalled = false;
- hookCalled = false;
- RxJavaPlugins.reset();
- }
-}
+package com.baeldung.rxjava;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Test;
+
+import io.reactivex.Completable;
+import io.reactivex.Flowable;
+import io.reactivex.Maybe;
+import io.reactivex.Observable;
+import io.reactivex.Single;
+import io.reactivex.flowables.ConnectableFlowable;
+import io.reactivex.observables.ConnectableObservable;
+import io.reactivex.plugins.RxJavaPlugins;
+import io.reactivex.schedulers.Schedulers;
+
+public class RxJavaHooksUnitTest {
+
+ private boolean initHookCalled = false;
+ private boolean hookCalled = false;
+
+ @Test
+ public void givenObservable_whenError_shouldExecuteTheHook() {
+ RxJavaPlugins.setErrorHandler(throwable -> {
+ hookCalled = true;
+ });
+
+ Observable.error(new IllegalStateException())
+ .subscribe();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenCompletable_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnCompletableAssembly(completable -> {
+ hookCalled = true;
+ return completable;
+ });
+ Completable.fromSingle(Single.just(1));
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenCompletable_whenSubscribed_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> {
+ hookCalled = true;
+ return observer;
+ });
+
+ Completable.fromSingle(Single.just(1))
+ .test();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenObservable_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnObservableAssembly(observable -> {
+ hookCalled = true;
+ return observable;
+ });
+
+ Observable.range(1, 10);
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenObservable_whenSubscribed_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> {
+ hookCalled = true;
+ return observer;
+ });
+
+ Observable.range(1, 10)
+ .test();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> {
+ hookCalled = true;
+ return connectableObservable;
+ });
+
+ ConnectableObservable.range(1, 10)
+ .publish()
+ .connect();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenFlowable_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnFlowableAssembly(flowable -> {
+ hookCalled = true;
+ return flowable;
+ });
+
+ Flowable.range(1, 10);
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenFlowable_whenSubscribed_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> {
+ hookCalled = true;
+ return observer;
+ });
+
+ Flowable.range(1, 10)
+ .test();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> {
+ hookCalled = true;
+ return connectableFlowable;
+ });
+
+ ConnectableFlowable.range(1, 10)
+ .publish()
+ .connect();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenParallel_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> {
+ hookCalled = true;
+ return parallelFlowable;
+ });
+
+ Flowable.range(1, 10)
+ .parallel();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenMaybe_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnMaybeAssembly(maybe -> {
+ hookCalled = true;
+ return maybe;
+ });
+
+ Maybe.just(1);
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenMaybe_whenSubscribed_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> {
+ hookCalled = true;
+ return observer;
+ });
+
+ Maybe.just(1)
+ .test();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenSingle_whenAssembled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnSingleAssembly(single -> {
+ hookCalled = true;
+ return single;
+ });
+
+ Single.just(1);
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenSingle_whenSubscribed_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setOnSingleSubscribe((single, observer) -> {
+ hookCalled = true;
+ return observer;
+ });
+
+ Single.just(1)
+ .test();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() {
+
+ RxJavaPlugins.setScheduleHandler((runnable) -> {
+ hookCalled = true;
+ return runnable;
+ });
+
+ Observable.range(1, 10)
+ .map(v -> v * 2)
+ .subscribeOn(Schedulers.single())
+ .test();
+ hookCalled = false;
+ Observable.range(1, 10)
+ .map(v -> v * 2)
+ .subscribeOn(Schedulers.computation())
+ .test();
+ assertTrue(hookCalled);
+ }
+
+ @Test
+ public void givenComputationScheduler_whenCalled_shouldExecuteTheHooks() {
+
+ RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> {
+ initHookCalled = true;
+ return scheduler.call();
+ });
+ RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> {
+ hookCalled = true;
+ return scheduler;
+ });
+
+ Observable.range(1, 10)
+ .map(v -> v * 2)
+ .subscribeOn(Schedulers.computation())
+ .test();
+ assertTrue(hookCalled && initHookCalled);
+ }
+
+ @After
+ public void reset() {
+ initHookCalled = false;
+ hookCalled = false;
+ RxJavaPlugins.reset();
+ }
+}
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/SingleUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/SingleUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/SingleUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/SingleUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java
rename to rxjava-core/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java
diff --git a/rxjava-libraries/README.md b/rxjava-libraries/README.md
new file mode 100644
index 0000000000..ac8aac6908
--- /dev/null
+++ b/rxjava-libraries/README.md
@@ -0,0 +1,10 @@
+## RxJava Libraries
+
+ This module contains articles about RxJava libraries
+
+### Related Articles:
+
+- [RxJava 2 – Flowable](https://www.baeldung.com/rxjava-2-flowable)
+- [Introduction to RxRelay for RxJava](https://www.baeldung.com/rx-relay)
+- [Introduction to rxjava-jdbc](https://www.baeldung.com/rxjava-jdbc)
+
diff --git a/rxjava-libraries/pom.xml b/rxjava-libraries/pom.xml
new file mode 100644
index 0000000000..541d9116c8
--- /dev/null
+++ b/rxjava-libraries/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+ rxjava-libraries
+ 1.0-SNAPSHOT
+ rxjava-libraries
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ io.reactivex
+ rxjava
+ ${rx.java.version}
+
+
+ io.reactivex.rxjava2
+ rxjava
+ ${rx.java2.version}
+
+
+ com.jakewharton.rxrelay2
+ rxrelay
+ ${rxrelay.version}
+
+
+ com.github.davidmoten
+ rxjava-jdbc
+ ${rx.java.jdbc.version}
+
+
+ com.h2database
+ h2
+ ${h2.version}
+ runtime
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+
+
+
+
+
+ 0.7.11
+ 1.2.5
+ 2.0.0
+ 2.2.2
+ 3.8.0
+
+
+
\ No newline at end of file
diff --git a/rxjava-2/src/main/java/com/baeldung/rxjava/RandomRelay.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/RandomRelay.java
similarity index 100%
rename from rxjava-2/src/main/java/com/baeldung/rxjava/RandomRelay.java
rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/RandomRelay.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Connector.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Connector.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Connector.java
rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Connector.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Employee.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Employee.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Employee.java
rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Employee.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Manager.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Manager.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Manager.java
rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Manager.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Utils.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Utils.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Utils.java
rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Utils.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java
rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java
diff --git a/rxjava/src/test/resources/actual_clob b/rxjava-libraries/src/test/resources/actual_clob
similarity index 100%
rename from rxjava/src/test/resources/actual_clob
rename to rxjava-libraries/src/test/resources/actual_clob
diff --git a/rxjava/src/test/resources/expected_clob b/rxjava-libraries/src/test/resources/expected_clob
similarity index 100%
rename from rxjava/src/test/resources/expected_clob
rename to rxjava-libraries/src/test/resources/expected_clob
diff --git a/rxjava-observables/README.md b/rxjava-observables/README.md
new file mode 100644
index 0000000000..3bec990012
--- /dev/null
+++ b/rxjava-observables/README.md
@@ -0,0 +1,11 @@
+## RxJava Observables
+
+ This module contains articles about RxJava Observables
+
+### Related Articles:
+
+- [Combining Observables in RxJava](https://www.baeldung.com/rxjava-combine-observables)
+- [RxJava One Observable, Multiple Subscribers](https://www.baeldung.com/rxjava-multiple-subscribers-observable)
+- [RxJava StringObservable](https://www.baeldung.com/rxjava-string)
+- [Filtering Observables in RxJava](https://www.baeldung.com/rxjava-filtering)
+
diff --git a/rxjava-observables/pom.xml b/rxjava-observables/pom.xml
new file mode 100644
index 0000000000..c2bf0bcd88
--- /dev/null
+++ b/rxjava-observables/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+ rxjava-observables
+ 1.0-SNAPSHOT
+ rxjava-observables
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ io.reactivex
+ rxjava
+ ${rx.java.version}
+
+
+ io.reactivex
+ rxjava-string
+ ${rx.java.string.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+
+
+
+
+
+ 1.1.1
+ 1.2.5
+ 3.8.0
+
+
+
\ No newline at end of file
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java b/rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java
rename to rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java b/rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java
rename to rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java
rename to rxjava-observables/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java
rename to rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java
rename to rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java
rename to rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java
rename to rxjava-observables/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java
diff --git a/rxjava-operators/README.md b/rxjava-operators/README.md
new file mode 100644
index 0000000000..293d310bbd
--- /dev/null
+++ b/rxjava-operators/README.md
@@ -0,0 +1,12 @@
+## RxJava Operators
+
+ This module contains articles about RxJava Operators
+
+### Related Articles:
+
+- [Mathematical and Aggregate Operators in RxJava](https://www.baeldung.com/rxjava-math)
+- [Observable Utility Operators in RxJava](https://www.baeldung.com/rxjava-observable-operators)
+- [Implementing Custom Operators in RxJava](https://www.baeldung.com/rxjava-custom-operators)
+- [Converting Synchronous and Asynchronous APIs to Observables using RxJava2](https://www.baeldung.com/rxjava-apis-to-observables)
+
+
diff --git a/rxjava/pom.xml b/rxjava-operators/pom.xml
similarity index 66%
rename from rxjava/pom.xml
rename to rxjava-operators/pom.xml
index 85106d1127..8064613f45 100644
--- a/rxjava/pom.xml
+++ b/rxjava-operators/pom.xml
@@ -1,11 +1,11 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- rxjava
+ rxjava-operators
1.0-SNAPSHOT
- rxjava
-
+ rxjava-operators
+
com.baeldung
parent-java
@@ -19,48 +19,40 @@
rxjava
${rx.java.version}
-
- io.reactivex
- rxjava-math
- ${rx.java.math.version}
+ io.reactivex.rxjava2
+ rxjava
+ ${rx.java2.version}
-
+
- io.reactivex
- rxjava-string
- ${rx.java.string.version}
-
-
-
- com.jayway.awaitility
- awaitility
- ${awaitility.version}
-
-
- com.github.davidmoten
- rxjava-jdbc
- ${rx.java.jdbc.version}
-
-
- com.h2database
- h2
- ${h2.version}
- runtime
+ com.github.akarnokd
+ rxjava2-extensions
+ ${rxjava2.ext.version}
org.assertj
assertj-core
${assertj.version}
+
+ io.reactivex
+ rxjava-math
+ ${rx.java.math.version}
+
+
+ com.jayway.awaitility
+ awaitility
+ ${awaitility.version}
+
+ 0.20.4
+ 2.2.2
3.8.0
1.2.5
- 0.7.11
1.0.0
- 1.1.1
1.7.0
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java b/rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java
rename to rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java
diff --git a/rxjava/src/main/java/com/baeldung/rxjava/operator/ToLength.java b/rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToLength.java
similarity index 100%
rename from rxjava/src/main/java/com/baeldung/rxjava/operator/ToLength.java
rename to rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToLength.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java
similarity index 96%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java
rename to rxjava-operators/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java
index 90f4fe94ae..2842fab80e 100644
--- a/rxjava-2/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java
+++ b/rxjava-operators/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java
@@ -1,107 +1,107 @@
-package com.baeldung.rxjava;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.junit.Test;
-
-import hu.akarnokd.rxjava2.async.AsyncObservable;
-import io.reactivex.Observable;
-
-public class AsyncAndSyncToObservableIntegrationTest {
-
- AtomicInteger counter = new AtomicInteger();
- Callable callable = () -> counter.incrementAndGet();
-
- /* Method will execute every time it gets subscribed*/
- @Test
- public void givenSyncMethod_whenConvertedWithFromCallable_thenReturnObservable() {
-
- Observable source = Observable.fromCallable(callable);
-
- for (int i = 1; i < 5; i++) {
- source.test()
- .awaitDone(5, TimeUnit.SECONDS)
- .assertResult(i);
-
- assertEquals(i, counter.get());
- }
- }
-
- /* Method will execute only once and cache its result.*/
- @Test
- public void givenSyncMethod_whenConvertedWithStart_thenReturnObservable() {
-
- Observable source = AsyncObservable.start(callable);
-
- for (int i = 1; i < 5; i++) {
- source.test()
- .awaitDone(5, TimeUnit.SECONDS)
- .assertResult(1);
-
- assertEquals(1, counter.get());
- }
- }
-
- /* Method will execute only once and cache its result.*/
- @Test
- public void givenAsyncMethod_whenConvertedWithFromFuture_thenRetrunObservble() {
-
- ExecutorService executor = Executors.newSingleThreadExecutor();
- Future future = executor.submit(callable);
- Observable source = Observable.fromFuture(future);
-
- for (int i = 1; i < 5; i++) {
- source.test()
- .awaitDone(5, TimeUnit.SECONDS)
- .assertResult(1);
-
- assertEquals(1, counter.get());
- }
-
- executor.shutdown();
- }
-
- /* Method will execute every time it gets subscribed*/
- @Test
- public void givenAsyncMethod_whenConvertedWithStartFuture_thenRetrunObservble() {
-
- ExecutorService executor = Executors.newSingleThreadExecutor();
- Observable source = AsyncObservable.startFuture(() -> executor.submit(callable));
-
- for (int i = 1; i < 5; i++) {
- source.test()
- .awaitDone(5, TimeUnit.SECONDS)
- .assertResult(i);
-
- assertEquals(i, counter.get());
- }
-
- executor.shutdown();
- }
-
- /*Method will execute only once and cache its result.*/
- @Test
- public void givenAsyncMethod_whenConvertedWithDeferFuture_thenRetrunObservble() {
- List list = Arrays.asList(new Integer[] { counter.incrementAndGet(), counter.incrementAndGet(), counter.incrementAndGet() });
- ExecutorService exec = Executors.newSingleThreadExecutor();
- Callable> callable = () -> Observable.fromIterable(list);
- Observable source = AsyncObservable.deferFuture(() -> exec.submit(callable));
- for (int i = 1; i < 4; i++) {
- source.test()
- .awaitDone(5, TimeUnit.SECONDS)
- .assertResult(1, 2, 3);
- }
-
- exec.shutdown();
- }
-
-}
+package com.baeldung.rxjava;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import hu.akarnokd.rxjava2.async.AsyncObservable;
+import io.reactivex.Observable;
+
+public class AsyncAndSyncToObservableIntegrationTest {
+
+ AtomicInteger counter = new AtomicInteger();
+ Callable callable = () -> counter.incrementAndGet();
+
+ /* Method will execute every time it gets subscribed*/
+ @Test
+ public void givenSyncMethod_whenConvertedWithFromCallable_thenReturnObservable() {
+
+ Observable source = Observable.fromCallable(callable);
+
+ for (int i = 1; i < 5; i++) {
+ source.test()
+ .awaitDone(5, TimeUnit.SECONDS)
+ .assertResult(i);
+
+ assertEquals(i, counter.get());
+ }
+ }
+
+ /* Method will execute only once and cache its result.*/
+ @Test
+ public void givenSyncMethod_whenConvertedWithStart_thenReturnObservable() {
+
+ Observable source = AsyncObservable.start(callable);
+
+ for (int i = 1; i < 5; i++) {
+ source.test()
+ .awaitDone(5, TimeUnit.SECONDS)
+ .assertResult(1);
+
+ assertEquals(1, counter.get());
+ }
+ }
+
+ /* Method will execute only once and cache its result.*/
+ @Test
+ public void givenAsyncMethod_whenConvertedWithFromFuture_thenRetrunObservble() {
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future future = executor.submit(callable);
+ Observable source = Observable.fromFuture(future);
+
+ for (int i = 1; i < 5; i++) {
+ source.test()
+ .awaitDone(5, TimeUnit.SECONDS)
+ .assertResult(1);
+
+ assertEquals(1, counter.get());
+ }
+
+ executor.shutdown();
+ }
+
+ /* Method will execute every time it gets subscribed*/
+ @Test
+ public void givenAsyncMethod_whenConvertedWithStartFuture_thenRetrunObservble() {
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Observable source = AsyncObservable.startFuture(() -> executor.submit(callable));
+
+ for (int i = 1; i < 5; i++) {
+ source.test()
+ .awaitDone(5, TimeUnit.SECONDS)
+ .assertResult(i);
+
+ assertEquals(i, counter.get());
+ }
+
+ executor.shutdown();
+ }
+
+ /*Method will execute only once and cache its result.*/
+ @Test
+ public void givenAsyncMethod_whenConvertedWithDeferFuture_thenRetrunObservble() {
+ List list = Arrays.asList(new Integer[] { counter.incrementAndGet(), counter.incrementAndGet(), counter.incrementAndGet() });
+ ExecutorService exec = Executors.newSingleThreadExecutor();
+ Callable> callable = () -> Observable.fromIterable(list);
+ Observable source = AsyncObservable.deferFuture(() -> exec.submit(callable));
+ for (int i = 1; i < 4; i++) {
+ source.test()
+ .awaitDone(5, TimeUnit.SECONDS)
+ .assertResult(1, 2, 3);
+ }
+
+ exec.shutdown();
+ }
+
+}
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java
rename to rxjava-operators/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java
rename to rxjava-operators/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java
rename to rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java
diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java
similarity index 100%
rename from rxjava-2/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java
rename to rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java
diff --git a/rxjava/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java
similarity index 100%
rename from rxjava/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java
rename to rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java
diff --git a/rxjava/README.md b/rxjava/README.md
deleted file mode 100644
index c9308ddcc6..0000000000
--- a/rxjava/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-## RxJava
-
-This module contains articles about RxJava.
-
-### Relevant articles:
-
-- [Dealing with Backpressure with RxJava](https://www.baeldung.com/rxjava-backpressure)
-- [How to Test RxJava?](https://www.baeldung.com/rxjava-testing)
-- [Implementing Custom Operators in RxJava](https://www.baeldung.com/rxjava-custom-operators)
-- [Introduction to RxJava](https://www.baeldung.com/rx-java)
-- [Observable Utility Operators in RxJava](https://www.baeldung.com/rxjava-observable-operators)
-- [Introduction to rxjava-jdbc](https://www.baeldung.com/rxjava-jdbc)
-- [Schedulers in RxJava](https://www.baeldung.com/rxjava-schedulers)
-- [Mathematical and Aggregate Operators in RxJava](https://www.baeldung.com/rxjava-math)
-- [Combining Observables in RxJava](https://www.baeldung.com/rxjava-combine-observables)
-- [RxJava StringObservable](https://www.baeldung.com/rxjava-string)
-- [Filtering Observables in RxJava](https://www.baeldung.com/rxjava-filtering)
-- [RxJava One Observable, Multiple Subscribers](https://www.baeldung.com/rxjava-multiple-subscribers-observable)
-- [Difference Between Flatmap and Switchmap in RxJava](https://www.baeldung.com/rxjava-flatmap-switchmap)
-- More articles: [[next -->]](/rxjava-2)
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/ErrorHandlingApp.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/ErrorHandlingApp.java
new file mode 100644
index 0000000000..72a9ec8ad7
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/ErrorHandlingApp.java
@@ -0,0 +1,26 @@
+package com.baeldung.springamqp.errorhandling;
+
+import com.baeldung.springamqp.errorhandling.producer.MessageProducer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableScheduling
+public class ErrorHandlingApp {
+
+ @Autowired
+ MessageProducer messageProducer;
+
+ public static void main(String[] args) {
+ SpringApplication.run(ErrorHandlingApp.class, args);
+ }
+
+ @EventListener(ApplicationReadyEvent.class)
+ public void doSomethingAfterStartup() {
+ messageProducer.sendMessage();
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXCustomAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXCustomAmqpConfiguration.java
new file mode 100644
index 0000000000..708b08476d
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXCustomAmqpConfiguration.java
@@ -0,0 +1,55 @@
+package com.baeldung.springamqp.errorhandling.configuration;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.FanoutExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+
+@Configuration
+@ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "dlx-custom")
+public class DLXCustomAmqpConfiguration {
+ public static final String DLX_EXCHANGE_MESSAGES = QUEUE_MESSAGES + ".dlx";
+
+ @Bean
+ Queue messagesQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES)
+ .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_MESSAGES)
+ .build();
+ }
+
+ @Bean
+ FanoutExchange deadLetterExchange() {
+ return new FanoutExchange(DLX_EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Queue deadLetterQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build();
+ }
+
+ @Bean
+ Binding deadLetterBinding() {
+ return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
+ }
+
+ @Bean
+ DirectExchange messagesExchange() {
+ return new DirectExchange(EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Binding bindingMessages() {
+ return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXParkingLotAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXParkingLotAmqpConfiguration.java
new file mode 100644
index 0000000000..bff325e657
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXParkingLotAmqpConfiguration.java
@@ -0,0 +1,72 @@
+package com.baeldung.springamqp.errorhandling.configuration;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.FanoutExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+
+@Configuration
+@ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "parking-lot-dlx")
+public class DLXParkingLotAmqpConfiguration {
+ public static final String DLX_EXCHANGE_MESSAGES = QUEUE_MESSAGES + ".dlx";
+ public static final String QUEUE_PARKING_LOT = QUEUE_MESSAGES + ".parking-lot";
+ public static final String EXCHANGE_PARKING_LOT = QUEUE_MESSAGES + "exchange.parking-lot";
+
+ @Bean
+ FanoutExchange parkingLotExchange() {
+ return new FanoutExchange(EXCHANGE_PARKING_LOT);
+ }
+
+ @Bean
+ Queue parkingLotQueue() {
+ return QueueBuilder.durable(QUEUE_PARKING_LOT).build();
+ }
+
+ @Bean
+ Binding parkingLotBinding() {
+ return BindingBuilder.bind(parkingLotQueue()).to(parkingLotExchange());
+ }
+
+ @Bean
+ Queue messagesQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES)
+ .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_MESSAGES)
+ .build();
+ }
+
+ @Bean
+ FanoutExchange deadLetterExchange() {
+ return new FanoutExchange(DLX_EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Queue deadLetterQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build();
+ }
+
+ @Bean
+ Binding deadLetterBinding() {
+ return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
+ }
+
+ @Bean
+ DirectExchange messagesExchange() {
+ return new DirectExchange(EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Binding bindingMessages() {
+ return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/FatalExceptionStrategyAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/FatalExceptionStrategyAmqpConfiguration.java
new file mode 100644
index 0000000000..dcd76d7f72
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/FatalExceptionStrategyAmqpConfiguration.java
@@ -0,0 +1,63 @@
+package com.baeldung.springamqp.errorhandling.configuration;
+
+import com.baeldung.springamqp.errorhandling.errorhandler.CustomFatalExceptionStrategy;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler;
+import org.springframework.amqp.rabbit.listener.FatalExceptionStrategy;
+import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ErrorHandler;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES;
+
+@Configuration
+@ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "fatal-error-strategy")
+public class FatalExceptionStrategyAmqpConfiguration {
+
+ @Bean
+ public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
+ ConnectionFactory connectionFactory,
+ SimpleRabbitListenerContainerFactoryConfigurer configurer) {
+ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+ configurer.configure(factory, connectionFactory);
+ factory.setErrorHandler(errorHandler());
+ return factory;
+ }
+
+ @Bean
+ public ErrorHandler errorHandler() {
+ return new ConditionalRejectingErrorHandler(customExceptionStrategy());
+ }
+
+ @Bean
+ FatalExceptionStrategy customExceptionStrategy() {
+ return new CustomFatalExceptionStrategy();
+ }
+
+ @Bean
+ Queue messagesQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES)
+ .build();
+ }
+
+ @Bean
+ DirectExchange messagesExchange() {
+ return new DirectExchange(EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Binding bindingMessages() {
+ return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/ListenerErrorHandlerAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/ListenerErrorHandlerAmqpConfiguration.java
new file mode 100644
index 0000000000..8990381da2
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/ListenerErrorHandlerAmqpConfiguration.java
@@ -0,0 +1,55 @@
+package com.baeldung.springamqp.errorhandling.configuration;
+
+import com.baeldung.springamqp.errorhandling.errorhandler.CustomErrorHandler;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ErrorHandler;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES;
+
+@Configuration
+@ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "listener-error")
+public class ListenerErrorHandlerAmqpConfiguration {
+
+ @Bean
+ public ErrorHandler errorHandler() {
+ return new CustomErrorHandler();
+ }
+
+ @Bean
+ public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory,
+ SimpleRabbitListenerContainerFactoryConfigurer configurer) {
+ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+ configurer.configure(factory, connectionFactory);
+ factory.setErrorHandler(errorHandler());
+ return factory;
+ }
+
+ @Bean
+ Queue messagesQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES)
+ .build();
+ }
+
+ @Bean
+ DirectExchange messagesExchange() {
+ return new DirectExchange(EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Binding bindingMessages() {
+ return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/RoutingKeyDLQAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/RoutingKeyDLQAmqpConfiguration.java
new file mode 100644
index 0000000000..defabed306
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/RoutingKeyDLQAmqpConfiguration.java
@@ -0,0 +1,55 @@
+package com.baeldung.springamqp.errorhandling.configuration;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.FanoutExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+
+@Configuration
+@ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "routing-dlq")
+public class RoutingKeyDLQAmqpConfiguration {
+ public static final String DLX_EXCHANGE_MESSAGES = QUEUE_MESSAGES + ".dlx";
+
+ @Bean
+ Queue messagesQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES)
+ .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_MESSAGES)
+ .build();
+ }
+
+ @Bean
+ FanoutExchange deadLetterExchange() {
+ return new FanoutExchange(DLX_EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Queue deadLetterQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build();
+ }
+
+ @Bean
+ Binding deadLetterBinding() {
+ return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
+ }
+
+ @Bean
+ DirectExchange messagesExchange() {
+ return new DirectExchange(EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Binding bindingMessages() {
+ return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/SimpleDLQAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/SimpleDLQAmqpConfiguration.java
new file mode 100644
index 0000000000..ea129986ca
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/SimpleDLQAmqpConfiguration.java
@@ -0,0 +1,43 @@
+package com.baeldung.springamqp.errorhandling.configuration;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "simple-dlq")
+public class SimpleDLQAmqpConfiguration {
+ public static final String QUEUE_MESSAGES = "baeldung-messages-queue";
+ public static final String QUEUE_MESSAGES_DLQ = QUEUE_MESSAGES + ".dlq";
+ public static final String EXCHANGE_MESSAGES = "baeldung-messages-exchange";
+
+ @Bean
+ Queue messagesQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES)
+ .withArgument("x-dead-letter-exchange", "")
+ .withArgument("x-dead-letter-routing-key", QUEUE_MESSAGES_DLQ)
+ .build();
+ }
+
+ @Bean
+ Queue deadLetterQueue() {
+ return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build();
+ }
+
+ @Bean
+ DirectExchange messagesExchange() {
+ return new DirectExchange(EXCHANGE_MESSAGES);
+ }
+
+ @Bean
+ Binding bindingMessages() {
+ return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/DLQCustomAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/DLQCustomAmqpContainer.java
new file mode 100644
index 0000000000..62907abee9
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/DLQCustomAmqpContainer.java
@@ -0,0 +1,35 @@
+package com.baeldung.springamqp.errorhandling.consumer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+import static com.baeldung.springamqp.errorhandling.consumer.MessagesConsumer.HEADER_X_RETRIES_COUNT;
+
+public class DLQCustomAmqpContainer {
+ private static final Logger log = LoggerFactory.getLogger(DLQCustomAmqpContainer.class);
+ private final RabbitTemplate rabbitTemplate;
+ public static final int MAX_RETRIES_COUNT = 2;
+
+ public DLQCustomAmqpContainer(RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ @RabbitListener(queues = QUEUE_MESSAGES_DLQ)
+ public void processFailedMessagesRetryHeaders(Message failedMessage) {
+ Integer retriesCnt = (Integer) failedMessage.getMessageProperties().getHeaders().get(HEADER_X_RETRIES_COUNT);
+ if (retriesCnt == null)
+ retriesCnt = 1;
+ if (retriesCnt > MAX_RETRIES_COUNT) {
+ log.info("Discarding message");
+ return;
+ }
+ log.info("Retrying message for the {} time", retriesCnt);
+ failedMessage.getMessageProperties().getHeaders().put(HEADER_X_RETRIES_COUNT, ++retriesCnt);
+ rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/MessagesConsumer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/MessagesConsumer.java
new file mode 100644
index 0000000000..17b65c58da
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/MessagesConsumer.java
@@ -0,0 +1,63 @@
+package com.baeldung.springamqp.errorhandling.consumer;
+
+import com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration;
+import com.baeldung.springamqp.errorhandling.errorhandler.BusinessException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MessagesConsumer {
+ public static final String HEADER_X_RETRIES_COUNT = "x-retries-count";
+
+
+ private static final Logger log = LoggerFactory.getLogger(MessagesConsumer.class);
+ private final RabbitTemplate rabbitTemplate;
+
+ public MessagesConsumer(RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ @RabbitListener(queues = SimpleDLQAmqpConfiguration.QUEUE_MESSAGES)
+ public void receiveMessage(Message message) throws BusinessException {
+ log.info("Received message: {}", message.toString());
+ throw new BusinessException();
+ }
+
+ @Bean
+ @ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "simple-dlq")
+ public SimpleDLQAmqpContainer simpleAmqpContainer() {
+ return new SimpleDLQAmqpContainer(rabbitTemplate);
+ }
+
+ @Bean
+ @ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "routing-dlq")
+ public RoutingDLQAmqpContainer routingDLQAmqpContainer() {
+ return new RoutingDLQAmqpContainer(rabbitTemplate);
+ }
+
+ @Bean
+ @ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "dlx-custom")
+ public DLQCustomAmqpContainer dlqAmqpContainer() {
+ return new DLQCustomAmqpContainer(rabbitTemplate);
+ }
+
+ @Bean
+ @ConditionalOnProperty(
+ value = "amqp.configuration.current",
+ havingValue = "parking-lot-dlx")
+ public ParkingLotDLQAmqpContainer parkingLotDLQAmqpContainer() {
+ return new ParkingLotDLQAmqpContainer(rabbitTemplate);
+ }
+}
\ No newline at end of file
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/ParkingLotDLQAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/ParkingLotDLQAmqpContainer.java
new file mode 100644
index 0000000000..34dccd408a
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/ParkingLotDLQAmqpContainer.java
@@ -0,0 +1,43 @@
+package com.baeldung.springamqp.errorhandling.consumer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+import static com.baeldung.springamqp.errorhandling.configuration.DLXParkingLotAmqpConfiguration.EXCHANGE_PARKING_LOT;
+import static com.baeldung.springamqp.errorhandling.configuration.DLXParkingLotAmqpConfiguration.QUEUE_PARKING_LOT;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+import static com.baeldung.springamqp.errorhandling.consumer.MessagesConsumer.HEADER_X_RETRIES_COUNT;
+
+public class ParkingLotDLQAmqpContainer {
+ private static final Logger log = LoggerFactory.getLogger(ParkingLotDLQAmqpContainer.class);
+ private final RabbitTemplate rabbitTemplate;
+ public static final int MAX_RETRIES_COUNT = 2;
+
+ public ParkingLotDLQAmqpContainer(RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ @RabbitListener(queues = QUEUE_MESSAGES_DLQ)
+ public void processFailedMessagesRetryWithParkingLot(Message failedMessage) {
+ Integer retriesCnt = (Integer) failedMessage.getMessageProperties().getHeaders().get(HEADER_X_RETRIES_COUNT);
+ if (retriesCnt == null)
+ retriesCnt = 1;
+ if (retriesCnt > MAX_RETRIES_COUNT) {
+ log.info("Sending message to the parking lot queue");
+ rabbitTemplate.send(EXCHANGE_PARKING_LOT, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage);
+ return;
+ }
+ log.info("Retrying message for the {} time", retriesCnt);
+ failedMessage.getMessageProperties().getHeaders().put(HEADER_X_RETRIES_COUNT, ++retriesCnt);
+ rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage);
+ }
+
+ @RabbitListener(queues = QUEUE_PARKING_LOT)
+ public void processParkingLotQueue(Message failedMessage) {
+ log.info("Received message in parking lot queue {}", failedMessage.toString());
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/RoutingDLQAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/RoutingDLQAmqpContainer.java
new file mode 100644
index 0000000000..fedce76880
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/RoutingDLQAmqpContainer.java
@@ -0,0 +1,33 @@
+package com.baeldung.springamqp.errorhandling.consumer;
+
+import com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration;
+import com.baeldung.springamqp.errorhandling.errorhandler.BusinessException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+
+public class RoutingDLQAmqpContainer {
+ private static final Logger log = LoggerFactory.getLogger(RoutingDLQAmqpContainer.class);
+ private final RabbitTemplate rabbitTemplate;
+
+ public RoutingDLQAmqpContainer(RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ @RabbitListener(queues = SimpleDLQAmqpConfiguration.QUEUE_MESSAGES)
+ public void receiveMessage(Message message) throws BusinessException {
+ log.info("Received message: {}", message.toString());
+ throw new BusinessException();
+ }
+
+ @RabbitListener(queues = QUEUE_MESSAGES_DLQ)
+ public void processFailedMessagesRequeue(Message failedMessage) {
+ log.info("Received failed message, requeueing: {}", failedMessage.toString());
+ rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/SimpleDLQAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/SimpleDLQAmqpContainer.java
new file mode 100644
index 0000000000..6f9da7b587
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/SimpleDLQAmqpContainer.java
@@ -0,0 +1,31 @@
+package com.baeldung.springamqp.errorhandling.consumer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES;
+import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ;
+
+public class SimpleDLQAmqpContainer {
+ private static final Logger log = LoggerFactory.getLogger(SimpleDLQAmqpContainer.class);
+ private final RabbitTemplate rabbitTemplate;
+
+ public SimpleDLQAmqpContainer(RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ @RabbitListener(queues = QUEUE_MESSAGES_DLQ)
+ public void processFailedMessages(Message message) {
+ log.info("Received failed message: {}", message.toString());
+ }
+
+ @RabbitListener(queues = QUEUE_MESSAGES_DLQ)
+ public void processFailedMessagesRequeue(Message failedMessage) {
+ log.info("Received failed message, requeueing: {}", failedMessage.toString());
+ log.info("Received failed message, requeueing: {}", failedMessage.getMessageProperties().getReceivedRoutingKey());
+ rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage);
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/BusinessException.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/BusinessException.java
new file mode 100644
index 0000000000..faec96e2aa
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/BusinessException.java
@@ -0,0 +1,4 @@
+package com.baeldung.springamqp.errorhandling.errorhandler;
+
+public class BusinessException extends Exception {
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomErrorHandler.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomErrorHandler.java
new file mode 100644
index 0000000000..5c5e9cdf13
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomErrorHandler.java
@@ -0,0 +1,14 @@
+package com.baeldung.springamqp.errorhandling.errorhandler;
+
+import org.springframework.amqp.AmqpRejectAndDontRequeueException;
+import org.springframework.util.ErrorHandler;
+
+public class CustomErrorHandler implements ErrorHandler {
+
+ @Override
+ public void handleError(Throwable t) {
+ if (!(t.getCause() instanceof BusinessException)) {
+ throw new AmqpRejectAndDontRequeueException("Error Handler converted exception to fatal", t);
+ }
+ }
+}
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomFatalExceptionStrategy.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomFatalExceptionStrategy.java
new file mode 100644
index 0000000000..e14be4e73c
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomFatalExceptionStrategy.java
@@ -0,0 +1,10 @@
+package com.baeldung.springamqp.errorhandling.errorhandler;
+
+import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler;
+
+public class CustomFatalExceptionStrategy extends ConditionalRejectingErrorHandler.DefaultExceptionStrategy {
+ @Override
+ public boolean isFatal(Throwable t) {
+ return !(t.getCause() instanceof BusinessException);
+ }
+}
\ No newline at end of file
diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/producer/MessageProducer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/producer/MessageProducer.java
new file mode 100644
index 0000000000..c14fd5bf3b
--- /dev/null
+++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/producer/MessageProducer.java
@@ -0,0 +1,24 @@
+package com.baeldung.springamqp.errorhandling.producer;
+
+import com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MessageProducer {
+
+ private static final Logger log = LoggerFactory.getLogger(MessageProducer.class);
+ private int messageNumber = 0;
+ private final RabbitTemplate rabbitTemplate;
+
+ public MessageProducer(final RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ public void sendMessage() {
+ log.info("Sending message...");
+ rabbitTemplate.convertAndSend(SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES, SimpleDLQAmqpConfiguration.QUEUE_MESSAGES, "Some message id:" + messageNumber++);
+ }
+}
\ No newline at end of file
diff --git a/spring-amqp/src/main/resources/application.properties b/spring-amqp/src/main/resources/application.properties
new file mode 100644
index 0000000000..c0c1cf1b47
--- /dev/null
+++ b/spring-amqp/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+spring.rabbitmq.listener.simple.default-requeue-rejected=false
+spring.main.allow-bean-definition-overriding=true
+amqp.configuration.current=parking-lot-dlx
\ No newline at end of file
diff --git a/spring-boot-springdoc/pom.xml b/spring-boot-springdoc/pom.xml
new file mode 100644
index 0000000000..a818db6e53
--- /dev/null
+++ b/spring-boot-springdoc/pom.xml
@@ -0,0 +1,106 @@
+
+
+ 4.0.0
+ com.baeldung
+ spring-boot-springdoc
+ 0.0.1-SNAPSHOT
+ spring-boot-springdoc
+ Project for Springdoc integration
+ jar
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springdoc
+ springdoc-openapi-core
+ 1.1.45
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ 1.1.45
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ integration
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.1.8.RELEASE
+
+
+ pre-integration-test
+
+ start
+
+
+
+ post-integration-test
+
+ stop
+
+
+
+
+
+ org.springdoc
+ springdoc-openapi-maven-plugin
+ 0.2
+
+
+ integration-test
+
+ generate
+
+
+
+
+ http://localhost:8080/api-docs
+ openapi.json
+ ${project.build.directory}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/SpringdocApplication.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/SpringdocApplication.java
new file mode 100644
index 0000000000..45c7c23621
--- /dev/null
+++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/SpringdocApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.springdoc;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringdocApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringdocApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java
new file mode 100644
index 0000000000..4d7d9e3d85
--- /dev/null
+++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java
@@ -0,0 +1,73 @@
+package com.baeldung.springdoc.controller;
+
+import java.util.Collection;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.springdoc.exception.BookNotFoundException;
+import com.baeldung.springdoc.model.Book;
+import com.baeldung.springdoc.repository.BookRepository;
+
+@RestController
+@RequestMapping("/api/book")
+public class BookController {
+
+ @Autowired
+ private BookRepository repository;
+
+ @GetMapping("/{id}")
+ public Book findById(@PathVariable long id) {
+ return repository.findById(id)
+ .orElseThrow(() -> new BookNotFoundException());
+ }
+
+ @GetMapping("/")
+ public Collection findBooks() {
+ return repository.getBooks();
+ }
+
+ @PutMapping("/{id}")
+ @ResponseStatus(HttpStatus.OK)
+ public Book updateBook(@PathVariable("id") final String id, @RequestBody final Book book) {
+ return book;
+ }
+
+ @PatchMapping("/{id}")
+ @ResponseStatus(HttpStatus.OK)
+ public Book patchBook(@PathVariable("id") final String id, @RequestBody final Book book) {
+ return book;
+ }
+
+ @PostMapping("/")
+ @ResponseStatus(HttpStatus.CREATED)
+ public Book postBook(@NotNull @Valid @RequestBody final Book book) {
+ return book;
+ }
+
+ @RequestMapping(method = RequestMethod.HEAD, value = "/")
+ @ResponseStatus(HttpStatus.OK)
+ public Book headBook() {
+ return new Book();
+ }
+
+ @DeleteMapping("/{id}")
+ @ResponseStatus(HttpStatus.OK)
+ public long deleteBook(@PathVariable final long id) {
+ return id;
+ }
+}
diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/BookNotFoundException.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/BookNotFoundException.java
new file mode 100644
index 0000000000..632cb683bc
--- /dev/null
+++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/BookNotFoundException.java
@@ -0,0 +1,10 @@
+package com.baeldung.springdoc.exception;
+
+@SuppressWarnings("serial")
+public class BookNotFoundException extends RuntimeException {
+
+ public BookNotFoundException() {
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/GlobalControllerExceptionHandler.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/GlobalControllerExceptionHandler.java
new file mode 100644
index 0000000000..c829072236
--- /dev/null
+++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/GlobalControllerExceptionHandler.java
@@ -0,0 +1,24 @@
+package com.baeldung.springdoc.exception;
+
+import org.springframework.core.convert.ConversionFailedException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class GlobalControllerExceptionHandler {
+
+ @ExceptionHandler(ConversionFailedException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ResponseEntity handleConnversion(RuntimeException ex) {
+ return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
+ }
+
+ @ExceptionHandler(BookNotFoundException.class)
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ResponseEntity handleBookNotFound(RuntimeException ex) {
+ return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
+ }
+}
diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java
new file mode 100644
index 0000000000..8f678a7ec2
--- /dev/null
+++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java
@@ -0,0 +1,41 @@
+package com.baeldung.springdoc.model;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+public class Book {
+
+ private long id;
+
+ @NotBlank
+ @Size(min = 0, max = 20)
+ private String title;
+
+ @NotBlank
+ @Size(min = 0, max = 30)
+ private String author;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+}
diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/repository/BookRepository.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/repository/BookRepository.java
new file mode 100644
index 0000000000..4040ba28c2
--- /dev/null
+++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/repository/BookRepository.java
@@ -0,0 +1,28 @@
+package com.baeldung.springdoc.repository;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.springdoc.model.Book;
+
+@Repository
+public class BookRepository {
+
+ private Map books = new HashMap<>();
+
+ public Optional findById(long id) {
+ return Optional.ofNullable(books.get(id));
+ }
+
+ public void add(Book book) {
+ books.put(book.getId(), book);
+ }
+
+ public Collection getBooks() {
+ return books.values();
+ }
+}
diff --git a/spring-boot-springdoc/src/main/resources/application.properties b/spring-boot-springdoc/src/main/resources/application.properties
new file mode 100644
index 0000000000..f03e90feb6
--- /dev/null
+++ b/spring-boot-springdoc/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+# custom path for swagger-ui
+springdoc.swagger-ui.path=/swagger-ui-custom.html
+
+# custom path for api docs
+springdoc.api-docs.path=/api-docs
diff --git a/rxjava/src/main/resources/logback.xml b/spring-boot-springdoc/src/main/resources/logback.xml
similarity index 74%
rename from rxjava/src/main/resources/logback.xml
rename to spring-boot-springdoc/src/main/resources/logback.xml
index 7d900d8ea8..6a07b178e9 100644
--- a/rxjava/src/main/resources/logback.xml
+++ b/spring-boot-springdoc/src/main/resources/logback.xml
@@ -7,6 +7,9 @@
+
+
+
diff --git a/spring-boot-springdoc/src/test/java/com/baeldung/springdoc/SpringContextIntegrationTest.java b/spring-boot-springdoc/src/test/java/com/baeldung/springdoc/SpringContextIntegrationTest.java
new file mode 100644
index 0000000000..58c12dc3bc
--- /dev/null
+++ b/spring-boot-springdoc/src/test/java/com/baeldung/springdoc/SpringContextIntegrationTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.springdoc;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+
+ }
+
+}
diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/Application.java b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/Application.java
new file mode 100644
index 0000000000..0472ba4e7b
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/Application.java
@@ -0,0 +1,14 @@
+package com.baeldung.flash_attributes;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+@SpringBootApplication
+public class Application extends SpringBootServletInitializer {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java
new file mode 100644
index 0000000000..6264ea0531
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java
@@ -0,0 +1,49 @@
+package com.baeldung.flash_attributes.controllers;
+
+import com.baeldung.flash_attributes.model.Poem;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+import org.springframework.web.servlet.support.RequestContextUtils;
+import org.springframework.web.servlet.view.RedirectView;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Controller
+public class PoemSubmission {
+
+ @GetMapping("/poem/success")
+ public String getSuccess(HttpServletRequest request) {
+ Map inputFlashMap = RequestContextUtils.getInputFlashMap(request);
+ if (inputFlashMap != null) {
+ Poem poem = (Poem) inputFlashMap.get("poem");
+ return "success";
+ } else {
+ return "redirect:/poem/submit";
+ }
+ }
+
+ @PostMapping("/poem/submit")
+ public RedirectView submitPost(
+ HttpServletRequest request,
+ @ModelAttribute Poem poem,
+ RedirectAttributes redirectAttributes) {
+ if (Poem.isValidPoem(poem)) {
+ redirectAttributes.addFlashAttribute("poem", poem);
+ return new RedirectView("/poem/success", true);
+ } else {
+ return new RedirectView("/poem/submit", true);
+ }
+ }
+
+ @GetMapping("/poem/submit")
+ public String submitGet(Model model) {
+ model.addAttribute("poem", new Poem());
+ return "submit";
+ }
+
+}
\ No newline at end of file
diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/model/Poem.java b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/model/Poem.java
new file mode 100644
index 0000000000..bff65456c1
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/model/Poem.java
@@ -0,0 +1,39 @@
+package com.baeldung.flash_attributes.model;
+
+import org.apache.logging.log4j.util.Strings;
+
+public class Poem {
+ private String title;
+ private String author;
+ private String body;
+
+ public static boolean isValidPoem(Poem poem) {
+ return poem != null && Strings.isNotBlank(poem.getAuthor()) && Strings.isNotBlank(poem.getBody())
+ && Strings.isNotBlank(poem.getTitle());
+ }
+
+ public String getTitle() {
+ return this.title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getBody() {
+ return this.body;
+ }
+
+ public void setBody(String body) {
+ this.body = body;
+ }
+
+ public String getAuthor() {
+ return this.author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+}
diff --git a/spring-mvc-simple-2/src/main/resources/application.properties b/spring-mvc-simple-2/src/main/resources/application.properties
index d29338d3d3..aca20f4e3c 100644
--- a/spring-mvc-simple-2/src/main/resources/application.properties
+++ b/spring-mvc-simple-2/src/main/resources/application.properties
@@ -1,3 +1,9 @@
spring.main.allow-bean-definition-overriding=true
+
spring.mail.host=localhost
-spring.mail.port=8025
\ No newline at end of file
+spring.mail.port=8025
+
+spring.thymeleaf.cache=false
+spring.thymeleaf.enabled=true
+spring.thymeleaf.prefix=classpath:/templates/
+spring.thymeleaf.suffix=.html
diff --git a/spring-mvc-simple-2/src/main/resources/templates/submit.html b/spring-mvc-simple-2/src/main/resources/templates/submit.html
new file mode 100644
index 0000000000..0ed0107c20
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/resources/templates/submit.html
@@ -0,0 +1,50 @@
+
+
+
+ Poetry Contest: Submission
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-mvc-simple-2/src/main/resources/templates/success.html b/spring-mvc-simple-2/src/main/resources/templates/success.html
new file mode 100644
index 0000000000..f845350ffb
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/resources/templates/success.html
@@ -0,0 +1,15 @@
+
+
+
+ Poetry Contest: Thank You
+
+
+
+
+ Click here to submit more.
+
+
+ Click here to submit a poem.
+
+
+
\ No newline at end of file
diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md
index a0ba8df27d..df7856725f 100644
--- a/spring-rest-full/README.md
+++ b/spring-rest-full/README.md
@@ -12,8 +12,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
- [Integration Testing with the Maven Cargo plugin](https://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin)
- [Project Configuration with Spring](https://www.baeldung.com/project-configuration-with-spring)
- [Metrics for your Spring REST API](https://www.baeldung.com/spring-rest-api-metrics)
-- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic)
-
### Build the Project
```
diff --git a/spring-rest/README.md b/spring-rest/README.md
index ac12066e8f..af054b2dcf 100644
--- a/spring-rest/README.md
+++ b/spring-rest/README.md
@@ -10,16 +10,11 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Returning Custom Status Codes from Spring Controllers](https://www.baeldung.com/spring-mvc-controller-custom-http-status-code)
- [Binary Data Formats in a Spring REST API](https://www.baeldung.com/spring-rest-api-with-binary-data-formats)
- [Guide to UriComponentsBuilder in Spring](https://www.baeldung.com/spring-uricomponentsbuilder)
-- [Introduction to FindBugs](https://www.baeldung.com/intro-to-findbugs)
- [A Custom Media Type for a Spring REST API](https://www.baeldung.com/spring-rest-custom-media-type)
- [HTTP PUT vs HTTP PATCH in a REST API](https://www.baeldung.com/http-put-patch-difference-spring)
- [Spring – Log Incoming Requests](https://www.baeldung.com/spring-http-logging)
-- [Introduction to CheckStyle](https://www.baeldung.com/checkstyle-java)
- [How to Change the Default Port in Spring Boot](https://www.baeldung.com/spring-boot-change-port)
- [Guide to DeferredResult in Spring](https://www.baeldung.com/spring-deferred-result)
- [Spring Custom Property Editor](https://www.baeldung.com/spring-mvc-custom-property-editor)
-- [Using the Spring RestTemplate Interceptor](https://www.baeldung.com/spring-rest-template-interceptor)
-- [Get and Post Lists of Objects with RestTemplate](https://www.baeldung.com/spring-rest-template-list)
- [How to Set a Header on a Response with Spring 5](https://www.baeldung.com/spring-response-header)
-- [Uploading MultipartFile with Spring RestTemplate](https://www.baeldung.com/spring-rest-template-multipart-upload)
- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file)
diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml
index 93160a9936..fce04a8f2d 100644
--- a/spring-rest/pom.xml
+++ b/spring-rest/pom.xml
@@ -20,10 +20,7 @@
org.springframework.boot
spring-boot-starter-web
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
-
+
org.springframework.boot
spring-boot-starter-actuator
@@ -141,11 +138,7 @@
commons-io
${commons-io.version}
-
- au.com.dius
- pact-jvm-provider-junit_2.11
- ${pact.version}
-
+
io.rest-assured
rest-assured
@@ -176,21 +169,7 @@
org.apache.maven.plugins
maven-war-plugin
-
- org.apache.maven.plugins
- maven-checkstyle-plugin
- ${checkstyle-maven-plugin.version}
-
- checkstyle.xml
-
-
-
-
- check
-
-
-
-
+
@@ -250,18 +229,7 @@
-
-
-
- org.apache.maven.plugins
- maven-checkstyle-plugin
- ${checkstyle-maven-plugin.version}
-
- checkstyle.xml
-
-
-
-
+
1.3.2
@@ -275,7 +243,7 @@
1.6.0
3.0.4
- 3.0.0
+
false
2.2.0
diff --git a/spring-resttemplate/README.md b/spring-resttemplate/README.md
index 82d8234908..054071a4df 100644
--- a/spring-resttemplate/README.md
+++ b/spring-resttemplate/README.md
@@ -13,4 +13,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Mocking a RestTemplate in Spring](https://www.baeldung.com/spring-mock-rest-template)
- [RestTemplate Post Request with JSON](https://www.baeldung.com/spring-resttemplate-post-json)
- [Download a Large File Through a Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-download-large-file)
+- [Using the Spring RestTemplate Interceptor](https://www.baeldung.com/spring-rest-template-interceptor)
+- [Uploading MultipartFile with Spring RestTemplate](https://www.baeldung.com/spring-rest-template-multipart-upload)
+- [Get and Post Lists of Objects with RestTemplate](https://www.baeldung.com/spring-rest-template-list)
- [Copy of RestTemplate Post Request with JSON](https://www.baeldung.com/spring-resttemplate-post-json-test)
diff --git a/spring-resttemplate/pom.xml b/spring-resttemplate/pom.xml
index ae5cfed4c9..26a3143d6d 100644
--- a/spring-resttemplate/pom.xml
+++ b/spring-resttemplate/pom.xml
@@ -21,6 +21,10 @@
org.springframework.boot
spring-boot-starter-actuator
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
org.springframework.boot
spring-boot-devtools
@@ -32,7 +36,13 @@
org.springframework.boot
spring-boot-starter-test
- test
+
+
+
+
+ au.com.dius
+ pact-jvm-provider-junit_2.11
+ ${pact.version}
@@ -111,11 +121,13 @@
+
junit
junit
- test
+ 4.12
+
org.hamcrest
hamcrest-core
@@ -295,6 +307,7 @@
3.4.1
+ 3.5.11
diff --git a/spring-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-resttemplate/src/main/java/com/baeldung/SpringContextIntegrationTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
rename to spring-resttemplate/src/main/java/com/baeldung/SpringContextIntegrationTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/SpringContextTest.java b/spring-resttemplate/src/main/java/com/baeldung/SpringContextTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/SpringContextTest.java
rename to spring-resttemplate/src/main/java/com/baeldung/SpringContextTest.java
diff --git a/spring-rest/src/main/java/com/baeldung/changeport/CustomApplication.java b/spring-resttemplate/src/main/java/com/baeldung/changeport/CustomApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/changeport/CustomApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/changeport/CustomApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/changeport/ServerPortCustomizer.java b/spring-resttemplate/src/main/java/com/baeldung/changeport/ServerPortCustomizer.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/changeport/ServerPortCustomizer.java
rename to spring-resttemplate/src/main/java/com/baeldung/changeport/ServerPortCustomizer.java
diff --git a/spring-rest/src/main/java/com/baeldung/produceimage/ImageApplication.java b/spring-resttemplate/src/main/java/com/baeldung/produceimage/ImageApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/produceimage/ImageApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/produceimage/ImageApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/produceimage/controller/DataProducerController.java b/spring-resttemplate/src/main/java/com/baeldung/produceimage/controller/DataProducerController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/produceimage/controller/DataProducerController.java
rename to spring-resttemplate/src/main/java/com/baeldung/produceimage/controller/DataProducerController.java
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java b/spring-resttemplate/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java b/spring-resttemplate/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java
rename to spring-resttemplate/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java b/spring-resttemplate/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java
rename to spring-resttemplate/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java b/spring-resttemplate/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java
rename to spring-resttemplate/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java b/spring-resttemplate/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java
rename to spring-resttemplate/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java b/spring-resttemplate/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java
rename to spring-resttemplate/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java b/spring-resttemplate/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java b/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java
rename to spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java b/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java
rename to spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java
diff --git a/spring-rest/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java b/spring-resttemplate/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java
rename to spring-resttemplate/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java
diff --git a/spring-rest/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java b/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java b/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java
rename to spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java
diff --git a/spring-rest/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java b/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java
rename to spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java
diff --git a/spring-rest/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java b/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java
rename to spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java
diff --git a/spring-rest/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java b/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java
rename to spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java
diff --git a/spring-rest/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java b/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java
rename to spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/config/MainApplication.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/MainApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/config/MainApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/MainApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java
index 8abc368bdb..cbaa21f4ca 100644
--- a/spring-rest/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java
@@ -1,29 +1,29 @@
-package com.baeldung.sampleapp.config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.client.RestTemplate;
-
-import com.baeldung.sampleapp.interceptors.RestTemplateHeaderModifierInterceptor;
-
-@Configuration
-public class RestClientConfig {
-
- @Bean
- public RestTemplate restTemplate() {
- RestTemplate restTemplate = new RestTemplate();
-
- List interceptors = restTemplate.getInterceptors();
- if (CollectionUtils.isEmpty(interceptors)) {
- interceptors = new ArrayList();
- }
- interceptors.add(new RestTemplateHeaderModifierInterceptor());
- restTemplate.setInterceptors(interceptors);
- return restTemplate;
- }
-}
+package com.baeldung.sampleapp.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.client.RestTemplate;
+
+import com.baeldung.sampleapp.interceptors.RestTemplateHeaderModifierInterceptor;
+
+@Configuration
+public class RestClientConfig {
+
+ @Bean
+ public RestTemplate restTemplate() {
+ RestTemplate restTemplate = new RestTemplate();
+
+ List interceptors = restTemplate.getInterceptors();
+ if (CollectionUtils.isEmpty(interceptors)) {
+ interceptors = new ArrayList();
+ }
+ interceptors.add(new RestTemplateHeaderModifierInterceptor());
+ restTemplate.setInterceptors(interceptors);
+ return restTemplate;
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/WebConfig.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/WebConfig.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java
index 519e5ebf0d..9ebe1553a5 100644
--- a/spring-rest/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java
@@ -1,18 +1,18 @@
-package com.baeldung.sampleapp.interceptors;
-
-import java.io.IOException;
-
-import org.springframework.http.HttpRequest;
-import org.springframework.http.client.ClientHttpRequestExecution;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.http.client.ClientHttpResponse;
-
-public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor {
-
- @Override
- public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
- ClientHttpResponse response = execution.execute(request, body);
- response.getHeaders().add("Foo", "bar");
- return response;
- }
-}
+package com.baeldung.sampleapp.interceptors;
+
+import java.io.IOException;
+
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor {
+
+ @Override
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+ ClientHttpResponse response = execution.execute(request, body);
+ response.getHeaders().add("Foo", "bar");
+ return response;
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Company.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Company.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Company.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Company.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Item.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Item.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Item.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Item.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Views.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Views.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Views.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Views.java
diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java b/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java
rename to spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java
diff --git a/spring-rest/src/main/java/com/baeldung/transfer/LoginForm.java b/spring-resttemplate/src/main/java/com/baeldung/transfer/LoginForm.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/transfer/LoginForm.java
rename to spring-resttemplate/src/main/java/com/baeldung/transfer/LoginForm.java
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/app/Application.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/app/Application.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/web/log/app/Application.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/app/Application.java
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/app/TaxiFareRequestInterceptor.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/app/TaxiFareRequestInterceptor.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/web/log/app/TaxiFareRequestInterceptor.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/app/TaxiFareRequestInterceptor.java
index b154f3665f..2ea0204dc3 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/app/TaxiFareRequestInterceptor.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/app/TaxiFareRequestInterceptor.java
@@ -1,44 +1,44 @@
-package com.baeldung.web.log.app;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
-import org.springframework.web.util.ContentCachingRequestWrapper;
-
-import com.baeldung.web.log.util.RequestLoggingUtil;
-
-@Component
-public class TaxiFareRequestInterceptor extends HandlerInterceptorAdapter {
-
- private final static Logger LOGGER = LoggerFactory.getLogger(TaxiFareRequestInterceptor.class);
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- String postData;
- HttpServletRequest requestCacheWrapperObject = null;
- try {
- // Uncomment to produce the stream closed issue
- // postData = RequestLoggingUtil.getStringFromInputStream(request.getInputStream());
-
- // To overcome request stream closed issue
- requestCacheWrapperObject = new ContentCachingRequestWrapper(request);
- requestCacheWrapperObject.getParameterMap();
- } catch (Exception exception) {
- exception.printStackTrace();
- } finally {
- postData = RequestLoggingUtil.readPayload(requestCacheWrapperObject);
- LOGGER.info("REQUEST DATA: " + postData);
- }
- return true;
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- LOGGER.info("RESPONSE: " + response.getStatus());
- }
-
-}
+package com.baeldung.web.log.app;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+
+import com.baeldung.web.log.util.RequestLoggingUtil;
+
+@Component
+public class TaxiFareRequestInterceptor extends HandlerInterceptorAdapter {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(TaxiFareRequestInterceptor.class);
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ String postData;
+ HttpServletRequest requestCacheWrapperObject = null;
+ try {
+ // Uncomment to produce the stream closed issue
+ // postData = RequestLoggingUtil.getStringFromInputStream(request.getInputStream());
+
+ // To overcome request stream closed issue
+ requestCacheWrapperObject = new ContentCachingRequestWrapper(request);
+ requestCacheWrapperObject.getParameterMap();
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ } finally {
+ postData = RequestLoggingUtil.readPayload(requestCacheWrapperObject);
+ LOGGER.info("REQUEST DATA: " + postData);
+ }
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ LOGGER.info("RESPONSE: " + response.getStatus());
+ }
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/config/CustomeRequestLoggingFilter.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/config/CustomeRequestLoggingFilter.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/web/log/config/CustomeRequestLoggingFilter.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/config/CustomeRequestLoggingFilter.java
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/config/RequestLoggingFilterConfig.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/config/RequestLoggingFilterConfig.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/web/log/config/RequestLoggingFilterConfig.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/config/RequestLoggingFilterConfig.java
index bc9ad1cf84..85728729d5 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/config/RequestLoggingFilterConfig.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/config/RequestLoggingFilterConfig.java
@@ -1,20 +1,20 @@
-package com.baeldung.web.log.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.filter.CommonsRequestLoggingFilter;
-
-@Configuration
-public class RequestLoggingFilterConfig {
-
- @Bean
- public CommonsRequestLoggingFilter logFilter() {
- CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
- filter.setIncludeQueryString(true);
- filter.setIncludePayload(true);
- filter.setMaxPayloadLength(10000);
- filter.setIncludeHeaders(false);
- filter.setAfterMessagePrefix("REQUEST DATA : ");
- return filter;
- }
-}
+package com.baeldung.web.log.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.filter.CommonsRequestLoggingFilter;
+
+@Configuration
+public class RequestLoggingFilterConfig {
+
+ @Bean
+ public CommonsRequestLoggingFilter logFilter() {
+ CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
+ filter.setIncludeQueryString(true);
+ filter.setIncludePayload(true);
+ filter.setMaxPayloadLength(10000);
+ filter.setIncludeHeaders(false);
+ filter.setAfterMessagePrefix("REQUEST DATA : ");
+ return filter;
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java
index 8f1a000acc..fb0c1d1d48 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java
@@ -1,19 +1,19 @@
-package com.baeldung.web.log.config;
-
-import com.baeldung.web.log.app.TaxiFareRequestInterceptor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class TaxiFareMVCConfig implements WebMvcConfigurer {
-
- @Autowired
- private TaxiFareRequestInterceptor taxiFareRequestInterceptor;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(taxiFareRequestInterceptor).addPathPatterns("/**/taxifare/**/");
- }
-}
+package com.baeldung.web.log.config;
+
+import com.baeldung.web.log.app.TaxiFareRequestInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class TaxiFareMVCConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private TaxiFareRequestInterceptor taxiFareRequestInterceptor;
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(taxiFareRequestInterceptor).addPathPatterns("/**/taxifare/**/");
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/controller/TaxiFareController.java
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/data/RateCard.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/data/RateCard.java
similarity index 95%
rename from spring-rest/src/main/java/com/baeldung/web/log/data/RateCard.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/data/RateCard.java
index c7955b561b..e486d6b1f7 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/data/RateCard.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/data/RateCard.java
@@ -1,31 +1,31 @@
-package com.baeldung.web.log.data;
-
-public class RateCard {
-
- private String nightSurcharge;
- private String ratePerMile;
-
- public RateCard() {
- nightSurcharge = "Extra $ 100";
- ratePerMile = "$ 10 Per Mile";
- }
-
-
- public String getNightSurcharge() {
- return nightSurcharge;
- }
-
- public void setNightSurcharge(String nightSurcharge) {
- this.nightSurcharge = nightSurcharge;
- }
-
- public String getRatePerMile() {
- return ratePerMile;
- }
-
- public void setRatePerMile(String ratePerMile) {
- this.ratePerMile = ratePerMile;
- }
-
-
-}
+package com.baeldung.web.log.data;
+
+public class RateCard {
+
+ private String nightSurcharge;
+ private String ratePerMile;
+
+ public RateCard() {
+ nightSurcharge = "Extra $ 100";
+ ratePerMile = "$ 10 Per Mile";
+ }
+
+
+ public String getNightSurcharge() {
+ return nightSurcharge;
+ }
+
+ public void setNightSurcharge(String nightSurcharge) {
+ this.nightSurcharge = nightSurcharge;
+ }
+
+ public String getRatePerMile() {
+ return ratePerMile;
+ }
+
+ public void setRatePerMile(String ratePerMile) {
+ this.ratePerMile = ratePerMile;
+ }
+
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/data/TaxiRide.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/data/TaxiRide.java
similarity index 95%
rename from spring-rest/src/main/java/com/baeldung/web/log/data/TaxiRide.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/data/TaxiRide.java
index 2e0f33f02b..6089c51996 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/data/TaxiRide.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/data/TaxiRide.java
@@ -1,33 +1,33 @@
-package com.baeldung.web.log.data;
-
-public class TaxiRide {
-
- private Boolean isNightSurcharge;
- private Long distanceInMile;
-
- public TaxiRide() {
- }
-
- public TaxiRide(Boolean isNightSurcharge, Long distanceInMile) {
- this.isNightSurcharge = isNightSurcharge;
- this.distanceInMile = distanceInMile;
- }
-
-
- public Boolean getIsNightSurcharge() {
- return isNightSurcharge;
- }
-
- public void setIsNightSurcharge(Boolean isNightSurcharge) {
- this.isNightSurcharge = isNightSurcharge;
- }
-
- public Long getDistanceInMile() {
- return distanceInMile;
- }
-
- public void setDistanceInMile(Long distanceInMile) {
- this.distanceInMile = distanceInMile;
- }
-
-}
+package com.baeldung.web.log.data;
+
+public class TaxiRide {
+
+ private Boolean isNightSurcharge;
+ private Long distanceInMile;
+
+ public TaxiRide() {
+ }
+
+ public TaxiRide(Boolean isNightSurcharge, Long distanceInMile) {
+ this.isNightSurcharge = isNightSurcharge;
+ this.distanceInMile = distanceInMile;
+ }
+
+
+ public Boolean getIsNightSurcharge() {
+ return isNightSurcharge;
+ }
+
+ public void setIsNightSurcharge(Boolean isNightSurcharge) {
+ this.isNightSurcharge = isNightSurcharge;
+ }
+
+ public Long getDistanceInMile() {
+ return distanceInMile;
+ }
+
+ public void setDistanceInMile(Long distanceInMile) {
+ this.distanceInMile = distanceInMile;
+ }
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/service/TaxiFareCalculatorService.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/service/TaxiFareCalculatorService.java
similarity index 96%
rename from spring-rest/src/main/java/com/baeldung/web/log/service/TaxiFareCalculatorService.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/service/TaxiFareCalculatorService.java
index 1176b31e4c..52a1698865 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/service/TaxiFareCalculatorService.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/service/TaxiFareCalculatorService.java
@@ -1,14 +1,14 @@
-package com.baeldung.web.log.service;
-
-import com.baeldung.web.log.data.TaxiRide;
-import org.springframework.stereotype.Service;
-
-@Service
-public class TaxiFareCalculatorService {
-
- public String calculateFare(TaxiRide taxiRide) {
- return String.valueOf((Long) (taxiRide.getIsNightSurcharge()
- ? taxiRide.getDistanceInMile() * 10 + 100
- : taxiRide.getDistanceInMile() * 10));
- }
-}
+package com.baeldung.web.log.service;
+
+import com.baeldung.web.log.data.TaxiRide;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TaxiFareCalculatorService {
+
+ public String calculateFare(TaxiRide taxiRide) {
+ return String.valueOf((Long) (taxiRide.getIsNightSurcharge()
+ ? taxiRide.getDistanceInMile() * 10 + 100
+ : taxiRide.getDistanceInMile() * 10));
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/log/util/RequestLoggingUtil.java b/spring-resttemplate/src/main/java/com/baeldung/web/log/util/RequestLoggingUtil.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/web/log/util/RequestLoggingUtil.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/log/util/RequestLoggingUtil.java
index c13d35b55c..70c4eaee90 100644
--- a/spring-rest/src/main/java/com/baeldung/web/log/util/RequestLoggingUtil.java
+++ b/spring-resttemplate/src/main/java/com/baeldung/web/log/util/RequestLoggingUtil.java
@@ -1,38 +1,38 @@
-package com.baeldung.web.log.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.io.IOUtils;
-import org.springframework.web.util.ContentCachingRequestWrapper;
-import org.springframework.web.util.WebUtils;
-
-public class RequestLoggingUtil {
-
- public static String getStringFromInputStream(InputStream is) {
- StringWriter writer = new StringWriter();
- String encoding = "UTF-8";
- try {
- IOUtils.copy(is, writer, encoding);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return writer.toString();
- }
-
- public static String readPayload(final HttpServletRequest request) throws IOException {
- String payloadData = null;
- ContentCachingRequestWrapper contentCachingRequestWrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
- if (null != contentCachingRequestWrapper) {
- byte[] buf = contentCachingRequestWrapper.getContentAsByteArray();
- if (buf.length > 0) {
- payloadData = new String(buf, 0, buf.length, contentCachingRequestWrapper.getCharacterEncoding());
- }
- }
- return payloadData;
- }
-
-}
+package com.baeldung.web.log.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+import org.springframework.web.util.WebUtils;
+
+public class RequestLoggingUtil {
+
+ public static String getStringFromInputStream(InputStream is) {
+ StringWriter writer = new StringWriter();
+ String encoding = "UTF-8";
+ try {
+ IOUtils.copy(is, writer, encoding);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return writer.toString();
+ }
+
+ public static String readPayload(final HttpServletRequest request) throws IOException {
+ String payloadData = null;
+ ContentCachingRequestWrapper contentCachingRequestWrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
+ if (null != contentCachingRequestWrapper) {
+ byte[] buf = contentCachingRequestWrapper.getContentAsByteArray();
+ if (buf.length > 0) {
+ payloadData = new String(buf, 0, buf.length, contentCachingRequestWrapper.getCharacterEncoding());
+ }
+ }
+ return payloadData;
+ }
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/web/upload/app/UploadApplication.java b/spring-resttemplate/src/main/java/com/baeldung/web/upload/app/UploadApplication.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/web/upload/app/UploadApplication.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/upload/app/UploadApplication.java
diff --git a/spring-rest/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java b/spring-resttemplate/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java
diff --git a/spring-rest/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java b/spring-resttemplate/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java
rename to spring-resttemplate/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java
diff --git a/spring-rest/src/test/java/com/baeldung/pact/PactProviderLiveTest.java b/spring-resttemplate/src/test/java/com/baeldung/pact/PactProviderLiveTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/pact/PactProviderLiveTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/pact/PactProviderLiveTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorUnitTest.java b/spring-resttemplate/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorUnitTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorUnitTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorUnitTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java b/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/web/controller/HeavyResourceControllerIntegrationTest.java b/spring-resttemplate/src/test/java/com/baeldung/web/controller/HeavyResourceControllerIntegrationTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/web/controller/HeavyResourceControllerIntegrationTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/web/controller/HeavyResourceControllerIntegrationTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/web/controller/TaxiFareControllerIntegrationTest.java b/spring-resttemplate/src/test/java/com/baeldung/web/controller/TaxiFareControllerIntegrationTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/web/controller/TaxiFareControllerIntegrationTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/web/controller/TaxiFareControllerIntegrationTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java b/spring-resttemplate/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java b/spring-resttemplate/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java
diff --git a/spring-rest/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java b/spring-resttemplate/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java
rename to spring-resttemplate/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java
diff --git a/spring-rest/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java b/spring-resttemplate/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java
similarity index 100%
rename from spring-rest/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java
rename to spring-resttemplate/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java
diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md
index d61a52070c..00bc2a1403 100644
--- a/spring-security-rest/README.md
+++ b/spring-security-rest/README.md
@@ -15,3 +15,4 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
- [Servlet 3 Async Support with Spring MVC and Spring Security](https://www.baeldung.com/spring-mvc-async-security)
- [Intro to Spring Security Expressions](https://www.baeldung.com/spring-security-expressions)
- [Spring Security for a REST API](https://www.baeldung.com/securing-a-restful-web-service-with-spring-security)
+- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic)
diff --git a/spring-vault/src/test/java/org/baeldung/springvault/VaultIntegrationTest.java b/spring-vault/src/test/java/org/baeldung/springvault/VaultIntegrationTest.java
index 75c700ee26..9f4b5d82a4 100644
--- a/spring-vault/src/test/java/org/baeldung/springvault/VaultIntegrationTest.java
+++ b/spring-vault/src/test/java/org/baeldung/springvault/VaultIntegrationTest.java
@@ -1,36 +1,28 @@
package org.baeldung.springvault;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
-import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.core.annotation.Order;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
-import org.springframework.vault.authentication.TokenAuthentication;
-import org.springframework.vault.client.VaultEndpoint;
-import org.springframework.vault.core.VaultTemplate;
-import org.springframework.vault.support.VaultResponse;
+import java.net.URISyntaxException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * These tests are requiring the {@code vault} command to be installed and available in the executing
+ * platform. So, if you intend to run them in your environment, the please install the vault and then
+ * run the ignored tests.
+ */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CredentialsService.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = VaultTestConfiguration.class, loader = AnnotationConfigContextLoader.class)
@@ -47,6 +39,7 @@ public class VaultIntegrationTest {
* @throws URISyntaxException
*/
@Test
+ @Ignore
public void givenCredentials_whenSecureCredentials_thenCredentialsSecured() throws URISyntaxException {
try {
// Given
@@ -63,9 +56,11 @@ public class VaultIntegrationTest {
/**
* Test to access credentials
+ *
* @throws URISyntaxException
*/
@Test
+ @Ignore
public void whenAccessCredentials_thenCredentialsRetrieved() throws URISyntaxException {
// Given
diff --git a/testing-modules/testing-libraries/README.md b/testing-modules/testing-libraries/README.md
index 7191989224..d76b7b1308 100644
--- a/testing-modules/testing-libraries/README.md
+++ b/testing-modules/testing-libraries/README.md
@@ -6,5 +6,7 @@
- [Cucumber and Scenario Outline](http://www.baeldung.com/cucumber-scenario-outline)
- [Cucumber Java 8 Support](http://www.baeldung.com/cucumber-java-8-support)
- [Introduction to Lambda Behave](http://www.baeldung.com/lambda-behave)
+- [Introduction to CheckStyle](https://www.baeldung.com/checkstyle-java)
+- [Introduction to FindBugs](https://www.baeldung.com/intro-to-findbugs)
diff --git a/spring-rest/checkstyle.xml b/testing-modules/testing-libraries/checkstyle.xml
similarity index 100%
rename from spring-rest/checkstyle.xml
rename to testing-modules/testing-libraries/checkstyle.xml
diff --git a/testing-modules/testing-libraries/pom.xml b/testing-modules/testing-libraries/pom.xml
index 7891ebbf6d..0838e81d14 100644
--- a/testing-modules/testing-libraries/pom.xml
+++ b/testing-modules/testing-libraries/pom.xml
@@ -35,11 +35,60 @@
${cucumber.version}
test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 2.2.0.RELEASE
+
+
+
+ testing-libraries
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${checkstyle-maven-plugin.version}
+
+ checkstyle.xml
+
+
+
+
+ check
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${checkstyle-maven-plugin.version}
+
+ checkstyle.xml
+
+
+
+
+
0.4
1.2.5
+ 3.0.0
diff --git a/testing-modules/testing-libraries/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java b/testing-modules/testing-libraries/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java
new file mode 100644
index 0000000000..7b57d35088
--- /dev/null
+++ b/testing-modules/testing-libraries/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java
@@ -0,0 +1,74 @@
+package com.baeldung.sampleapp.web.controller;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.baeldung.sampleapp.web.dto.Foo;
+
+// used to test HttpClientPostingTest
+@RestController
+public class SimplePostController {
+
+ @RequestMapping(value = "/users", method = RequestMethod.POST)
+ public String postUser(@RequestParam final String username, @RequestParam final String password) {
+ return "Success" + username;
+ }
+
+ @RequestMapping(value = "/users/detail", method = RequestMethod.POST)
+ public String postUserDetail(@RequestBody final Foo entity) {
+ return "Success" + entity.getId();
+ }
+
+ @RequestMapping(value = "/users/multipart", method = RequestMethod.POST)
+ public String uploadFile(@RequestParam final String username, @RequestParam final String password, @RequestParam("file") final MultipartFile file) {
+ if (!file.isEmpty()) {
+ try {
+ final DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
+ final String fileName = dateFormat.format(new Date());
+ final File fileServer = new File(fileName);
+ fileServer.createNewFile();
+ final byte[] bytes = file.getBytes();
+ final BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fileServer));
+ stream.write(bytes);
+ stream.close();
+ return "You successfully uploaded " + username;
+ } catch (final Exception e) {
+ return "You failed to upload " + e.getMessage();
+ }
+ } else {
+ return "You failed to upload because the file was empty.";
+ }
+ }
+
+ @RequestMapping(value = "/users/upload", method = RequestMethod.POST)
+ public String postMultipart(@RequestParam("file") final MultipartFile file) {
+ if (!file.isEmpty()) {
+ try {
+ final DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
+ final String fileName = dateFormat.format(new Date());
+ final File fileServer = new File(fileName);
+ fileServer.createNewFile();
+ final byte[] bytes = file.getBytes();
+ final BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fileServer));
+ stream.write(bytes);
+ stream.close();
+ return "You successfully uploaded ";
+ } catch (final Exception e) {
+ return "You failed to upload " + e.getMessage();
+ }
+ } else {
+ return "You failed to upload because the file was empty.";
+ }
+ }
+}
diff --git a/testing-modules/testing-libraries/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java b/testing-modules/testing-libraries/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java
new file mode 100644
index 0000000000..de1d76ed92
--- /dev/null
+++ b/testing-modules/testing-libraries/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java
@@ -0,0 +1,42 @@
+package com.baeldung.sampleapp.web.dto;
+
+public class Foo {
+ private long id;
+ private String name;
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ public Foo(final long id, final String name) {
+ super();
+
+ this.id = id;
+ this.name = name;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+}
\ No newline at end of file