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-collections-list-3/src/main/java/com/baeldung/list/DuplicatesCounter.java b/core-java-modules/core-java-collections-list-3/src/main/java/com/baeldung/list/duplicatescounter/DuplicatesCounter.java
similarity index 96%
rename from core-java-modules/core-java-collections-list-3/src/main/java/com/baeldung/list/DuplicatesCounter.java
rename to core-java-modules/core-java-collections-list-3/src/main/java/com/baeldung/list/duplicatescounter/DuplicatesCounter.java
index 04e24e5fa1..b5138eed7d 100644
--- a/core-java-modules/core-java-collections-list-3/src/main/java/com/baeldung/list/DuplicatesCounter.java
+++ b/core-java-modules/core-java-collections-list-3/src/main/java/com/baeldung/list/duplicatescounter/DuplicatesCounter.java
@@ -1,4 +1,4 @@
-package com.baeldung.list;
+package com.baeldung.list.duplicatescounter;
import java.util.HashMap;
import java.util.List;
diff --git a/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java b/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java
index cbc7136192..d41c12cd23 100644
--- a/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java
+++ b/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java
@@ -33,9 +33,9 @@ public class CollectionFilteringUnitTest {
for (Employee employee : originalList) {
for (String name : nameFilter) {
- if (employee.getName()
- .equalsIgnoreCase(name)) {
+ if (employee.getName().equals(name)) {
filteredList.add(employee);
+ //break;
}
}
}
diff --git a/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/DuplicatesCounterUnitTest.java b/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/duplicatescounter/DuplicatesCounterUnitTest.java
similarity index 97%
rename from core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/DuplicatesCounterUnitTest.java
rename to core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/duplicatescounter/DuplicatesCounterUnitTest.java
index 4b6a03aaef..be9ccded9b 100644
--- a/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/DuplicatesCounterUnitTest.java
+++ b/core-java-modules/core-java-collections-list-3/src/test/java/com/baeldung/list/duplicatescounter/DuplicatesCounterUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.list;
+package com.baeldung.list.duplicatescounter;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
diff --git a/core-java-modules/core-java-io-2/src/test/java/com/baeldung/file/FileClassDemoUnitTest.java b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/file/FileClassDemoUnitTest.java
index b60a12d208..322060fed8 100644
--- a/core-java-modules/core-java-io-2/src/test/java/com/baeldung/file/FileClassDemoUnitTest.java
+++ b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/file/FileClassDemoUnitTest.java
@@ -11,148 +11,171 @@ import static org.junit.Assert.*;
public class FileClassDemoUnitTest {
@Test
- public void givenDirectoryCreated_whenMkdirIsInvoked_thenDirectoryIsDeleted() {
- File directory = new File("testDirectory");
- if (!directory.isDirectory() || !directory.exists()) {
- directory.mkdir();
- }
-
+ public void givenDir_whenMkdir_thenDirIsDeleted() {
+ File directory = new File("dir");
+ assertTrue(directory.mkdir());
assertTrue(directory.delete());
}
@Test
- public void givenFileCreated_whenCreateNewFileIsInvoked_thenFileIsDeleted() throws IOException {
- File file = new File("testFile.txt");
- if (!file.isFile() || !file.exists()) {
- file.createNewFile();
+ public void givenFile_whenCreateNewFile_thenFileIsDeleted() {
+ File file = new File("file.txt");
+ try {
+ assertTrue(file.createNewFile());
+ } catch (IOException e) {
+ fail("Could not create " + "file.txt");
}
-
assertTrue(file.delete());
}
+ @Test
+ public void givenFile_whenCreateNewFile_thenMetadataIsCorrect() {
+
+ String sep = File.separator;
+
+ File parentDir = makeDir("filesDir");
+
+ File child = new File(parentDir, "file.txt");
+ try {
+ child.createNewFile();
+ } catch (IOException e) {
+ fail("Could not create " + "file.txt");
+ }
+
+ assertEquals("file.txt", child.getName());
+ assertEquals(parentDir.getName(), child.getParentFile().getName());
+ assertEquals(parentDir.getPath() + sep + "file.txt", child.getPath());
+
+ removeDir(parentDir);
+ }
+
@Test
- public void givenFileCreated_whenCreateNewFileInvoked_thenMetadataIsAsExpected() throws IOException {
+ public void givenReadOnlyFile_whenCreateNewFile_thenCantModFile() {
+ File parentDir = makeDir("readDir");
- // different Operating systems have different separator characters
- String separatorCharacter = System.getProperty("file.separator");
-
- File parentDirectory = makeDirectory("filesDirectory");
-
- File childFile = new File(parentDirectory, "file1.txt");
- childFile.createNewFile();
-
- assertTrue(childFile.getName().equals("file1.txt"));
- assertTrue(childFile.getParentFile().getName().equals(parentDirectory.getName()));
- assertTrue(childFile.getPath().equals(parentDirectory.getPath() + separatorCharacter + "file1.txt"));
-
- removeDirectory(parentDirectory);
- }
-
-
- @Test(expected = FileNotFoundException.class)
- public void givenReadOnlyFileCreated_whenCreateNewFileInvoked_thenFileCannotBeWrittenTo() throws IOException {
- File parentDirectory = makeDirectory("filesDirectory");
-
- File childFile = new File(parentDirectory, "file1.txt");
- childFile.createNewFile();
-
- childFile.setWritable(false);
-
- FileOutputStream fos = new FileOutputStream(childFile);
- fos.write("Hello World".getBytes()); // write operation
- fos.flush();
- fos.close();
-
- removeDirectory(parentDirectory);
- }
-
- @Test(expected = FileNotFoundException.class)
- public void givenWriteOnlyFileCreated_whenCreateNewFileInvoked_thenFileCannotBeReadFrom() throws IOException {
- File parentDirectory = makeDirectory("filesDirectory");
-
- File childFile = new File(parentDirectory, "file1.txt");
- childFile.createNewFile();
-
- childFile.setReadable(false);
-
- FileInputStream fis = new FileInputStream(childFile);
- fis.read(); // read operation
- fis.close();
-
- removeDirectory(parentDirectory);
+ File child = new File(parentDir, "file.txt");
+ try {
+ child.createNewFile();
+ } catch (IOException e) {
+ fail("Could not create " + "file.txt");
+ }
+ child.setWritable(false);
+ boolean writable = true;
+ try (FileOutputStream fos = new FileOutputStream(child)) {
+ fos.write("Hello World".getBytes()); // write operation
+ fos.flush();
+ } catch (IOException e) {
+ writable = false;
+ } finally {
+ removeDir(parentDir);
+ }
+ assertFalse(writable);
}
@Test
- public void givenFilesCreatedInDirectory_whenCreateNewFileInvoked_thenTheyCanBeListedAsExpected() throws IOException {
- File directory = makeDirectory("filtersDirectory");
+ public void givenWriteOnlyFile_whenCreateNewFile_thenCantReadFile() {
+ File parentDir = makeDir("writeDir");
- File csvFile = new File(directory, "csvFile.csv");
- csvFile.createNewFile();
+ File child = new File(parentDir, "file.txt");
+ try {
+ child.createNewFile();
+ } catch (IOException e) {
+ fail("Could not create " + "file.txt");
+ }
+ child.setReadable(false);
+ boolean readable = true;
+ try (FileInputStream fis = new FileInputStream(child)) {
+ fis.read(); // read operation
+ } catch (IOException e) {
+ readable = false;
+ } finally {
+ removeDir(parentDir);
+ }
+ assertFalse(readable);
+ }
- File txtFile = new File(directory, "txtFile.txt");
- txtFile.createNewFile();
+ @Test
+ public void givenFilesInDir_whenCreateNewFile_thenCanListFiles() {
+ File parentDir = makeDir("filtersDir");
+
+ String[] files = {"file1.csv", "file2.txt"};
+ for (String file : files) {
+ try {
+ new File(parentDir, file).createNewFile();
+ } catch (IOException e) {
+ fail("Could not create " + file);
+ }
+ }
//normal listing
- assertEquals(2, directory.list().length);
+ assertEquals(2, parentDir.list().length);
//filtered listing
FilenameFilter csvFilter = (dir, ext) -> ext.endsWith(".csv");
- assertEquals(1, directory.list(csvFilter).length);
+ assertEquals(1, parentDir.list(csvFilter).length);
- removeDirectory(directory);
+ removeDir(parentDir);
}
@Test
- public void givenDirectoryIsCreated_whenMkdirInvoked_thenDirectoryCanBeRenamed() {
+ public void givenDir_whenMkdir_thenCanRenameDir() {
- File source = makeDirectory("source");
- File destination = makeDirectory("destination");
- source.renameTo(destination);
+ File source = makeDir("source");
+ File destination = makeDir("destination");
+ boolean renamed = source.renameTo(destination);
- assertFalse(source.isDirectory());
- assertTrue(destination.isDirectory());
+ if (renamed) {
+ assertFalse(source.isDirectory());
+ assertTrue(destination.isDirectory());
- removeDirectory(destination);
+ removeDir(destination);
+ }
}
@Test
- public void givenDataIsWrittenToFile_whenWriteIsInvoked_thenFreeSpaceOnSystemDecreases() throws IOException {
+ public void givenDataWritten_whenWrite_thenFreeSpaceReduces() {
- String name = System.getProperty("user.home") + System.getProperty("file.separator") + "test";
- File testDir = makeDirectory(name);
+ String home = System.getProperty("user.home");
+ String sep = File.separator;
+ File testDir = makeDir(home + sep + "test");
File sample = new File(testDir, "sample.txt");
- long freeSpaceBeforeWrite = testDir.getFreeSpace();
- writeSampleDataToFile(sample);
+ long freeSpaceBefore = testDir.getFreeSpace();
+ try {
+ writeSampleDataToFile(sample);
+ } catch (IOException e) {
+ fail("Could not write to " + "sample.txt");
+ }
- long freeSpaceAfterWrite = testDir.getFreeSpace();
- assertTrue(freeSpaceAfterWrite < freeSpaceBeforeWrite);
+ long freeSpaceAfter = testDir.getFreeSpace();
+ assertTrue(freeSpaceAfter < freeSpaceBefore);
- removeDirectory(testDir);
+ removeDir(testDir);
}
- private static File makeDirectory(String directoryName) {
- File directory = new File(directoryName);
+ private static File makeDir(String name) {
+ File directory = new File(name);
directory.mkdir();
if (directory.isDirectory()) {
return directory;
}
- throw new RuntimeException("Directory not created for " + directoryName);
+ throw new RuntimeException("'" + name + "' not made!");
}
- private static void removeDirectory(File directory) {
+ private static void removeDir(File directory) {
// make sure you don't delete your home directory here
- if (directory.getPath().equals(System.getProperty("user.home"))) {
+ String home = System.getProperty("user.home");
+ if (directory.getPath().equals(home)) {
return;
}
// remove directory and its files from system
- if (directory != null && directory.exists()) {
+ if (directory.exists()) {
// delete all files inside the directory
- File[] filesInDirectory = directory.listFiles();
- if (filesInDirectory != null) {
- List files = Arrays.asList(filesInDirectory);
+ File[] dirFiles = directory.listFiles();
+ if (dirFiles != null) {
+ List files = Arrays.asList(dirFiles);
files.forEach(f -> deleteFile(f));
}
@@ -171,8 +194,8 @@ public class FileClassDemoUnitTest {
//write sample text to file
try (FileOutputStream out = new FileOutputStream(sample)) {
for (int i = 1; i <= 100000; i++) {
- String sampleText = "Sample line number " + i + "\n";
- out.write(sampleText.getBytes());
+ String text = "Sample line number " + i + "\n";
+ out.write(text.getBytes());
}
}
}
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 727bd2546c..b64a436957 100644
--- a/core-java-modules/core-java-nio/README.md
+++ b/core-java-modules/core-java-nio/README.md
@@ -5,4 +5,13 @@ This module contains articles about core Java non-blocking input and output (IO)
## Relevant Articles:
- [Determine File Creation Date in Java](https://www.baeldung.com/java-file-creation-date)
-- [Find the Number of Lines in a File Using Jav](https://www.baeldung.com/java-file-number-of-lines)
+- [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/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/debug/entity/Customer.java b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/debug/entity/Customer.java
new file mode 100644
index 0000000000..b8e1b6db5b
--- /dev/null
+++ b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/debug/entity/Customer.java
@@ -0,0 +1,19 @@
+package com.baeldung.streams.debug.entity;
+
+public class Customer {
+ private final String name;
+ private final int age;
+
+ public Customer(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+}
diff --git a/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/debug/Example1.java b/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/debug/Example1.java
new file mode 100644
index 0000000000..d8087bc98a
--- /dev/null
+++ b/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/debug/Example1.java
@@ -0,0 +1,18 @@
+package com.baeldung.streams.debug;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.stream.IntStream;
+
+import org.junit.Test;
+
+public class Example1 {
+ @Test
+ public void whenDebugging_thenInformationIsShown() {
+ int[] listOutputSorted = IntStream.of(-3, 10, -4, 1, 3)
+ .sorted()
+ .toArray();
+
+ assertThat(listOutputSorted).isSorted();
+ }
+}
diff --git a/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/debug/Example2.java b/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/debug/Example2.java
new file mode 100644
index 0000000000..56cbddf0b4
--- /dev/null
+++ b/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/debug/Example2.java
@@ -0,0 +1,36 @@
+package com.baeldung.streams.debug;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.junit.Test;
+
+import com.baeldung.streams.debug.entity.Customer;
+
+public class Example2 {
+ @Test
+ public void whenDebugging_thenInformationIsShown() {
+ List> customers = Arrays.asList(
+ Optional.of(new Customer("John P.", 15)),
+ Optional.of(new Customer("Sarah M.", 78)),
+ Optional.empty(),
+ Optional.of(new Customer("Mary T.", 20)),
+ Optional.empty(),
+ Optional.of(new Customer("Florian G.", 89)),
+ Optional.empty()
+ );
+
+ long numberOf65PlusCustomers = customers.stream()
+ .flatMap(c -> c.map(Stream::of)
+ .orElseGet(Stream::empty))
+ .mapToInt(Customer::getAge)
+ .filter(c -> c > 65)
+ .count();
+
+ assertThat(numberOf65PlusCustomers).isEqualTo(2);
+ }
+}
diff --git a/core-java-modules/core-java-string-algorithms-2/README.md b/core-java-modules/core-java-string-algorithms-2/README.md
index 2cd64e1920..94ace77d66 100644
--- a/core-java-modules/core-java-string-algorithms-2/README.md
+++ b/core-java-modules/core-java-string-algorithms-2/README.md
@@ -12,5 +12,5 @@ This module contains articles about string-related algorithms.
- [Pad a String with Zeros or Spaces in Java](https://www.baeldung.com/java-pad-string)
- [Remove Leading and Trailing Characters from a String](https://www.baeldung.com/java-remove-trailing-characters)
- [Counting Words in a String](https://www.baeldung.com/java-word-counting)
-- [Finding the Difference Between Two Strings](https://www.baeldung.com/java-difference-between-two-strings)
+- [Finding the Difference Between Two Strings in Java](https://www.baeldung.com/java-difference-between-two-strings)
- More articles: [[<-- prev]](../core-java-string-algorithms)
diff --git a/httpclient/README.md b/httpclient/README.md
index 678b195965..d88739e901 100644
--- a/httpclient/README.md
+++ b/httpclient/README.md
@@ -2,7 +2,7 @@
This module contains articles about HttpClient 4.x
-###The Course
+### The Course
The "REST With Spring" Classes: http://bit.ly/restwithspring
diff --git a/jackson/README.md b/jackson/README.md
index f96a569617..a62a788c41 100644
--- a/jackson/README.md
+++ b/jackson/README.md
@@ -2,10 +2,12 @@
This module contains articles about Jackson.
-###The Course
+### The Course
+
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
+
- [Jackson – Unmarshall to Collection/Array](https://www.baeldung.com/jackson-collection-array)
- [Jackson – Custom Serializer](https://www.baeldung.com/jackson-custom-serialization)
- [Getting Started with Custom Deserialization in Jackson](https://www.baeldung.com/jackson-deserialization)
@@ -24,7 +26,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Map Serialization and Deserialization with Jackson](https://www.baeldung.com/jackson-map)
- [Jackson Streaming API](https://www.baeldung.com/jackson-streaming-api)
- [Jackson – JsonMappingException (No serializer found for class)](https://www.baeldung.com/jackson-jsonmappingexception)
-- [How To Serialize Enums as JSON Objects with Jackson](https://www.baeldung.com/jackson-serialize-enums)
+- [How To Serialize and Deserialize Enums with Jackson](https://www.baeldung.com/jackson-serialize-enums)
- [Jackson – Marshall String to JsonNode](https://www.baeldung.com/jackson-json-to-jsonnode)
- [Jackson – Unmarshall to Collection/Array](https://www.baeldung.com/jackson-collection-array)
- [Serialize Only Fields that meet a Custom Criteria with Jackson](https://www.baeldung.com/jackson-serialize-field-custom-criteria)
diff --git a/java-jdi/README.md b/java-jdi/README.md
index c8c2d3e9ab..110906e845 100644
--- a/java-jdi/README.md
+++ b/java-jdi/README.md
@@ -2,6 +2,6 @@
This module contains articles about JDI, the Java Debug Interface.
-###Relevant articles
+### Relevant articles
- [An Intro to the Java Debug Interface (JDI)](https://www.baeldung.com/java-debug-interface)
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/mapstruct/README.md b/mapstruct/README.md
index f5a1e1a092..9887a7f43d 100644
--- a/mapstruct/README.md
+++ b/mapstruct/README.md
@@ -2,7 +2,8 @@
This module contains articles about MapStruct.
-###Relevant Articles:
+### Relevant Articles:
+
- [Quick Guide to MapStruct](https://www.baeldung.com/mapstruct)
- [Custom Mapper with MapStruct](https://www.baeldung.com/mapstruct-custom-mapper)
- [Using Multiple Source Objects with MapStruct](https://www.baeldung.com/mapstruct-multiple-source-objects)
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/persistence-modules/spring-data-cassandra-reactive/README.md b/persistence-modules/spring-data-cassandra-reactive/README.md
index 87a61d46b3..5352843850 100644
--- a/persistence-modules/spring-data-cassandra-reactive/README.md
+++ b/persistence-modules/spring-data-cassandra-reactive/README.md
@@ -1,3 +1,3 @@
-#Relevant Articles
+### Relevant Articles
- [Spring Data with Reactive Cassandra](https://www.baeldung.com/spring-data-cassandra-reactive)
diff --git a/pom.xml b/pom.xml
index 88aa7011d0..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
@@ -722,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
@@ -922,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
@@ -1180,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
@@ -1198,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
@@ -1467,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/spring-5/README.md b/spring-5/README.md
index 8a0cbe807e..857b199562 100644
--- a/spring-5/README.md
+++ b/spring-5/README.md
@@ -15,4 +15,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Spring ResponseStatusException](https://www.baeldung.com/spring-response-status-exception)
- [Spring Assert Statements](https://www.baeldung.com/spring-assert)
- [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari)
-- [Difference between vs ](https://www.baeldung.com/spring-contextannotation-contextcomponentscan)
+- [Difference between \ vs \](https://www.baeldung.com/spring-contextannotation-contextcomponentscan)
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/spring-boot-springdoc/src/main/resources/logback.xml b/spring-boot-springdoc/src/main/resources/logback.xml
new file mode 100644
index 0000000000..6a07b178e9
--- /dev/null
+++ b/spring-boot-springdoc/src/main/resources/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
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-cloud/spring-cloud-stream-starters/README.md b/spring-cloud/spring-cloud-stream-starters/README.md
index 761d54abbd..5b9b70e4f1 100644
--- a/spring-cloud/spring-cloud-stream-starters/README.md
+++ b/spring-cloud/spring-cloud-stream-starters/README.md
@@ -1,3 +1,3 @@
-#Revelant Articles:
+# Relevant Articles:
- [Using a Spring Cloud App Starter](http://www.baeldung.com/spring-cloud-app-starter)
diff --git a/spring-core-3/README.md b/spring-core-3/README.md
index 7ca95ae78e..1c5d911402 100644
--- a/spring-core-3/README.md
+++ b/spring-core-3/README.md
@@ -1,7 +1,7 @@
## Relevant Articles:
- [Understanding getBean() in Spring](https://www.baeldung.com/spring-getbean)
-- [Exploring the Spring BeanFactory API](https://www.baeldung.com/spring-beanfactory)
+- [Guide to the Spring BeanFactory](https://www.baeldung.com/spring-beanfactory)
- [How to use the Spring FactoryBean?](https://www.baeldung.com/spring-factorybean)
- [Spring – Injecting Collections](https://www.baeldung.com/spring-injecting-collections)
-- More articles: [[<-- prev]](/spring-core-2)
\ No newline at end of file
+- More articles: [[<-- prev]](/spring-core-2)
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-mvc-xml/README.md b/spring-mvc-xml/README.md
index 44a20e1527..0adf127aaa 100644
--- a/spring-mvc-xml/README.md
+++ b/spring-mvc-xml/README.md
@@ -2,10 +2,12 @@
This module contains articles about Spring MVC with XML configuration
-###The Course
+### The Course
+
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
+
- [Java Session Timeout](https://www.baeldung.com/servlet-session-timeout)
- [Returning Image/Media Data with Spring MVC](https://www.baeldung.com/spring-mvc-image-media-data)
- [Geolocation by IP in Java](https://www.baeldung.com/geolocation-by-ip-with-maxmind)
@@ -17,4 +19,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Debugging the Spring MVC 404 “No mapping found for HTTP request” Error](https://www.baeldung.com/spring-mvc-404-error)
## Spring MVC with XML Configuration Example Project
+
- access a sample jsp page at: `http://localhost:8080/spring-mvc-xml/sample.html`
diff --git a/spring-security-mvc-custom/README.md b/spring-security-mvc-custom/README.md
index 1a131f4c23..5eb6169f4b 100644
--- a/spring-security-mvc-custom/README.md
+++ b/spring-security-mvc-custom/README.md
@@ -2,10 +2,12 @@
This module contains articles about Spring Security with custom MVC applications
-###The Course
+### The Course
+
The "REST With Spring" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
+
- [Spring Security Remember Me](https://www.baeldung.com/spring-security-remember-me)
- [Redirect to different pages after Login with Spring Security](https://www.baeldung.com/spring_redirect_after_login)
- [Changing Spring Model Parameters with Handler Interceptor](https://www.baeldung.com/spring-model-parameters-with-handler-interceptor)
@@ -15,6 +17,7 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com
- [How to Manually Authenticate User with Spring Security](https://www.baeldung.com/manually-set-user-authentication-spring-security)
### Build the Project
+
```
mvn clean install
```
diff --git a/spring-security-mvc-digest-auth/README.md b/spring-security-mvc-digest-auth/README.md
index 0d36dbfd63..be06d63fc4 100644
--- a/spring-security-mvc-digest-auth/README.md
+++ b/spring-security-mvc-digest-auth/README.md
@@ -2,10 +2,12 @@
This module contains articles about digest authentication with Spring Security
-###The Course
+### The Course
+
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Article:
+
- [Spring Security Digest Authentication](https://www.baeldung.com/spring-security-digest-authentication)
- [RestTemplate with Digest Authentication](https://www.baeldung.com/resttemplate-digest-authentication)
diff --git a/spring-security-mvc-ldap/README.md b/spring-security-mvc-ldap/README.md
index 3230c0398a..288791b389 100644
--- a/spring-security-mvc-ldap/README.md
+++ b/spring-security-mvc-ldap/README.md
@@ -2,14 +2,17 @@
This module contains articles about Spring Security LDAP
-###The Course
+### The Course
+
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Article:
+
- [Spring Security – security none, filters none, access permitAll](https://www.baeldung.com/security-none-filters-none-access-permitAll)
- [Intro to Spring Security LDAP](https://www.baeldung.com/spring-security-ldap)
### Notes
+
- the project uses Spring Boot - simply run 'SampleLDAPApplication.java' to start up Spring Boot with a Tomcat container and embedded LDAP server.
- Once started, open 'http://localhost:8080'
- This will display the publicly available Home Page
diff --git a/spring-security-mvc-persisted-remember-me/README.md b/spring-security-mvc-persisted-remember-me/README.md
index e3003e89e2..e1208330a3 100644
--- a/spring-security-mvc-persisted-remember-me/README.md
+++ b/spring-security-mvc-persisted-remember-me/README.md
@@ -2,13 +2,16 @@
This module contains articles about 'remember me' with Spring Security
-###The Course
+### The Course
+
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
+
- [Spring Security – Persistent Remember Me](https://www.baeldung.com/spring-security-persistent-remember-me)
### Build the Project
+
```
mvn clean install
```
diff --git a/spring-security-mvc/README.md b/spring-security-mvc/README.md
index a458127c61..7d1a492cd3 100644
--- a/spring-security-mvc/README.md
+++ b/spring-security-mvc/README.md
@@ -2,15 +2,18 @@
This module contains articles about Spring Security in MVC applications
-###The Course
+### The Course
+
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
+
- [HttpSessionListener Example – Monitoring](https://www.baeldung.com/httpsessionlistener_with_metrics)
- [Control the Session with Spring Security](https://www.baeldung.com/spring-security-session)
### Build the Project
+
```
mvn clean install
```
diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md
index d12427a106..af6dd598cc 100644
--- a/spring-security-rest-basic-auth/README.md
+++ b/spring-security-rest-basic-auth/README.md
@@ -2,11 +2,12 @@
This module contains articles about basic authentication in RESTful APIs with Spring Security
-###The Course
+### The Course
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
+
- [Basic Authentication with the RestTemplate](https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring)
- [A Custom Filter in the Spring Security Filter Chain](https://www.baeldung.com/spring-security-custom-filter)
- [Spring Security Basic Authentication](https://www.baeldung.com/spring-security-basic-authentication)
diff --git a/spring-security-rest-custom/README.md b/spring-security-rest-custom/README.md
index 15cbc22b5f..be360e035e 100644
--- a/spring-security-rest-custom/README.md
+++ b/spring-security-rest-custom/README.md
@@ -2,10 +2,12 @@
This module contains articles about REST APIs with Spring Security
-###The Course
+### The Course
+
The "REST With Spring" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
+
- [Spring Security Authentication Provider](https://www.baeldung.com/spring-security-authentication-provider)
- [Retrieve User Information in Spring Security](https://www.baeldung.com/get-user-in-spring-security)
- [Spring Security – Run-As Authentication](https://www.baeldung.com/spring-security-run-as-auth)
diff --git a/testing-modules/rest-assured/README.md b/testing-modules/rest-assured/README.md
index 0012a63012..96d3c5e353 100644
--- a/testing-modules/rest-assured/README.md
+++ b/testing-modules/rest-assured/README.md
@@ -1,4 +1,5 @@
-###Relevant Articles:
+### Relevant Articles:
+
- [A Guide to REST-assured](http://www.baeldung.com/rest-assured-tutorial)
- [REST-assured Support for Spring MockMvc](https://www.baeldung.com/spring-mock-mvc-rest-assured)
- [Getting and Verifying Response Data with REST-assured](https://www.baeldung.com/rest-assured-response)
diff --git a/testing-modules/rest-testing/README.md b/testing-modules/rest-testing/README.md
index 2d366bd550..27e77e0f51 100644
--- a/testing-modules/rest-testing/README.md
+++ b/testing-modules/rest-testing/README.md
@@ -2,10 +2,12 @@
## REST Testing and Examples
-###The Course
+### The Course
+
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
+
- [Introduction to WireMock](http://www.baeldung.com/introduction-to-wiremock)
- [Using WireMock Scenarios](https://www.baeldung.com/wiremock-scenarios)
- [REST API Testing with Cucumber](http://www.baeldung.com/cucumber-rest-api-testing)
diff --git a/testing-modules/xmlunit-2/README.md b/testing-modules/xmlunit-2/README.md
index 72b683796e..55c2c651f2 100644
--- a/testing-modules/xmlunit-2/README.md
+++ b/testing-modules/xmlunit-2/README.md
@@ -1,2 +1,3 @@
-###Relevant Articles:
+### Relevant Articles:
+
- [Introduction To XMLUnit 2.x](http://www.baeldung.com/xmlunit2)