diff --git a/algorithms-miscellaneous-2/src/test/resources/graph.png b/algorithms-miscellaneous-2/src/test/resources/graph.png index 7165a51782..12af62c131 100644 Binary files a/algorithms-miscellaneous-2/src/test/resources/graph.png and b/algorithms-miscellaneous-2/src/test/resources/graph.png differ 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/balancedbinarytree/BalancedBinaryTree.java b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/balancedbinarytree/BalancedBinaryTree.java new file mode 100644 index 0000000000..84180473e2 --- /dev/null +++ b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/balancedbinarytree/BalancedBinaryTree.java @@ -0,0 +1,33 @@ +package com.baeldung.algorithms.balancedbinarytree; + +public class BalancedBinaryTree { + + public static boolean isBalanced(Tree tree) { + return isBalancedRecursive(tree, -1).isBalanced; + } + + private static Result isBalancedRecursive(Tree tree, int depth) { + if (tree == null) { + return new Result(true, -1); + } + + Result leftSubtreeResult = isBalancedRecursive(tree.left(), depth + 1); + Result rightSubtreeResult = isBalancedRecursive(tree.right(), depth + 1); + + boolean isBalanced = Math.abs(leftSubtreeResult.height - rightSubtreeResult.height) <= 1; + boolean subtreesAreBalanced = leftSubtreeResult.isBalanced && rightSubtreeResult.isBalanced; + int height = Math.max(leftSubtreeResult.height, rightSubtreeResult.height) + 1; + + return new Result(isBalanced && subtreesAreBalanced, height); + } + + private static final class Result { + private final boolean isBalanced; + private final int height; + + private Result(boolean isBalanced, int height) { + this.isBalanced = isBalanced; + this.height = height; + } + } +} diff --git a/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/balancedbinarytree/Tree.java b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/balancedbinarytree/Tree.java new file mode 100644 index 0000000000..8e091408c9 --- /dev/null +++ b/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/balancedbinarytree/Tree.java @@ -0,0 +1,34 @@ +package com.baeldung.algorithms.balancedbinarytree; + +public class Tree { + private final int value; + private final Tree left; + private final Tree right; + + public Tree(int value, Tree left, Tree right) { + this.value = value; + this.left = left; + this.right = right; + } + + public int value() { + return value; + } + + public Tree left() { + return left; + } + + public Tree right() { + return right; + } + + @Override + public String toString() { + return String.format("[%s, %s, %s]", + value, + left == null ? "null" : left.toString(), + right == null ? "null" : right.toString() + ); + } +} 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/balancedbinarytree/BalancedBinaryTreeUnitTest.java b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/balancedbinarytree/BalancedBinaryTreeUnitTest.java new file mode 100644 index 0000000000..25f313f991 --- /dev/null +++ b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/balancedbinarytree/BalancedBinaryTreeUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.algorithms.balancedbinarytree; + +import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +public class BalancedBinaryTreeUnitTest extends BinaryTreeDataProvider { + + @Test + public void givenBalancedTrees_whenCallingIsBalanced_ShouldReturnTrue() { + for (Tree tree : balancedTrees()) { + assertTrue(toString(tree) + " should be balanced", BalancedBinaryTree.isBalanced(tree)); + } + } + + @Test + public void givenUnbalancedTrees_whenCallingIsBalanced_ShouldReturnFalse() { + for (Tree tree : unbalancedTrees()) { + assertFalse(toString(tree) + " should not be balanced", BalancedBinaryTree.isBalanced(tree)); + } + } + + private String toString(Tree tree) { + return tree != null ? tree.toString() : "null"; + } +} diff --git a/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/balancedbinarytree/BinaryTreeDataProvider.java b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/balancedbinarytree/BinaryTreeDataProvider.java new file mode 100644 index 0000000000..3f4318afbc --- /dev/null +++ b/algorithms-miscellaneous-5/src/test/java/com/baeldung/algorithms/balancedbinarytree/BinaryTreeDataProvider.java @@ -0,0 +1,69 @@ +package com.baeldung.algorithms.balancedbinarytree; + +import java.util.Arrays; +import java.util.Collection; + +class BinaryTreeDataProvider { + + static Collection balancedTrees() { + return Arrays.asList( + null, + leaf(1), + tree(1, leaf(2), leaf(3)), + tree( + 1, + leaf(2), + tree(3, leaf(4), null) + ), + tree( + 1, + tree( + 2, + tree(3, leaf(4), null), + leaf(5) + ), + tree( + 6, + leaf(7), + tree(8, null, leaf(9)) + ) + ) + ); + } + + static Collection unbalancedTrees() { + return Arrays.asList( + tree( + 1, + tree(2, leaf(3), null), + null + ), + tree( + 1, + tree( + 2, + tree(3, leaf(4), leaf(5)), + null + ), + tree(6, leaf(7), null) + ), + tree( + 1, + tree(2, leaf(3), null), + tree( + 4, + tree(5, leaf(6), leaf(7)), + null + ) + ) + ); + } + + private static Tree leaf(int value) { + return new Tree(value, null, null); + } + + private static Tree tree(int value, Tree left, Tree right) { + return new Tree(value, left, right); + } +} 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/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-date-operations/pom.xml b/core-java-modules/core-java-date-operations/pom.xml new file mode 100644 index 0000000000..f6e75ca518 --- /dev/null +++ b/core-java-modules/core-java-date-operations/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + core-java-date-operations + ${project.parent.version} + 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-date-operations/src/main/java/com/baeldung/datetime/CalendarUtils.java b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/CalendarUtils.java new file mode 100644 index 0000000000..ab1550fd90 --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/CalendarUtils.java @@ -0,0 +1,15 @@ +package com.baeldung.datetime; + +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; + +public class CalendarUtils { + + public static Calendar getPlusDays(Date date, int amount) throws ParseException { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.DAY_OF_YEAR, amount); + return calendar; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/DateUtils.java b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/DateUtils.java new file mode 100644 index 0000000000..34f799d3f4 --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/DateUtils.java @@ -0,0 +1,20 @@ +package com.baeldung.datetime; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateUtils { + + public static Date getNow() { + return new Date(); + } + + public static Date getDate(long millis) { + return new Date(millis); + } + + public static Date getDate(String dateAsString, String pattern) throws ParseException { + return new SimpleDateFormat(pattern).parse(dateAsString); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/DateUtils.java b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/DateUtils.java new file mode 100644 index 0000000000..1b4e825df8 --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/DateUtils.java @@ -0,0 +1,21 @@ +package com.baeldung.datetime.sql; + +import java.sql.Date; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class DateUtils { + + public static Date getNow() { + return new Date(System.currentTimeMillis()); + } + + public static Date getDate(String dateAsString) { + return Date.valueOf(dateAsString); + } + + public static Date getDate(String dateAsString, String pattern) throws ParseException { + java.util.Date customUtilDate = new SimpleDateFormat(pattern).parse(dateAsString); + return new Date(customUtilDate.getTime()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/TimeUtils.java b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/TimeUtils.java new file mode 100644 index 0000000000..3fa1ffdef8 --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/TimeUtils.java @@ -0,0 +1,21 @@ +package com.baeldung.datetime.sql; + +import java.sql.Time; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class TimeUtils { + + public static Time getNow() { + return new Time(System.currentTimeMillis()); + } + + public static Time getTime(String timeAsString) { + return Time.valueOf(timeAsString); + } + + public static Time getTime(String dateAsString, String pattern) throws ParseException { + java.util.Date customUtilDate = new SimpleDateFormat(pattern).parse(dateAsString); + return new Time(customUtilDate.getTime()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/TimestampUtils.java b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/TimestampUtils.java new file mode 100644 index 0000000000..02a928daa7 --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/main/java/com/baeldung/datetime/sql/TimestampUtils.java @@ -0,0 +1,21 @@ +package com.baeldung.datetime.sql; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class TimestampUtils { + + public static Timestamp getNow() { + return new Timestamp(System.currentTimeMillis()); + } + + public static Timestamp getTimestamp(String timestampAsString) { + return Timestamp.valueOf(timestampAsString); + } + + public static Timestamp getTimestamp(String dateAsString, String pattern) throws ParseException { + java.util.Date customUtilDate = new SimpleDateFormat(pattern).parse(dateAsString); + return new Timestamp(customUtilDate.getTime()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/CalendarUtilsUnitTest.java b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/CalendarUtilsUnitTest.java new file mode 100644 index 0000000000..0060162ffb --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/CalendarUtilsUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.datetime; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.datetime.CalendarUtils; +import com.baeldung.datetime.DateUtils; + +import java.text.ParseException; +import java.util.Date; + +public class CalendarUtilsUnitTest { + + @Test + public void givenDateAndDaysToAdd_thenCalendarIsCorrectlyReturned() throws ParseException { + Date initialDate = DateUtils.getDate("2020/01/01", "yyyy/MM/dd"); + Date expectedDate= DateUtils.getDate("2020/01/11", "yyyy/MM/dd"); + assertEquals(expectedDate, CalendarUtils.getPlusDays(initialDate, 10).getTime()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/DateUtilsUnitTest.java b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/DateUtilsUnitTest.java new file mode 100644 index 0000000000..62a0fc0b4b --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/DateUtilsUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.datetime; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.datetime.DateUtils; + +import java.text.ParseException; +import java.util.Date; + +public class DateUtilsUnitTest { + + @Test + public void givenTimeMillis_thenDateIsReturned() { + Date now = DateUtils.getNow(); + assertEquals(DateUtils.getDate(now.getTime()), now); + } + + @Test + public void givenDateAndPattern_thenDateIsCorrectlyReturned() throws ParseException { + long milliseconds = new Date(2020 - 1900, 0, 1).getTime(); + assertEquals(DateUtils.getDate(milliseconds), DateUtils.getDate("2020/01/01", "yyyy/MM/dd")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/DateUtilsUnitTest.java b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/DateUtilsUnitTest.java new file mode 100644 index 0000000000..a04f64f6dd --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/DateUtilsUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.datetime.sql; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.datetime.sql.DateUtils; + +import java.text.ParseException; +import java.util.Date; + +public class DateUtilsUnitTest { + + @Test + public void givenCurrentDate_thenTodayIsReturned() { + assertEquals(DateUtils.getNow(), new Date()); + } + + @Test(expected = IllegalArgumentException.class) + public void givenDateAsString_whenPatternIsNotRespected_thenExceptionIsThrown() { + DateUtils.getDate("2020 01 01"); + } + + @Test + public void givenDateAndPattern_thenDateIsCorrectlyReturned() throws ParseException { + assertEquals(DateUtils.getDate("2020-01-01"), DateUtils.getDate("2020/01/01", "yyyy/MM/dd")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/TimeUtilsUnitTest.java b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/TimeUtilsUnitTest.java new file mode 100644 index 0000000000..6b49558f1b --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/TimeUtilsUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.datetime.sql; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.datetime.sql.TimeUtils; + +import java.text.ParseException; +import java.util.Date; + +public class TimeUtilsUnitTest { + + @Test + public void givenCurrentTime_thenNowIsReturned() { + assertEquals(TimeUtils.getNow(), new Date()); + } + + @Test(expected = IllegalArgumentException.class) + public void givenTimeAsString_whenPatternIsNotRespected_thenExceptionIsThrown() { + TimeUtils.getTime("10 11 12"); + } + + @Test + public void givenTimeAndPattern_thenTimeIsCorrectlyReturned() throws ParseException { + assertEquals(TimeUtils.getTime("10:11:12"), TimeUtils.getTime("10 11 12", "hh mm ss")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/TimestampUtilsUnitTest.java b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/TimestampUtilsUnitTest.java new file mode 100644 index 0000000000..2faf8fab0e --- /dev/null +++ b/core-java-modules/core-java-date-operations/src/test/java/com/baeldung/datetime/sql/TimestampUtilsUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.datetime.sql; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.datetime.sql.TimestampUtils; + +import java.text.ParseException; +import java.util.Date; + +public class TimestampUtilsUnitTest { + + @Test + public void givenCurrentTimestamp_thenNowIsReturned() { + assertEquals(TimestampUtils.getNow() + .getTime(), new Date().getTime()); + } + + @Test(expected = IllegalArgumentException.class) + public void givenTimestampAsString_whenPatternIsNotRespected_thenExceptionIsThrown() { + TimestampUtils.getTimestamp("2020/01/01 10:11-12"); + } + + @Test + public void givenTimestampAndPattern_thenTimestampIsCorrectlyReturned() throws ParseException { + assertEquals(TimestampUtils.getTimestamp("2020-01-01 10:11:12"), TimestampUtils.getTimestamp("2020/01/01 10:11-12", "yyyy/MM/dd hh:mm-ss")); + } +} \ 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 56c966349f..b1ca877ae0 100644 --- a/core-java-modules/core-java-lang-oop-3/README.md +++ b/core-java-modules/core-java-lang-oop-3/README.md @@ -13,4 +13,4 @@ This module contains articles about Object-oriented programming (OOP) in Java - [A Guide to Inner Interfaces in Java](https://www.baeldung.com/java-inner-interfaces) - [Java Classes and Objects](https://www.baeldung.com/java-classes-objects) - [Java Interfaces](https://www.baeldung.com/java-interfaces) -- [[<-- Prev]](/core-java-modules/core-java-lang-oop-2)[[More -->]](/core-java-modules/core-java-lang-oop-4) +- [[<-- Prev]](/core-java-modules/core-java-lang-oop-2)[[More -->]](/core-java-modules/core-java-lang-oop-4) \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-4/README.md b/core-java-modules/core-java-lang-oop-4/README.md index 8fab6e3cef..51650dc1f6 100644 --- a/core-java-modules/core-java-lang-oop-4/README.md +++ b/core-java-modules/core-java-lang-oop-4/README.md @@ -6,4 +6,4 @@ This module contains articles about Object-oriented programming (OOP) in Java - [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding) - [Methods in Java](https://www.baeldung.com/java-methods) - [Java ‘private’ Access Modifier](https://www.baeldung.com/java-private-keyword) -- [[<-- Prev]](/core-java-modules/core-java-lang-oop-3) +- [[<-- Prev]](/core-java-modules/core-java-lang-oop-3) \ No newline at end of file diff --git a/java-strings/src/test/java/com/baeldung/string/StringUnitTest.java b/core-java-modules/core-java-string-apis/src/test/java/com/baeldung/stringapi/StringUnitTest.java similarity index 96% rename from java-strings/src/test/java/com/baeldung/string/StringUnitTest.java rename to core-java-modules/core-java-string-apis/src/test/java/com/baeldung/stringapi/StringUnitTest.java index 0d4fd6eff9..5c1fe2fbda 100644 --- a/java-strings/src/test/java/com/baeldung/string/StringUnitTest.java +++ b/core-java-modules/core-java-string-apis/src/test/java/com/baeldung/stringapi/StringUnitTest.java @@ -1,16 +1,13 @@ -package com.baeldung.string; +package com.baeldung.stringapi; -import static org.junit.Assert.assertArrayEquals; -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.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.IllegalFormatException; import java.util.regex.PatternSyntaxException; -import org.junit.Test; +import static org.junit.Assert.*; public class StringUnitTest { diff --git a/core-java-modules/core-java-strings/README.md b/core-java-modules/core-java-strings/README.md new file mode 100644 index 0000000000..4a418db29f --- /dev/null +++ b/core-java-modules/core-java-strings/README.md @@ -0,0 +1,14 @@ +## Java Strings + +This module contains articles about strings in Java. + +### Relevant Articles: +- [Use char[] Array over a String for Manipulating Passwords in Java?](https://www.baeldung.com/java-storing-passwords) +- [Compact Strings in Java 9](https://www.baeldung.com/java-9-compact-string) +- [String Not Empty Test Assertions in Java](https://www.baeldung.com/java-assert-string-not-empty) +- [String Performance Hints](https://www.baeldung.com/java-string-performance) +- [Java Localization – Formatting Messages](https://www.baeldung.com/java-localization-messages-formatting) +- [Java – Generate Random String](https://www.baeldung.com/java-random-string) +- [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions) +- [Java Multi-line String](https://www.baeldung.com/java-multiline-string) +- [Guide to Java String Pool](https://www.baeldung.com/java-string-pool) diff --git a/core-java-modules/core-java-strings/pom.xml b/core-java-modules/core-java-strings/pom.xml new file mode 100644 index 0000000000..6a80886549 --- /dev/null +++ b/core-java-modules/core-java-strings/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + core-java-strings + 0.1.0-SNAPSHOT + jar + core-java-strings + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator.version} + + + com.ibm.icu + icu4j + ${icu4j.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + core-java-strings + + + src/main/resources + true + + + + + + 3.6.1 + 61.1 + + + diff --git a/java-strings/src/main/java/com/baeldung/java9/compactstring/CompactStringDemo.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/java9/compactstring/CompactStringDemo.java similarity index 97% rename from java-strings/src/main/java/com/baeldung/java9/compactstring/CompactStringDemo.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/java9/compactstring/CompactStringDemo.java index cb24511f72..eae75eaa2b 100644 --- a/java-strings/src/main/java/com/baeldung/java9/compactstring/CompactStringDemo.java +++ b/core-java-modules/core-java-strings/src/main/java/com/baeldung/java9/compactstring/CompactStringDemo.java @@ -1,9 +1,10 @@ package com.baeldung.java9.compactstring; import java.util.List; -import static java.util.stream.Collectors.toList; import java.util.stream.IntStream; +import static java.util.stream.Collectors.toList; + public class CompactStringDemo { public static void main(String[] args) { @@ -11,14 +12,14 @@ public class CompactStringDemo { List strings = IntStream.rangeClosed(1, 10_000_000) .mapToObj(Integer::toString).collect(toList()); long totalTime = System.currentTimeMillis() - startTime; - System.out.println("Generated " + strings.size() + " strings in " + System.out.println("Generated " + strings.size() + " strings in " + totalTime + " ms."); startTime = System.currentTimeMillis(); String appended = (String) strings.stream().limit(100_000) .reduce("", (left, right) -> left.toString() + right.toString()); totalTime = System.currentTimeMillis() - startTime; - System.out.println("Created string of length " + appended.length() + System.out.println("Created string of length " + appended.length() + " in " + totalTime + " ms."); } } diff --git a/java-strings-2/src/main/java/com/baeldung/localization/App.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/App.java similarity index 100% rename from java-strings-2/src/main/java/com/baeldung/localization/App.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/App.java diff --git a/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/ICUFormat.java similarity index 100% rename from java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/ICUFormat.java index f7bc357933..c82af30c87 100644 --- a/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java +++ b/core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/ICUFormat.java @@ -1,11 +1,11 @@ package com.baeldung.localization; +import com.ibm.icu.text.MessageFormat; + import java.util.List; import java.util.Locale; import java.util.ResourceBundle; -import com.ibm.icu.text.MessageFormat; - public class ICUFormat { public static String getLabel(Locale locale, Object[] data) { diff --git a/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/JavaSEFormat.java similarity index 100% rename from java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/JavaSEFormat.java diff --git a/java-strings-2/src/main/java/com/baeldung/localization/Localization.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/Localization.java similarity index 100% rename from java-strings-2/src/main/java/com/baeldung/localization/Localization.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/localization/Localization.java diff --git a/java-strings-2/src/main/java/com/baeldung/string/multiline/MultiLineString.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java similarity index 98% rename from java-strings-2/src/main/java/com/baeldung/string/multiline/MultiLineString.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java index 1bde2dcb63..987bc751cd 100644 --- a/java-strings-2/src/main/java/com/baeldung/string/multiline/MultiLineString.java +++ b/core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java @@ -1,4 +1,7 @@ -package com.baeldung.string.multiline; +package com.baeldung.multiline; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import java.io.IOException; import java.io.PrintWriter; @@ -6,9 +9,6 @@ import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Paths; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; - public class MultiLineString { String newLine = System.getProperty("line.separator"); diff --git a/java-strings/src/main/java/com/baeldung/string/StringPerformance.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/stringperformance/StringPerformance.java similarity index 99% rename from java-strings/src/main/java/com/baeldung/string/StringPerformance.java rename to core-java-modules/core-java-strings/src/main/java/com/baeldung/stringperformance/StringPerformance.java index 3b0c32991c..8e9d3afdde 100644 --- a/java-strings/src/main/java/com/baeldung/string/StringPerformance.java +++ b/core-java-modules/core-java-strings/src/main/java/com/baeldung/stringperformance/StringPerformance.java @@ -1,4 +1,4 @@ -package com.baeldung.string; +package com.baeldung.stringperformance; import com.google.common.base.Splitter; import org.apache.commons.lang3.StringUtils; diff --git a/java-strings-2/src/main/resources/formats_en.properties b/core-java-modules/core-java-strings/src/main/resources/formats_en.properties similarity index 100% rename from java-strings-2/src/main/resources/formats_en.properties rename to core-java-modules/core-java-strings/src/main/resources/formats_en.properties diff --git a/java-strings-2/src/main/resources/formats_fr.properties b/core-java-modules/core-java-strings/src/main/resources/formats_fr.properties similarity index 100% rename from java-strings-2/src/main/resources/formats_fr.properties rename to core-java-modules/core-java-strings/src/main/resources/formats_fr.properties diff --git a/java-strings-2/src/main/resources/formats_it.properties b/core-java-modules/core-java-strings/src/main/resources/formats_it.properties similarity index 100% rename from java-strings-2/src/main/resources/formats_it.properties rename to core-java-modules/core-java-strings/src/main/resources/formats_it.properties diff --git a/java-strings-2/src/main/resources/formats_pl.properties b/core-java-modules/core-java-strings/src/main/resources/formats_pl.properties similarity index 100% rename from java-strings-2/src/main/resources/formats_pl.properties rename to core-java-modules/core-java-strings/src/main/resources/formats_pl.properties diff --git a/java-strings-2/src/main/resources/logback.xml b/core-java-modules/core-java-strings/src/main/resources/logback.xml similarity index 100% rename from java-strings-2/src/main/resources/logback.xml rename to core-java-modules/core-java-strings/src/main/resources/logback.xml diff --git a/java-strings-2/src/main/resources/messages_en.properties b/core-java-modules/core-java-strings/src/main/resources/messages_en.properties similarity index 100% rename from java-strings-2/src/main/resources/messages_en.properties rename to core-java-modules/core-java-strings/src/main/resources/messages_en.properties diff --git a/java-strings-2/src/main/resources/messages_fr.properties b/core-java-modules/core-java-strings/src/main/resources/messages_fr.properties similarity index 100% rename from java-strings-2/src/main/resources/messages_fr.properties rename to core-java-modules/core-java-strings/src/main/resources/messages_fr.properties diff --git a/java-strings-2/src/main/resources/messages_it.properties b/core-java-modules/core-java-strings/src/main/resources/messages_it.properties similarity index 100% rename from java-strings-2/src/main/resources/messages_it.properties rename to core-java-modules/core-java-strings/src/main/resources/messages_it.properties diff --git a/java-strings-2/src/main/resources/messages_pl.properties b/core-java-modules/core-java-strings/src/main/resources/messages_pl.properties similarity index 100% rename from java-strings-2/src/main/resources/messages_pl.properties rename to core-java-modules/core-java-strings/src/main/resources/messages_pl.properties diff --git a/java-strings-2/src/main/resources/stephenking.txt b/core-java-modules/core-java-strings/src/main/resources/stephenking.txt similarity index 100% rename from java-strings-2/src/main/resources/stephenking.txt rename to core-java-modules/core-java-strings/src/main/resources/stephenking.txt diff --git a/java-strings/src/test/java/com/baeldung/chararraypassword/PasswordStoreExamplesUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/chararraypassword/PasswordStoreExamplesUnitTest.java similarity index 100% rename from java-strings/src/test/java/com/baeldung/chararraypassword/PasswordStoreExamplesUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/chararraypassword/PasswordStoreExamplesUnitTest.java diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/LocaleUnitTest.java similarity index 93% rename from java-strings-2/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/LocaleUnitTest.java index 1d221056fd..5655d2536d 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/LocaleUnitTest.java @@ -1,11 +1,12 @@ -package com.baeldung.string.interview; +package com.baeldung.interview; + +import org.junit.Test; import java.math.BigDecimal; import java.text.NumberFormat; import java.util.Locale; -import static org.junit.Assert.assertEquals; -import org.junit.Test; +import static org.junit.Assert.assertEquals; public class LocaleUnitTest { @Test diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringAnagramUnitTest.java similarity index 94% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringAnagramUnitTest.java index aadfade737..8f3bacc267 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringAnagramUnitTest.java @@ -1,10 +1,10 @@ -package com.baeldung.string.interview; +package com.baeldung.interview; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; import java.util.Arrays; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; public class StringAnagramUnitTest { public boolean isAnagram(String s1, String s2) { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringChangeCaseUnitTest.java similarity index 92% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringChangeCaseUnitTest.java index 2c7ec500fe..4c3815a2e4 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringChangeCaseUnitTest.java @@ -1,9 +1,9 @@ -package com.baeldung.string.interview; - -import static org.junit.Assert.assertEquals; +package com.baeldung.interview; import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class StringChangeCaseUnitTest { @Test public void givenString_whenChangingToUppercase_thenCaseChanged() { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringCountOccurrencesUnitTest.java similarity index 94% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringCountOccurrencesUnitTest.java index 6c17643ac8..cb92c06d32 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringCountOccurrencesUnitTest.java @@ -1,9 +1,9 @@ -package com.baeldung.string.interview; - -import static org.junit.Assert.assertEquals; +package com.baeldung.interview; import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class StringCountOccurrencesUnitTest { public int countOccurrences(String s, char c) { int count = 0; diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringFormatUnitTest.java similarity index 90% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringFormatUnitTest.java index 787017791c..8492db0dc0 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringFormatUnitTest.java @@ -1,9 +1,9 @@ -package com.baeldung.string.interview; - -import static org.junit.Assert.assertEquals; +package com.baeldung.interview; import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class StringFormatUnitTest { @Test public void givenString_whenUsingStringFormat_thenStringFormatted() { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringInternUnitTest.java similarity index 91% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringInternUnitTest.java index c5bffb7573..3092a72399 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringInternUnitTest.java @@ -1,9 +1,9 @@ -package com.baeldung.string.interview; - -import static org.assertj.core.api.Assertions.assertThat; +package com.baeldung.interview; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + public class StringInternUnitTest { @Test public void whenCallingStringIntern_thenStringsInterned() { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringJoinerUnitTest.java similarity index 91% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringJoinerUnitTest.java index d44c7478e4..b5556f588c 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringJoinerUnitTest.java @@ -1,10 +1,11 @@ -package com.baeldung.string.interview; - -import java.util.StringJoiner; -import static org.junit.Assert.assertEquals; +package com.baeldung.interview; import org.junit.Test; +import java.util.StringJoiner; + +import static org.junit.Assert.assertEquals; + public class StringJoinerUnitTest { @Test public void whenUsingStringJoiner_thenStringsJoined() { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringPalindromeUnitTest.java similarity index 95% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringPalindromeUnitTest.java index 79ed14cd99..760939932a 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringPalindromeUnitTest.java @@ -1,9 +1,9 @@ -package com.baeldung.string.interview; - -import static org.assertj.core.api.Assertions.assertThat; +package com.baeldung.interview; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + public class StringPalindromeUnitTest { public boolean isPalindrome(String text) { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringReverseUnitTest.java similarity index 88% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringReverseUnitTest.java index bb9b45dc97..484a6d0d68 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringReverseUnitTest.java @@ -1,9 +1,9 @@ -package com.baeldung.string.interview; - -import static org.junit.Assert.assertEquals; +package com.baeldung.interview; import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class StringReverseUnitTest { @Test public void whenUsingInbuildMethods_thenStringReversed() { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringSplitUnitTest.java similarity index 95% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringSplitUnitTest.java index e1cea62462..5aff593e3e 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringSplitUnitTest.java @@ -1,7 +1,8 @@ -package com.baeldung.string.interview; +package com.baeldung.interview; import org.apache.commons.lang3.StringUtils; import org.junit.Test; + import static org.junit.Assert.assertArrayEquals; public class StringSplitUnitTest { diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToByteArrayUnitTest.java similarity index 95% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToByteArrayUnitTest.java index aee4eedcd6..90c5ca25c2 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToByteArrayUnitTest.java @@ -1,11 +1,11 @@ -package com.baeldung.string.interview; +package com.baeldung.interview; -import static org.junit.Assert.assertArrayEquals; +import org.junit.Test; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; -import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; public class StringToByteArrayUnitTest { @Test diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToCharArrayUnitTest.java similarity index 91% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToCharArrayUnitTest.java index 1322d0fa82..5ebd7448f1 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToCharArrayUnitTest.java @@ -1,10 +1,10 @@ -package com.baeldung.string.interview; +package com.baeldung.interview; -import static org.junit.Assert.assertEquals; +import org.junit.Test; import java.util.Arrays; -import org.junit.Test; +import static org.junit.Assert.assertEquals; public class StringToCharArrayUnitTest { @Test diff --git a/java-strings-2/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToIntegerUnitTest.java similarity index 89% rename from java-strings-2/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToIntegerUnitTest.java index a905438a84..24a715dc75 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/interview/StringToIntegerUnitTest.java @@ -1,6 +1,7 @@ -package com.baeldung.string.interview; +package com.baeldung.interview; import org.junit.Test; + import static org.assertj.core.api.Assertions.assertThat; public class StringToIntegerUnitTest { diff --git a/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java similarity index 98% rename from java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java index 2c8f9b47f3..3c5c5fcb55 100644 --- a/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java @@ -1,12 +1,10 @@ package com.baeldung.localization; -import static org.junit.Assert.assertEquals; - -import java.util.Locale; - import org.junit.Test; -import com.baeldung.localization.ICUFormat; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; public class ICUFormatUnitTest { diff --git a/java-strings-2/src/test/java/com/baeldung/string/multiline/MultiLineStringUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java similarity index 85% rename from java-strings-2/src/test/java/com/baeldung/string/multiline/MultiLineStringUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java index 3ebee9b5d1..04d318c71b 100644 --- a/java-strings-2/src/test/java/com/baeldung/string/multiline/MultiLineStringUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java @@ -1,11 +1,10 @@ -package com.baeldung.string.multiline; +package com.baeldung.multiline; import org.junit.Test; -import static org.junit.Assert.assertEquals; import java.io.IOException; -import com.baeldung.string.multiline.MultiLineString; +import static org.junit.Assert.assertEquals; public class MultiLineStringUnitTest { diff --git a/core-java-modules/core-java-strings/src/test/java/com/baeldung/randomstrings/RandomStringsUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/randomstrings/RandomStringsUnitTest.java new file mode 100644 index 0000000000..2806635d03 --- /dev/null +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/randomstrings/RandomStringsUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.randomstrings; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.Charset; +import java.util.Random; + +public class RandomStringsUnitTest { + + private static final Logger LOG = LoggerFactory.getLogger(RandomStringsUnitTest.class); + + @Test + public void givenUsingPlainJava_whenGeneratingRandomStringUnbounded_thenCorrect() { + final byte[] array = new byte[7]; // length is bounded by 7 + new Random().nextBytes(array); + final String generatedString = new String(array, Charset.forName("UTF-8")); + + LOG.debug(generatedString); + } + + @Test + public void givenUsingPlainJava_whenGeneratingRandomStringBounded_thenCorrect() { + final int leftLimit = 97; // letter 'a' + final int rightLimit = 122; // letter 'z' + final int targetStringLength = 10; + final Random random = new Random(); + final StringBuilder buffer = new StringBuilder(targetStringLength); + + for (int i = 0; i < targetStringLength; i++) { + final int randomLimitedInt = leftLimit + (int) (random.nextFloat() * (rightLimit - leftLimit + 1)); + buffer.append((char) randomLimitedInt); + } + final String generatedString = buffer.toString(); + + LOG.debug(generatedString); + } + + @Test + public void givenUsingApache_whenGeneratingRandomString_thenCorrect() { + final String generatedString = RandomStringUtils.random(10); + + LOG.debug(generatedString); + } + + @Test + public void givenUsingApache_whenGeneratingRandomAlphabeticString_thenCorrect() { + final String generatedString = RandomStringUtils.randomAlphabetic(10); + + LOG.debug(generatedString); + } + + @Test + public void givenUsingApache_whenGeneratingRandomAlphanumericString_thenCorrect() { + final String generatedString = RandomStringUtils.randomAlphanumeric(10); + + LOG.debug(generatedString); + } + + @Test + public void givenUsingApache_whenGeneratingRandomStringBounded_thenCorrect() { + final int length = 10; + final boolean useLetters = true; + final boolean useNumbers = false; + final String generatedString = RandomStringUtils.random(length, useLetters, useNumbers); + + LOG.debug(generatedString); + } + +} diff --git a/java-strings/src/test/java/com/baeldung/string/StringEmptyUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/stringnotempty/StringNotEmptyUnitTest.java similarity index 81% rename from java-strings/src/test/java/com/baeldung/string/StringEmptyUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/stringnotempty/StringNotEmptyUnitTest.java index 17b13f89de..482105cc40 100644 --- a/java-strings/src/test/java/com/baeldung/string/StringEmptyUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/stringnotempty/StringNotEmptyUnitTest.java @@ -1,21 +1,16 @@ -package com.baeldung.string; - -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString; -import static org.hamcrest.text.IsEmptyString.isEmptyString; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +package com.baeldung.stringnotempty; +import com.google.common.base.Strings; import org.apache.commons.lang3.StringUtils; import org.assertj.core.api.Assertions; import org.junit.Test; -import com.google.common.base.Strings; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString; +import static org.hamcrest.text.IsEmptyString.isEmptyString; +import static org.junit.Assert.*; -public class StringEmptyUnitTest { +public class StringNotEmptyUnitTest { private String text = "baeldung"; diff --git a/java-strings-ops/src/test/java/com/baeldung/stringpool/StringPoolUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/stringpool/StringPoolUnitTest.java similarity index 100% rename from java-strings-ops/src/test/java/com/baeldung/stringpool/StringPoolUnitTest.java rename to core-java-modules/core-java-strings/src/test/java/com/baeldung/stringpool/StringPoolUnitTest.java diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 68ece1c473..16ec19835a 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -19,6 +19,7 @@ core-java-lang-operators core-java-networking-2 core-java-security-manager + core-java-date-operations diff --git a/java-strings-2/src/test/java/com/baeldung/random/JavaRandomUnitTest.java b/java-numbers/src/test/java/com/baeldung/random/JavaRandomUnitTest.java similarity index 69% rename from java-strings-2/src/test/java/com/baeldung/random/JavaRandomUnitTest.java rename to java-numbers/src/test/java/com/baeldung/random/JavaRandomUnitTest.java index 2273dfda13..de37b8d1e3 100644 --- a/java-strings-2/src/test/java/com/baeldung/random/JavaRandomUnitTest.java +++ b/java-numbers/src/test/java/com/baeldung/random/JavaRandomUnitTest.java @@ -1,12 +1,10 @@ package com.baeldung.random; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.math3.random.RandomDataGenerator; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.nio.charset.Charset; import java.util.Random; public class JavaRandomUnitTest { @@ -155,63 +153,4 @@ public class JavaRandomUnitTest { LOG.debug("{}", generatedDouble); } - // tests - random String - - @Test - public void givenUsingPlainJava_whenGeneratingRandomStringUnbounded_thenCorrect() { - final byte[] array = new byte[7]; // length is bounded by 7 - new Random().nextBytes(array); - final String generatedString = new String(array, Charset.forName("UTF-8")); - - LOG.debug(generatedString); - } - - @Test - public void givenUsingPlainJava_whenGeneratingRandomStringBounded_thenCorrect() { - final int leftLimit = 97; // letter 'a' - final int rightLimit = 122; // letter 'z' - final int targetStringLength = 10; - final Random random = new Random(); - final StringBuilder buffer = new StringBuilder(targetStringLength); - - for (int i = 0; i < targetStringLength; i++) { - final int randomLimitedInt = leftLimit + (int) (random.nextFloat() * (rightLimit - leftLimit + 1)); - buffer.append((char) randomLimitedInt); - } - final String generatedString = buffer.toString(); - - LOG.debug(generatedString); - } - - @Test - public void givenUsingApache_whenGeneratingRandomString_thenCorrect() { - final String generatedString = RandomStringUtils.random(10); - - LOG.debug(generatedString); - } - - @Test - public void givenUsingApache_whenGeneratingRandomAlphabeticString_thenCorrect() { - final String generatedString = RandomStringUtils.randomAlphabetic(10); - - LOG.debug(generatedString); - } - - @Test - public void givenUsingApache_whenGeneratingRandomAlphanumericString_thenCorrect() { - final String generatedString = RandomStringUtils.randomAlphanumeric(10); - - LOG.debug(generatedString); - } - - @Test - public void givenUsingApache_whenGeneratingRandomStringBounded_thenCorrect() { - final int length = 10; - final boolean useLetters = true; - final boolean useNumbers = false; - final String generatedString = RandomStringUtils.random(length, useLetters, useNumbers); - - LOG.debug(generatedString); - } - } diff --git a/java-strings-2/README.md b/java-strings-2/README.md deleted file mode 100644 index ecbdb7def9..0000000000 --- a/java-strings-2/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Java Strings Cookbooks and Examples - -This module contains articles about strings in Java. - -### Relevant Articles: - -- [Java Localization – Formatting Messages](https://www.baeldung.com/java-localization-messages-formatting) -- [Java – Generate Random String](https://www.baeldung.com/java-random-string) -- [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions) -- [Java Multi-line String](https://www.baeldung.com/java-multiline-string) -- More articles: [[<-- prev>]](/java-strings) diff --git a/java-strings-2/pom.xml b/java-strings-2/pom.xml deleted file mode 100755 index be47b1ec89..0000000000 --- a/java-strings-2/pom.xml +++ /dev/null @@ -1,155 +0,0 @@ - - 4.0.0 - java-strings-2 - 0.1.0-SNAPSHOT - jar - java-strings-2 - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-core.version} - - - com.ibm.icu - icu4j - ${icu4j.version} - - - com.google.guava - guava - ${guava.version} - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - commons-io - commons-io - ${commons-io.version} - - - commons-codec - commons-codec - ${commons-codec.version} - - - junit - junit - ${junit.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - org.passay - passay - ${passay.version} - - - org.apache.commons - commons-text - ${commons-text.version} - - - com.vdurmont - emoji-java - ${emoji-java.version} - - - org.ahocorasick - ahocorasick - ${ahocorasick.version} - - - javax.validation - validation-api - ${validation-api.version} - - - org.hibernate.validator - hibernate-validator - ${hibernate-validator.version} - - - javax.el - javax.el-api - ${javax.el-api.version} - - - org.glassfish.web - javax.el - ${javax.el.version} - - - - - java-strings-2 - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java.version} - ${java.version} - -parameters - - - - - - - 3.8.1 - 1.10 - 1.3.1 - - 3.6.1 - 4.0.0 - 0.4.0 - 61.1 - 28.0-jre - 1.4 - 2.0.0.Final - 6.0.2.Final - 3.0.0 - 2.2.6 - - - \ No newline at end of file diff --git a/java-strings-2/src/test/resources/.gitignore b/java-strings-2/src/test/resources/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/java-strings-2/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/java-strings-ops/README.md b/java-strings-ops/README.md deleted file mode 100644 index 4c618585f3..0000000000 --- a/java-strings-ops/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Java Strings Cookbooks and Examples - -This module contains articles about operations on strings in Java. - -### Relevant Articles: -- [Guide to Java String Pool](https://www.baeldung.com/java-string-pool) diff --git a/java-strings-ops/pom.xml b/java-strings-ops/pom.xml deleted file mode 100644 index ebed216c2b..0000000000 --- a/java-strings-ops/pom.xml +++ /dev/null @@ -1,99 +0,0 @@ - - 4.0.0 - com.baeldung - java-strings-ops - 0.1.0-SNAPSHOT - jar - java-strings-ops - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - log4j - log4j - ${log4j.version} - - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-generator.version} - - - com.google.guava - guava - ${guava.version} - - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter-api.version} - test - - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - - - - - - java-strings-ops - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java.version} - ${java.version} - -parameters - - - - - - - - 3.8.1 - 27.0.1-jre - - 3.6.1 - 5.3.1 - - - diff --git a/java-strings-ops/src/main/resources/log4j.properties b/java-strings-ops/src/main/resources/log4j.properties deleted file mode 100644 index 2ea9fa9209..0000000000 --- a/java-strings-ops/src/main/resources/log4j.properties +++ /dev/null @@ -1,8 +0,0 @@ -# Root logger option -log4j.rootLogger=DEBUG, stdout - -# Redirect log messages to console -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/java-strings-ops/src/test/resources/.gitignore b/java-strings-ops/src/test/resources/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/java-strings-ops/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/java-strings/README.md b/java-strings/README.md deleted file mode 100644 index 4668ad014e..0000000000 --- a/java-strings/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## Java Strings Cookbooks and Examples - -This module contains articles about strings in Java. - -### Relevant Articles: -- [Use char[] Array Over a String for Manipulating Passwords in Java?](https://www.baeldung.com/java-storing-passwords) -- [Compact Strings in Java 9](https://www.baeldung.com/java-9-compact-string) -- [String Not Empty Test Assertions in Java](https://www.baeldung.com/java-assert-string-not-empty) -- [String Performance Hints](https://www.baeldung.com/java-string-performance) -- More articles: [[next -->]](/java-strings-2) diff --git a/java-strings/pom.xml b/java-strings/pom.xml deleted file mode 100755 index 42a57bfb42..0000000000 --- a/java-strings/pom.xml +++ /dev/null @@ -1,117 +0,0 @@ - - 4.0.0 - com.baeldung - java-strings - 0.1.0-SNAPSHOT - jar - java-strings - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - commons-io - commons-io - ${commons-io.version} - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - log4j - log4j - ${log4j.version} - - - commons-codec - commons-codec - ${commons-codec.version} - - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-generator.version} - - - com.ibm.icu - icu4j - ${icu4j.version} - - - com.google.guava - guava - ${guava.version} - - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter-api.version} - test - - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - - - - - - java-strings - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java.version} - ${java.version} - -parameters - - - - - - - - 3.8.1 - 1.10 - - 3.6.1 - 61.1 - 27.0.1-jre - 5.3.1 - 1.4 - - - diff --git a/java-strings/src/main/resources/data.csv b/java-strings/src/main/resources/data.csv deleted file mode 100644 index ec4ac10443..0000000000 --- a/java-strings/src/main/resources/data.csv +++ /dev/null @@ -1,3 +0,0 @@ -1|IND|India -2|MY|Malaysia -3|AU|Australia diff --git a/java-strings/src/main/resources/logback.xml b/java-strings/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/java-strings/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/java-strings/src/test/java/com/baeldung/CharArrayToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/CharArrayToStringUnitTest.java deleted file mode 100644 index 3488f8b390..0000000000 --- a/java-strings/src/test/java/com/baeldung/CharArrayToStringUnitTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class CharArrayToStringUnitTest { - - @Test - public void givenCharArray_whenCallingStringConstructor_shouldConvertToString() { - char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; - String result = new String(charArray); - String expectedValue = "character"; - - assertEquals(expectedValue, result); - } - - @Test - public void givenCharArray_whenCallingStringConstructorWithOffsetAndLength_shouldConvertToString() { - char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; - String result = new String(charArray, 4, 3); - String expectedValue = "act"; - - assertEquals(expectedValue, result); - } - - @Test - public void givenCharArray_whenCallingStringCopyValueOf_shouldConvertToString() { - char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; - String result = String.copyValueOf(charArray); - String expectedValue = "character"; - - assertEquals(expectedValue, result); - } - - @Test - public void givenCharArray_whenCallingStringCopyValueOfWithOffsetAndLength_shouldConvertToString() { - char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; - String result = String.copyValueOf(charArray, 0, 4); - String expectedValue = "char"; - - assertEquals(expectedValue, result); - } - - @Test - public void givenCharArray_whenCallingStringValueOf_shouldConvertToString() { - char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; - String result = String.valueOf(charArray); - String expectedValue = "character"; - - assertEquals(expectedValue, result); - } - - @Test - public void givenCharArray_whenCallingStringValueOfWithOffsetAndLength_shouldConvertToString() { - char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; - String result = String.valueOf(charArray, 3, 4); - String expectedValue = "ract"; - - assertEquals(expectedValue, result); - } -} diff --git a/java-strings/src/test/java/com/baeldung/StringToCharArrayUnitTest.java b/java-strings/src/test/java/com/baeldung/StringToCharArrayUnitTest.java deleted file mode 100644 index cd996e58e2..0000000000 --- a/java-strings/src/test/java/com/baeldung/StringToCharArrayUnitTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class StringToCharArrayUnitTest { - - @Test - public void givenString_whenCallingStringToCharArray_shouldConvertToCharArray() { - String givenString = "characters"; - - char[] result = givenString.toCharArray(); - - char[] expectedCharArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r', 's' }; - - assertArrayEquals(expectedCharArray, result); - } - -} diff --git a/java-strings/src/test/resources/.gitignore b/java-strings/src/test/resources/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/java-strings/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/libraries-3/README.md b/libraries-3/README.md new file mode 100644 index 0000000000..a6c6b190ab --- /dev/null +++ b/libraries-3/README.md @@ -0,0 +1,9 @@ +## Libraries-3 + +This module contains articles about various Java libraries. +These are small libraries that are relatively easy to use and do not require any separate module of their own. + +The code examples related to different libraries are each in their own module. + +Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-modules) we already have separate modules. Please make sure to have a look at the existing modules in such cases. + diff --git a/libraries-3/pom.xml b/libraries-3/pom.xml new file mode 100644 index 0000000000..214e87287d --- /dev/null +++ b/libraries-3/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + libraries-3 + libraries-3 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + jboss-public-repository-group + JBoss Public Repository Group + http://repository.jboss.org/nexus/content/groups/public/ + + true + never + + + true + daily + + + + + + + com.beust + jcommander + ${jcommander.version} + + + org.projectlombok + lombok + ${lombok.version} + + + + + 1.78 + 1.18.6 + UTF-8 + 1.8 + 1.8 + + diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/helloworld/HelloWorldApp.java b/libraries-3/src/main/java/com/baeldung/jcommander/helloworld/HelloWorldApp.java new file mode 100644 index 0000000000..56a74ecf21 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/helloworld/HelloWorldApp.java @@ -0,0 +1,37 @@ +package com.baeldung.jcommander.helloworld; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; + +public class HelloWorldApp { + + /* + * Execute: + * mvn exec:java -Dexec.mainClass=com.baeldung.jcommander.helloworld.HelloWorldApp -q \ + * -Dexec.args="--name JavaWorld" + */ + public static void main(String[] args) { + HelloWorldArgs jArgs = new HelloWorldArgs(); + JCommander helloCmd = JCommander + .newBuilder() + .addObject(jArgs) + .build(); + + helloCmd.parse(args); + System.out.println("Hello " + jArgs.getName()); + } +} + +class HelloWorldArgs { + + @Parameter( + names = "--name", + description = "User name", + required = true + ) + private String name; + + public String getName() { + return name; + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/UsageBasedBillingApp.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/UsageBasedBillingApp.java new file mode 100644 index 0000000000..029e7eed01 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/UsageBasedBillingApp.java @@ -0,0 +1,23 @@ +package com.baeldung.jcommander.usagebilling; + +import com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling; + +public class UsageBasedBillingApp { + + /* + * Entry-point: invokes the cli passing the command-line args + * + * Invoking "Submit" sub-command: + * mvn exec:java \ + -Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \ + -Dexec.args="submit --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 --pricing-type PRE_RATED --timestamp 2019-10-03T10:58:00 --quantity 7 --price 24.56" + * + * Invoking "Fetch" sub-command: + * mvn exec:java \ + -Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \ + -Dexec.args="fetch --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 subscriptionPQRMN002 subscriptionPQRMN003 --itemized" + */ + public static void main(String[] args) { + new UsageBasedBilling().run(args); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommand.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommand.java new file mode 100644 index 0000000000..ea6b18af53 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommand.java @@ -0,0 +1,67 @@ +package com.baeldung.jcommander.usagebilling.cli; + +import com.baeldung.jcommander.usagebilling.cli.splitter.ColonParameterSplitter; +import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator; +import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest; +import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse; +import com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import lombok.Getter; + +import java.util.List; + +import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.*; +import static com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService.getDefault; + +@Parameters( + commandNames = { FETCH_CMD }, + commandDescription = "Fetch charges for a customer in the current month, can be itemized or aggregated" +) +@Getter +class FetchCurrentChargesCommand { + + FetchCurrentChargesCommand() { + } + + private FetchCurrentChargesService service = getDefault(); + + @Parameter(names = "--help", help = true) + private boolean help; + + @Parameter( + names = { "--customer", "-C" }, + description = "Id of the Customer who's using the services", + validateWith = UUIDValidator.class, + order = 1, + required = true + ) + private String customerId; + + @Parameter( + names = { "--subscription", "-S" }, + description = "Filter charges for specific subscription Ids, includes all subscriptions if no value is specified", + variableArity = true, + splitter = ColonParameterSplitter.class, + order = 2 + ) + private List subscriptionIds; + + @Parameter( + names = { "--itemized" }, + description = "Whether the response should contain breakdown by subscription, only aggregate values are returned by default", + order = 3 + ) + private boolean itemized; + + void fetch() { + CurrentChargesRequest req = CurrentChargesRequest.builder() + .customerId(customerId) + .subscriptionIds(subscriptionIds) + .itemized(itemized) + .build(); + + CurrentChargesResponse response = service.fetch(req); + System.out.println(response); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommand.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommand.java new file mode 100644 index 0000000000..d3516b19d3 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommand.java @@ -0,0 +1,96 @@ +package com.baeldung.jcommander.usagebilling.cli; + +import com.baeldung.jcommander.usagebilling.cli.converter.ISO8601TimestampConverter; +import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator; +import com.baeldung.jcommander.usagebilling.model.UsageRequest; +import com.baeldung.jcommander.usagebilling.model.UsageRequest.PricingType; +import com.baeldung.jcommander.usagebilling.service.SubmitUsageService; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import lombok.Getter; + +import java.math.BigDecimal; +import java.time.Instant; + +import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.*; +import static com.baeldung.jcommander.usagebilling.service.SubmitUsageService.getDefault; + +@Parameters( + commandNames = { SUBMIT_CMD }, + commandDescription = "Submit usage for a given customer and subscription, accepts one usage item" +) +@Getter +class SubmitUsageCommand { + + SubmitUsageCommand() { + } + + private SubmitUsageService service = getDefault(); + + @Parameter(names = "--help", help = true) + private boolean help; + + @Parameter( + names = { "--customer", "-C" }, + description = "Id of the Customer who's using the services", + validateWith = UUIDValidator.class, + order = 1, + required = true + ) + private String customerId; + + @Parameter( + names = { "--subscription", "-S" }, + description = "Id of the Subscription that was purchased", + order = 2, + required = true + ) + private String subscriptionId; + + @Parameter( + names = { "--pricing-type", "-P" }, + description = "Pricing type of the usage reported", + order = 3, + required = true + ) + private PricingType pricingType; + + @Parameter( + names = { "--quantity" }, + description = "Used quantity; reported quantity is added over the billing period", + order = 3, + required = true + ) + private Integer quantity; + + @Parameter( + names = { "--timestamp" }, + description = "Timestamp of the usage event, must lie in the current billing period", + converter = ISO8601TimestampConverter.class, + order = 4, + required = true + ) + private Instant timestamp; + + @Parameter( + names = { "--price" }, + description = "If PRE_RATED, unit price to be applied per unit of usage quantity reported", + order = 5 + ) + private BigDecimal price; + + void submit() { + + UsageRequest req = UsageRequest.builder() + .customerId(customerId) + .subscriptionId(subscriptionId) + .pricingType(pricingType) + .quantity(quantity) + .timestamp(timestamp) + .price(price) + .build(); + + String reqId = service.submit(req); + System.out.println("Generated Request Id for reference: " + reqId); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/UsageBasedBilling.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/UsageBasedBilling.java new file mode 100644 index 0000000000..a531a68644 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/UsageBasedBilling.java @@ -0,0 +1,80 @@ +package com.baeldung.jcommander.usagebilling.cli; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterException; +import com.beust.jcommander.UnixStyleUsageFormatter; + +public class UsageBasedBilling { + + static final String SUBMIT_CMD = "submit"; + static final String FETCH_CMD = "fetch"; + + private JCommander jCommander; + private SubmitUsageCommand submitUsageCmd; + private FetchCurrentChargesCommand fetchChargesCmd; + + public UsageBasedBilling() { + this.submitUsageCmd = new SubmitUsageCommand(); + this.fetchChargesCmd = new FetchCurrentChargesCommand(); + jCommander = JCommander.newBuilder() + .addObject(this) + .addCommand(submitUsageCmd) + .addCommand(fetchChargesCmd) + .build(); + + setUsageFormatter(SUBMIT_CMD); + setUsageFormatter(FETCH_CMD); + } + + public void run(String[] args) { + String parsedCmdStr; + try { + jCommander.parse(args); + parsedCmdStr = jCommander.getParsedCommand(); + + switch (parsedCmdStr) { + case SUBMIT_CMD: + if (submitUsageCmd.isHelp()) { + getSubCommandHandle(SUBMIT_CMD).usage(); + } + System.out.println("Parsing usage request..."); + submitUsageCmd.submit(); + break; + + case FETCH_CMD: + if (fetchChargesCmd.isHelp()) { + getSubCommandHandle(SUBMIT_CMD).usage(); + } + System.out.println("Preparing fetch query..."); + fetchChargesCmd.fetch(); + + break; + + default: + System.err.println("Invalid command: " + parsedCmdStr); + } + } catch (ParameterException e) { + System.err.println(e.getLocalizedMessage()); + parsedCmdStr = jCommander.getParsedCommand(); + if (parsedCmdStr != null) { + getSubCommandHandle(parsedCmdStr).usage(); + } else { + jCommander.usage(); + } + } + } + + private JCommander getSubCommandHandle(String command) { + JCommander cmd = jCommander.getCommands().get(command); + + if (cmd == null) { + System.err.println("Invalid command: " + command); + } + return cmd; + } + + private void setUsageFormatter(String subCommand) { + JCommander cmd = getSubCommandHandle(subCommand); + cmd.setUsageFormatter(new UnixStyleUsageFormatter(cmd)); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/converter/ISO8601TimestampConverter.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/converter/ISO8601TimestampConverter.java new file mode 100644 index 0000000000..e54865a811 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/converter/ISO8601TimestampConverter.java @@ -0,0 +1,33 @@ +package com.baeldung.jcommander.usagebilling.cli.converter; + +import com.beust.jcommander.ParameterException; +import com.beust.jcommander.converters.BaseConverter; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +import static java.lang.String.format; + +public class ISO8601TimestampConverter extends BaseConverter { + + private static final DateTimeFormatter TS_FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss"); + + public ISO8601TimestampConverter(String optionName) { + super(optionName); + } + + @Override + public Instant convert(String value) { + try { + return LocalDateTime + .parse(value, TS_FORMATTER) + .atOffset(ZoneOffset.UTC) + .toInstant(); + } catch (DateTimeParseException e) { + throw new ParameterException(getErrorString(value, format("an ISO-8601 formatted timestamp (%s)", TS_FORMATTER.toString()))); + } + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/splitter/ColonParameterSplitter.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/splitter/ColonParameterSplitter.java new file mode 100644 index 0000000000..f24c028123 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/splitter/ColonParameterSplitter.java @@ -0,0 +1,15 @@ +package com.baeldung.jcommander.usagebilling.cli.splitter; + +import com.beust.jcommander.converters.IParameterSplitter; + +import java.util.List; + +import static java.util.Arrays.asList; + +public class ColonParameterSplitter implements IParameterSplitter { + + @Override + public List split(String value) { + return asList(value.split(":")); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/validator/UUIDValidator.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/validator/UUIDValidator.java new file mode 100644 index 0000000000..a72912f7d0 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/cli/validator/UUIDValidator.java @@ -0,0 +1,26 @@ +package com.baeldung.jcommander.usagebilling.cli.validator; + +import com.beust.jcommander.IParameterValidator; +import com.beust.jcommander.ParameterException; + +import java.util.regex.Pattern; + +public class UUIDValidator implements IParameterValidator { + + private static final String UUID_REGEX = + "[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}"; + + @Override + public void validate(String name, String value) throws ParameterException { + if (!isValidUUID(value)) { + throw new ParameterException( + "String parameter " + value + " is not a valid UUID."); + } + } + + private boolean isValidUUID(String value) { + return Pattern + .compile(UUID_REGEX) + .matcher(value).matches(); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesRequest.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesRequest.java new file mode 100644 index 0000000000..93dd7a5732 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesRequest.java @@ -0,0 +1,16 @@ +package com.baeldung.jcommander.usagebilling.model; + +import lombok.*; + +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PACKAGE) +@AllArgsConstructor(access = AccessLevel.PACKAGE) +@Builder +@Getter +public class CurrentChargesRequest { + + private String customerId; + private List subscriptionIds; + private boolean itemized; +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesResponse.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesResponse.java new file mode 100644 index 0000000000..865a6e4a3d --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/CurrentChargesResponse.java @@ -0,0 +1,56 @@ +package com.baeldung.jcommander.usagebilling.model; + +import lombok.*; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PACKAGE) +@AllArgsConstructor(access = AccessLevel.PACKAGE) +@Builder +@Getter +public class CurrentChargesResponse { + + private String customerId; + private BigDecimal amountDue; + private List lineItems; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb + .append("Current Month Charges: {") + .append("\n\tcustomer: ") + .append(this.customerId) + .append("\n\ttotalAmountDue: ") + .append(this.amountDue.setScale(2, RoundingMode.HALF_UP)) + .append("\n\tlineItems: ["); + + for (LineItem li : this.lineItems) { + sb + .append("\n\t\t{") + .append("\n\t\t\tsubscription: ") + .append(li.subscriptionId) + .append("\n\t\t\tamount: ") + .append(li.amount.setScale(2, RoundingMode.HALF_UP)) + .append("\n\t\t\tquantity: ") + .append(li.quantity) + .append("\n\t\t},"); + } + + sb.append("\n\t]\n}\n"); + return sb.toString(); + } + + @NoArgsConstructor(access = AccessLevel.PACKAGE) + @AllArgsConstructor(access = AccessLevel.PACKAGE) + @Builder + @Getter + public static class LineItem { + + private String subscriptionId; + private BigDecimal amount; + private Integer quantity; + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/UsageRequest.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/UsageRequest.java new file mode 100644 index 0000000000..2785474acf --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/model/UsageRequest.java @@ -0,0 +1,50 @@ +package com.baeldung.jcommander.usagebilling.model; + +import lombok.*; + +import java.math.BigDecimal; +import java.time.Instant; + +@NoArgsConstructor(access = AccessLevel.PACKAGE) +@AllArgsConstructor(access = AccessLevel.PACKAGE) +@Builder +@Getter +public class UsageRequest { + + private String customerId; + private String subscriptionId; + private PricingType pricingType; + private Integer quantity; + private BigDecimal price; + private Instant timestamp; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb + .append("\nUsage: {") + .append("\n\tcustomer: ") + .append(this.customerId) + .append("\n\tsubscription: ") + .append(this.subscriptionId) + .append("\n\tquantity: ") + .append(this.quantity) + .append("\n\ttimestamp: ") + .append(this.timestamp) + .append("\n\tpricingType: ") + .append(this.pricingType); + + if (PricingType.PRE_RATED == this.pricingType) { + sb + .append("\n\tpreRatedAt: ") + .append(this.price); + } + + sb.append("\n}\n"); + return sb.toString(); + } + + public enum PricingType { + PRE_RATED, UNRATED + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultFetchCurrentChargesService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultFetchCurrentChargesService.java new file mode 100644 index 0000000000..6436d49875 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultFetchCurrentChargesService.java @@ -0,0 +1,68 @@ +package com.baeldung.jcommander.usagebilling.service; + +import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest; +import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse; +import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse.LineItem; + +import java.math.BigDecimal; +import java.util.List; +import java.util.UUID; + +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static java.util.Arrays.fill; +import static java.util.Collections.emptyList; +import static java.util.concurrent.ThreadLocalRandom.current; +import static java.util.stream.Collectors.toList; + +class DefaultFetchCurrentChargesService implements FetchCurrentChargesService { + + @Override + public CurrentChargesResponse fetch(CurrentChargesRequest request) { + List subscriptions = request.getSubscriptionIds(); + + if (subscriptions == null || subscriptions.isEmpty()) { + System.out.println("Fetching ALL charges for customer: " + request.getCustomerId()); + subscriptions = mockSubscriptions(); + + } else { + System.out.println(format("Fetching charges for customer: %s and subscriptions: %s", request.getCustomerId(), subscriptions)); + } + + CurrentChargesResponse charges = mockCharges(request.getCustomerId(), subscriptions, request.isItemized()); + System.out.println("Fetched charges..."); + return charges; + } + + private CurrentChargesResponse mockCharges(String customerId, List subscriptions, boolean itemized) { + List lineItems = mockLineItems(subscriptions); + BigDecimal amountDue = lineItems + .stream() + .map(li -> li.getAmount()) + .reduce(new BigDecimal("0"), BigDecimal::add); + + return CurrentChargesResponse + .builder() + .customerId(customerId) + .lineItems(itemized ? lineItems : emptyList()) + .amountDue(amountDue) + .build(); + } + + private List mockLineItems(List subscriptions) { + return subscriptions + .stream() + .map(subscription -> LineItem.builder() + .subscriptionId(subscription) + .quantity(current().nextInt(20)) + .amount(new BigDecimal(current().nextDouble(1_000))) + .build()) + .collect(toList()); + } + + private List mockSubscriptions() { + String[] subscriptions = new String[5]; + fill(subscriptions, UUID.randomUUID().toString()); + return asList(subscriptions); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultSubmitUsageService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultSubmitUsageService.java new file mode 100644 index 0000000000..44ac9e9ed7 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/DefaultSubmitUsageService.java @@ -0,0 +1,16 @@ +package com.baeldung.jcommander.usagebilling.service; + +import com.baeldung.jcommander.usagebilling.model.UsageRequest; + +import java.util.UUID; + +class DefaultSubmitUsageService implements SubmitUsageService { + + @Override + public String submit(UsageRequest request) { + System.out.println("Submitting usage..." + request); + + System.out.println("Submitted usage successfully..."); + return UUID.randomUUID().toString(); + } +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/FetchCurrentChargesService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/FetchCurrentChargesService.java new file mode 100644 index 0000000000..2cc56658ff --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/FetchCurrentChargesService.java @@ -0,0 +1,13 @@ +package com.baeldung.jcommander.usagebilling.service; + +import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest; +import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse; + +public interface FetchCurrentChargesService { + + static FetchCurrentChargesService getDefault() { + return new DefaultFetchCurrentChargesService(); + } + + CurrentChargesResponse fetch(CurrentChargesRequest request); +} diff --git a/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/SubmitUsageService.java b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/SubmitUsageService.java new file mode 100644 index 0000000000..2a29e6e474 --- /dev/null +++ b/libraries-3/src/main/java/com/baeldung/jcommander/usagebilling/service/SubmitUsageService.java @@ -0,0 +1,12 @@ +package com.baeldung.jcommander.usagebilling.service; + +import com.baeldung.jcommander.usagebilling.model.UsageRequest; + +public interface SubmitUsageService { + + static SubmitUsageService getDefault() { + return new DefaultSubmitUsageService(); + } + + String submit(UsageRequest request); +} diff --git a/libraries-3/src/test/java/com/baeldung/jcommander/helloworld/HelloWorldAppUnitTest.java b/libraries-3/src/test/java/com/baeldung/jcommander/helloworld/HelloWorldAppUnitTest.java new file mode 100644 index 0000000000..48b3ac2896 --- /dev/null +++ b/libraries-3/src/test/java/com/baeldung/jcommander/helloworld/HelloWorldAppUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.jcommander.helloworld; + +import com.beust.jcommander.JCommander; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class HelloWorldAppUnitTest { + + @Test + public void whenJCommanderInvokedWithArgs_thenArgsParsed() { + + HelloWorldArgs jArgs = new HelloWorldArgs(); + JCommander helloCmd = JCommander + .newBuilder() + .addObject(jArgs) + .build(); + + // when + String[] argv = new String[] { + "--name", "JavaWorld" + }; + helloCmd.parse(argv); + + // then + assertEquals("JavaWorld", jArgs.getName()); + } +} diff --git a/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommandUnitTest.java b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommandUnitTest.java new file mode 100644 index 0000000000..b639661c39 --- /dev/null +++ b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/FetchCurrentChargesCommandUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.jcommander.usagebilling.cli; + +import com.beust.jcommander.JCommander; +import org.junit.Test; + +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.junit.Assert.assertThat; + +public class FetchCurrentChargesCommandUnitTest { + + private JCommander jc = JCommander.newBuilder() + .addObject(new FetchCurrentChargesCommand()) + .build(); + + @Test + public void whenParsedMultipleSubscriptionsParameter_thenParameterSubscriptionsIsPopulated() { + FetchCurrentChargesCommand cmd = (FetchCurrentChargesCommand) jc + .getObjects() + .get(0); + + jc.parse(new String[] { + "-C", "cb898e7a-f2a0-46d2-9a09-531f1cee1839", + "-S", "subscriptionA001", + "-S", "subscriptionA002", + "-S", "subscriptionA003", + }); + + assertThat(cmd.getSubscriptionIds(), + contains("subscriptionA001", "subscriptionA002", "subscriptionA003")); + } + + @Test + public void whenParsedSubscriptionsColonSeparatedParameter_thenParameterSubscriptionsIsPopulated() { + FetchCurrentChargesCommand cmd = (FetchCurrentChargesCommand) jc + .getObjects() + .get(0); + + jc.parse(new String[] { + "-C", "cb898e7a-f2a0-46d2-9a09-531f1cee1839", + "-S", "subscriptionA001:subscriptionA002:subscriptionA003", + }); + + assertThat(cmd.getSubscriptionIds(), + contains("subscriptionA001", "subscriptionA002", "subscriptionA003")); + } + + @Test + public void whenParsedSubscriptionsWithVariableArity_thenParameterSubscriptionsIsPopulated() { + FetchCurrentChargesCommand cmd = (FetchCurrentChargesCommand) jc + .getObjects() + .get(0); + + jc.parse(new String[] { + "-C", "cb898e7a-f2a0-46d2-9a09-531f1cee1839", + "-S", "subscriptionA001", "subscriptionA002", "subscriptionA003", + }); + + assertThat(cmd.getSubscriptionIds(), + contains("subscriptionA001", "subscriptionA002", "subscriptionA003")); + } +} diff --git a/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommandUnitTest.java b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommandUnitTest.java new file mode 100644 index 0000000000..d6ce132053 --- /dev/null +++ b/libraries-3/src/test/java/com/baeldung/jcommander/usagebilling/cli/SubmitUsageCommandUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.jcommander.usagebilling.cli; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SubmitUsageCommandUnitTest { + + private JCommander jc = JCommander.newBuilder() + .addObject(new SubmitUsageCommand()) + .build(); + + @Test + public void whenParsedCustomerParameter_thenParameterOfTypeStringIsPopulated() { + jc.parse(new String[] { + "--customer", "cb898e7a-f2a0-46d2-9a09-531f1cee1839", + "--subscription", "subscriptionPQRMN001", + "--pricing-type", "PRE_RATED", + "--timestamp", "2019-10-03T10:58:00", + "--quantity", "7", + "--price", "24.56" + }); + + SubmitUsageCommand cmd = (SubmitUsageCommand) jc + .getObjects() + .get(0); + assertEquals("cb898e7a-f2a0-46d2-9a09-531f1cee1839", cmd.getCustomerId()); + } + + @Test + public void whenParsedTimestampParameter_thenParameterOfTypeInstantIsPopulated() { + jc.parse(new String[] { + "--customer", "cb898e7a-f2a0-46d2-9a09-531f1cee1839", + "--subscription", "subscriptionPQRMN001", + "--pricing-type", "PRE_RATED", + "--timestamp", "2019-10-03T10:58:00", + "--quantity", "7", + "--price", "24.56" + }); + + SubmitUsageCommand cmd = (SubmitUsageCommand) jc + .getObjects() + .get(0); + assertEquals("2019-10-03T10:58:00Z", cmd + .getTimestamp() + .toString()); + } + + @Test(expected = ParameterException.class) + public void whenParsedCustomerIdNotUUID_thenParameterException() { + jc.parse(new String[] { + "--customer", "customer001", + "--subscription", "subscriptionPQRMN001", + "--pricing-type", "PRE_RATED", + "--timestamp", "2019-10-03T10:58:00", + "--quantity", "7", + "--price", "24.56" + }); + } +} diff --git a/linux-bash/json/src/main/bash/fruit.json b/linux-bash/json/src/main/bash/fruit.json new file mode 100644 index 0000000000..392d2290ae --- /dev/null +++ b/linux-bash/json/src/main/bash/fruit.json @@ -0,0 +1 @@ +{"fruit":{"name":"apple","color":"green","price":1.20}} diff --git a/linux-bash/json/src/main/bash/fruits.json b/linux-bash/json/src/main/bash/fruits.json new file mode 100644 index 0000000000..114a9a35cc --- /dev/null +++ b/linux-bash/json/src/main/bash/fruits.json @@ -0,0 +1,17 @@ +[ + { + "name": "apple", + "color": "green", + "price": 1.2 + }, + { + "name": "banana", + "color": "yellow", + "price": 0.5 + }, + { + "name": "kiwi", + "color": "green", + "price": 1.25 + } +] diff --git a/linux-bash/json/src/main/bash/jq.sh b/linux-bash/json/src/main/bash/jq.sh new file mode 100755 index 0000000000..786be304db --- /dev/null +++ b/linux-bash/json/src/main/bash/jq.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +#3.1. Beautify JSON +echo '{"fruit":{"name":"apple","color":"green","price":1.20}}' | jq '.' +jq '.' fruit.json +curl http://api.open-notify.org/iss-now.json | jq '.' + +#3.2. Accessing Properties +jq '.fruit' fruit.json +jq '.fruit.color' fruit.json +jq '.fruit.color,.fruit.price' fruit.json +echo '{ "with space": "hello" }' | jq '."with space"' + +#4.1. Iteration +echo '["x","y","z"]' | jq '.[]' +jq '.[] | .name' fruits.json +jq '.[].name' fruits.json + +#4.2. Accessing By Index +jq '.[1].price' fruits.json + +#4.3. Slicing +echo '[1,2,3,4,5,6,7,8,9,10]' | jq '.[6:9]' +echo '[1,2,3,4,5,6,7,8,9,10]' | jq '.[:6]' | jq '.[-2:]' + +#5.1. Getting Keys +jq '.fruit | keys' fruit.json + +#5.2. Returning the Length +jq '.fruit | length' fruit.json +jq '.fruit.name | length' fruit.json + +#5.3. Mapping Values +jq 'map(has("name"))' fruits.json +jq 'map(.price+2)' fruits.json + +#5.4. Min and Max +jq '[.[].price] | min' fruits.json +jq '[.[].price] | max' fruits.json + +#5.5. Selecting Values +jq '.[] | select(.price>0.5)' fruits.json +jq '.[] | select(.color=="yellow")' fruits.json +jq '.[] | select(.color=="yellow" and .price>=0.5)' fruits.json + +#5.6. Support For RegEx +jq '.[] | select(.name|test("^a.")) | .price' fruits.json + +#5.7. Find Unique Values +jq 'map(.color) | unique' fruits.json + +#5.8. Deleting Keys From JSON +jq 'del(.fruit.name)' fruit.json + +# 6. Transforming +jq '.query.pages | [.[] | map(.) | .[] | {page_title: .title, page_description: .extract}]' wikipedia.json diff --git a/linux-bash/json/src/main/bash/wikipedia.json b/linux-bash/json/src/main/bash/wikipedia.json new file mode 100644 index 0000000000..180b160bcc --- /dev/null +++ b/linux-bash/json/src/main/bash/wikipedia.json @@ -0,0 +1,22 @@ +{ + "query": { + "pages": [ + { + "21721040": { + "pageid": 21721040, + "ns": 0, + "title": "Stack Overflow", + "extract": "Some interesting text about Stack Overflow" + } + }, + { + "21721041": { + "pageid": 21721041, + "ns": 0, + "title": "Baeldung", + "extract": "A great place to learn about Java" + } + } + ] + } +} diff --git a/lombok/pom.xml b/lombok/pom.xml index 2acf9e240d..b67320909e 100644 --- a/lombok/pom.xml +++ b/lombok/pom.xml @@ -76,7 +76,7 @@ - 1.18.4 + 1.18.10 1.0.0.Final diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java new file mode 100644 index 0000000000..74ae51c040 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/BasicAccount.java @@ -0,0 +1,24 @@ +package com.baeldung.lombok.accessors.model; + +import java.math.BigDecimal; + +public class BasicAccount { + String name; + BigDecimal balance; + + public BigDecimal getBalance() { + return this.balance; + } + + public void setBalance(BigDecimal newBalance) { + this.balance = newBalance; + } + + public String getName() { + return this.name; + } + + public void setName(String accountName) { + this.name = accountName; + } +} diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java new file mode 100644 index 0000000000..8fa9a2e8aa --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedAccount.java @@ -0,0 +1,15 @@ +package com.baeldung.lombok.accessors.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Accessors(chain = true) +@Getter +@Setter +public class ChainedAccount { + String name; + BigDecimal balance; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java new file mode 100644 index 0000000000..22e85848bd --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/ChainedFluentAccount.java @@ -0,0 +1,15 @@ +package com.baeldung.lombok.accessors.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Accessors(fluent = true, chain = true) +@Getter +@Setter +public class ChainedFluentAccount { + String name; + BigDecimal balance; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java new file mode 100644 index 0000000000..bc5e6ba70e --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/FluentAccount.java @@ -0,0 +1,15 @@ +package com.baeldung.lombok.accessors.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Accessors(fluent = true, chain = false) +@Getter +@Setter +public class FluentAccount { + String name; + BigDecimal balance; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java new file mode 100644 index 0000000000..e3e3ae620b --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedAccount.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.accessors.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + + +@Accessors(prefix = {"s", "bd"}) +@Getter +@Setter +public class PrefixedAccount { + String sName; + BigDecimal bdBalance; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java new file mode 100644 index 0000000000..462a9b41ec --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/PrefixedFluentAccount.java @@ -0,0 +1,15 @@ +package com.baeldung.lombok.accessors.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Accessors(prefix = {"s", "bd"}, fluent = true) +@Getter +@Setter +public class PrefixedFluentAccount { + String sName; + BigDecimal bdBalance; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java b/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java new file mode 100644 index 0000000000..89727fef19 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/accessors/model/StandardAccount.java @@ -0,0 +1,13 @@ +package com.baeldung.lombok.accessors.model; + +import lombok.Getter; +import lombok.Setter; + +import java.math.BigDecimal; + +@Getter +@Setter +public class StandardAccount { + String name; + BigDecimal balance; +} diff --git a/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java new file mode 100644 index 0000000000..679c7d39ef --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/accessors/AccessorsUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.lombok.accessors; + +import com.baeldung.lombok.accessors.model.*; +import org.junit.Test; + +import java.math.BigDecimal; + +import static org.junit.Assert.assertEquals; + +public class AccessorsUnitTest { + + @Test + public void givenBasicAccount_thenUseBasicAccessors() { + BasicAccount account = new BasicAccount(); + account.setBalance(BigDecimal.TEN); + account.setName("Basic Accessors"); + + assertEquals(BigDecimal.TEN, account.getBalance()); + assertEquals("Basic Accessors", account.getName()); + } + + @Test + public void givenFluentAccount_thenUseFluentAccessors() { + FluentAccount account = new FluentAccount(); + account.name("Fluent Account"); + account.balance(BigDecimal.TEN); + + assertEquals(BigDecimal.TEN, account.balance()); + assertEquals("Fluent Account", account.name()); + } + + @Test + public void givenChainedAccount_thenUseChainedAccessors() { + ChainedAccount account = new ChainedAccount(); + account.setName("Chained Account").setBalance(BigDecimal.TEN); + + assertEquals(BigDecimal.TEN, account.getBalance()); + assertEquals("Chained Account", account.getName()); + } + + @Test + public void givenChainedFluentAccount_thenUseChainedFluentAccessors() { + ChainedFluentAccount account = new ChainedFluentAccount() + .name("Fluent Account") + .balance(BigDecimal.TEN); + + assertEquals(BigDecimal.TEN, account.balance()); + assertEquals("Fluent Account", account.name()); + } + + @Test + public void givenPrefixedAccount_thenRemovePrefixFromAccessors() { + PrefixedAccount account = new PrefixedAccount(); + account.setName("Prefixed Fields"); + account.setBalance(BigDecimal.TEN); + + assertEquals(BigDecimal.TEN, account.getBalance()); + assertEquals("Prefixed Fields", account.getName()); + } + + @Test + public void givenPrefixedFluentAccount_thenRemovePrefixFromAccessors() { + PrefixedFluentAccount account = new PrefixedFluentAccount(); + account + .name("Prefixed Fluent Fields") + .balance(BigDecimal.TEN); + + assertEquals(BigDecimal.TEN, account.balance()); + assertEquals("Prefixed Fluent Fields", account.name()); + } + +} diff --git a/persistence-modules/spring-data-jpa-3/pom.xml b/persistence-modules/spring-data-jpa-3/pom.xml index f743fce2a3..32f81d5745 100644 --- a/persistence-modules/spring-data-jpa-3/pom.xml +++ b/persistence-modules/spring-data-jpa-3/pom.xml @@ -18,29 +18,22 @@ + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-data-jpa - org.postgresql - postgresql - ${postgresql.version} + com.h2database + h2 + runtime + ${h2.version} - - org.testcontainers - junit-jupiter - ${testcontainers.version} - test - - - org.testcontainers - postgresql - ${testcontainers.version} - test - org.springframework.boot spring-boot-starter-test @@ -71,8 +64,7 @@ - 1.12.2 - 42.2.8 + 1.4.200 diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/tx/Payment.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/model/Payment.java similarity index 97% rename from persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/tx/Payment.java rename to persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/model/Payment.java index 37f3d09381..2c24e5777e 100644 --- a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/tx/Payment.java +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/model/Payment.java @@ -1,4 +1,4 @@ -package com.baeldung.tx; +package com.baeldung.model; import javax.persistence.*; diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/model/User.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/model/User.java new file mode 100644 index 0000000000..94d0c023f2 --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/model/User.java @@ -0,0 +1,42 @@ +package com.baeldung.model; + +import javax.persistence.*; +import java.util.Set; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue + private Long id; + + private String username; + + @ElementCollection + private Set permissions; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Set getPermissions() { + return permissions; + } + + public void setPermissions(Set permissions) { + this.permissions = permissions; + } +} diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/repository/UserRepository.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/repository/UserRepository.java new file mode 100644 index 0000000000..bb3ce781f6 --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/repository/UserRepository.java @@ -0,0 +1,17 @@ +package com.baeldung.repository; + +import com.baeldung.model.User; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + + @EntityGraph(attributePaths = "permissions") + Optional findDetailedByUsername(String username); + + Optional findSummaryByUsername(String username); + + Optional findByUsername(String username); +} diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/service/SimpleUserService.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/service/SimpleUserService.java new file mode 100644 index 0000000000..6782254f61 --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/service/SimpleUserService.java @@ -0,0 +1,24 @@ +package com.baeldung.service; + +import com.baeldung.model.User; +import com.baeldung.repository.UserRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +public class SimpleUserService implements UserService { + + private final UserRepository userRepository; + + public SimpleUserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + @Transactional(readOnly = true) + public Optional findOne(String username) { + return userRepository.findDetailedByUsername(username); + } +} diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/service/UserService.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/service/UserService.java new file mode 100644 index 0000000000..11b3dc82ce --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/service/UserService.java @@ -0,0 +1,9 @@ +package com.baeldung.service; + +import com.baeldung.model.User; + +import java.util.Optional; + +public interface UserService { + Optional findOne(String username); +} diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/web/DetailedUserDto.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/web/DetailedUserDto.java new file mode 100644 index 0000000000..0d8fe02b91 --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/web/DetailedUserDto.java @@ -0,0 +1,45 @@ +package com.baeldung.web; + +import com.baeldung.model.User; + +import java.util.Set; + +public class DetailedUserDto { + + private Long id; + private String username; + private Set permissions; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Set getPermissions() { + return permissions; + } + + public void setPermissions(Set permissions) { + this.permissions = permissions; + } + + public static DetailedUserDto fromEntity(User user) { + DetailedUserDto detailed = new DetailedUserDto(); + detailed.setId(user.getId()); + detailed.setUsername(user.getUsername()); + detailed.setPermissions(user.getPermissions()); + + return detailed; + } +} diff --git a/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/web/UserController.java b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/web/UserController.java new file mode 100644 index 0000000000..867d60cc2f --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/main/java/com/baeldung/web/UserController.java @@ -0,0 +1,27 @@ +package com.baeldung.web; + +import com.baeldung.service.UserService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/users") +public class UserController { + + private final UserService userService; + + public UserController(UserService userService) { + this.userService = userService; + } + + @GetMapping("/{username}") + public ResponseEntity findOne(@PathVariable String username) { + return userService.findOne(username) + .map(DetailedUserDto::fromEntity) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } +} diff --git a/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/osiv/UserControllerIntegrationTest.java b/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/osiv/UserControllerIntegrationTest.java new file mode 100644 index 0000000000..ba94fc111b --- /dev/null +++ b/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/osiv/UserControllerIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.osiv; + +import com.baeldung.model.User; +import com.baeldung.repository.UserRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.Arrays; +import java.util.HashSet; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@ActiveProfiles("test") +class UserControllerIntegrationTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + User user = new User(); + user.setUsername("root"); + user.setPermissions(new HashSet<>(Arrays.asList("PERM_READ", "PERM_WRITE"))); + + userRepository.save(user); + } + + @Test + void givenTheUserExists_WhenOsivIsEnabled_ThenLazyInitWorkEverywhere() throws Exception { + mockMvc.perform(get("/users/root")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.username").value("root")) + .andExpect(jsonPath("$.permissions", containsInAnyOrder("PERM_READ", "PERM_WRITE"))); + } + + @AfterEach + void flushDb() { + userRepository.deleteAll(); + } +} diff --git a/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/tx/ManualTransactionIntegrationTest.java b/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/tx/ManualTransactionIntegrationTest.java index 62d64d4372..1ce8e91ec5 100644 --- a/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/tx/ManualTransactionIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-3/src/test/java/com/baeldung/tx/ManualTransactionIntegrationTest.java @@ -1,10 +1,10 @@ package com.baeldung.tx; +import com.baeldung.model.Payment; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.PlatformTransactionManager; @@ -14,27 +14,17 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; import javax.persistence.EntityManager; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE; import static org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED; @DataJpaTest -@Testcontainers @ActiveProfiles("test") -@AutoConfigureTestDatabase(replace = NONE) @Transactional(propagation = NOT_SUPPORTED) class ManualTransactionIntegrationTest { - @Container - private static PostgreSQLContainer pg = initPostgres(); - @Autowired private PlatformTransactionManager transactionManager; @@ -159,13 +149,4 @@ class ManualTransactionIntegrationTest { .getResultList()).hasSize(1); } - private static PostgreSQLContainer initPostgres() { - PostgreSQLContainer pg = new PostgreSQLContainer<>("postgres:11.1") - .withDatabaseName("baeldung") - .withUsername("test") - .withPassword("test"); - pg.setPortBindings(singletonList("54320:5432")); - - return pg; - } } diff --git a/persistence-modules/spring-data-jpa-3/src/test/resources/application-test.properties b/persistence-modules/spring-data-jpa-3/src/test/resources/application-test.properties index aa7093f751..f9497c8f37 100644 --- a/persistence-modules/spring-data-jpa-3/src/test/resources/application-test.properties +++ b/persistence-modules/spring-data-jpa-3/src/test/resources/application-test.properties @@ -1,4 +1,2 @@ spring.jpa.hibernate.ddl-auto=update -spring.datasource.url=jdbc:postgresql://localhost:54320/baeldung -spring.datasource.username=test -spring.datasource.password=test +spring.datasource.url=jdbc:h2:mem:jpa3 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9569d7b391..94526ec4ce 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 @@ -446,6 +445,7 @@ core-java-modules/core-java-string-algorithms core-java-modules/core-java-string-algorithms-2 core-java-modules/core-java-string-apis + core-java-modules/core-java-strings core-java-modules/core-java core-java-modules/core-java-jvm core-scala @@ -508,9 +508,6 @@ java-numbers-2 java-rmi java-spi - java-strings - java-strings-2 - java-strings-ops java-vavr-stream java-websocket javafx @@ -544,6 +541,7 @@ libraries libraries-2 + libraries-3 libraries-data libraries-data-2 libraries-data-db @@ -604,8 +602,10 @@ rule-engines rsocket - rxjava - rxjava-2 + rxjava-core + rxjava-observables + rxjava-operators + rxjava-libraries software-security/sql-injection-samples tensorflow-java @@ -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 @@ -1219,6 +1221,7 @@ core-java-modules/core-java-string-algorithms core-java-modules/core-java-string-algorithms-2 core-java-modules/core-java-string-apis + core-java-modules/core-java-strings core-scala couchbase custom-pmd @@ -1279,9 +1282,6 @@ java-numbers-2 java-rmi java-spi - java-strings - java-strings-2 - java-strings-ops java-vavr-stream java-websocket javafx @@ -1313,6 +1313,7 @@ libraries + libraries-3 libraries-data libraries-data-2 libraries-data-db @@ -1371,8 +1372,10 @@ rule-engines rsocket - rxjava - rxjava-2 + rxjava-core + rxjava-observables + rxjava-operators + rxjava-libraries oauth2-framework-impl spf4j spring-boot-performance @@ -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/rxjava-2/README.md b/rxjava-2/README.md deleted file mode 100644 index 87f606a323..0000000000 --- a/rxjava-2/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## RxJava - -This module contains articles about RxJava. - -### Relevant articles: - -- [RxJava and Error Handling](https://www.baeldung.com/rxjava-error-handling) -- [RxJava 2 – Flowable](https://www.baeldung.com/rxjava-2-flowable) -- [RxJava Maybe](https://www.baeldung.com/rxjava-maybe) -- [Introduction to RxRelay for RxJava](https://www.baeldung.com/rx-relay) -- [Combining RxJava Completables](https://www.baeldung.com/rxjava-completable) -- [Converting Synchronous and Asynchronous APIs to Observables using RxJava2](https://www.baeldung.com/rxjava-apis-to-observables) -- [RxJava Hooks](https://www.baeldung.com/rxjava-hooks) -- More articles: [[<-- prev]](/rxjava) diff --git a/rxjava-2/pom.xml b/rxjava-2/pom.xml deleted file mode 100644 index 47d16ec8dd..0000000000 --- a/rxjava-2/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - rxjava-2 - rxjava-2 - 1.0-SNAPSHOT - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - io.reactivex.rxjava2 - rxjava - ${rx.java2.version} - - - com.jayway.awaitility - awaitility - ${awaitility.version} - - - org.assertj - assertj-core - ${assertj.version} - - - com.jakewharton.rxrelay2 - rxrelay - ${rxrelay.version} - - - - com.github.akarnokd - rxjava2-extensions - ${rxjava2.ext.version} - - - - - 3.8.0 - 2.2.2 - 1.7.0 - 2.0.0 - 0.20.4 - - \ No newline at end of file diff --git a/rxjava-core/README.md b/rxjava-core/README.md new file mode 100644 index 0000000000..2773bd9423 --- /dev/null +++ b/rxjava-core/README.md @@ -0,0 +1,16 @@ +## RxJava + +This module contains articles about RxJava. + +### Relevant articles: + +- [Dealing with Backpressure with RxJava](https://www.baeldung.com/rxjava-backpressure) +- [How to Test RxJava?](https://www.baeldung.com/rxjava-testing) +- [Introduction to RxJava](https://www.baeldung.com/rx-java) +- [Schedulers in RxJava](https://www.baeldung.com/rxjava-schedulers) +- [Difference Between Flatmap and Switchmap in RxJava](https://www.baeldung.com/rxjava-flatmap-switchmap) +- [RxJava and Error Handling](https://www.baeldung.com/rxjava-error-handling) +- [RxJava Maybe](https://www.baeldung.com/rxjava-maybe) +- [Combining RxJava Completables](https://www.baeldung.com/rxjava-completable) +- [RxJava Hooks](https://www.baeldung.com/rxjava-hooks) +- More articles: [[next -->]](/rxjava-2) diff --git a/rxjava-core/pom.xml b/rxjava-core/pom.xml new file mode 100644 index 0000000000..401ad83808 --- /dev/null +++ b/rxjava-core/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + rxjava-core + 1.0-SNAPSHOT + rxjava-core + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + io.reactivex + rxjava + ${rx.java.version} + + + io.reactivex.rxjava2 + rxjava + ${rx.java2.version} + + + com.jayway.awaitility + awaitility + ${awaitility.version} + + + org.assertj + assertj-core + ${assertj.version} + + + + + 3.8.0 + 1.2.5 + 1.7.0 + 2.2.2 + + + \ No newline at end of file diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ComputeFunction.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ComputeFunction.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/ComputeFunction.java rename to rxjava-core/src/main/java/com/baeldung/rxjava/ComputeFunction.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java rename to rxjava-core/src/main/java/com/baeldung/rxjava/ConnectableObservableImpl.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ObservableImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ObservableImpl.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/ObservableImpl.java rename to rxjava-core/src/main/java/com/baeldung/rxjava/ObservableImpl.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/ResourceManagement.java b/rxjava-core/src/main/java/com/baeldung/rxjava/ResourceManagement.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/ResourceManagement.java rename to rxjava-core/src/main/java/com/baeldung/rxjava/ResourceManagement.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/SingleImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/SingleImpl.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/SingleImpl.java rename to rxjava-core/src/main/java/com/baeldung/rxjava/SingleImpl.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/SubjectImpl.java b/rxjava-core/src/main/java/com/baeldung/rxjava/SubjectImpl.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/SubjectImpl.java rename to rxjava-core/src/main/java/com/baeldung/rxjava/SubjectImpl.java diff --git a/java-strings-ops/src/main/resources/logback.xml b/rxjava-core/src/main/resources/logback.xml similarity index 100% rename from java-strings-ops/src/main/resources/logback.xml rename to rxjava-core/src/main/resources/logback.xml diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/CompletableUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/ConnectableObservableIntegrationTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/MaybeUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/ObservableUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/ResourceManagementUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaBackpressureLongRunningUnitTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java similarity index 96% rename from rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java index b79fa9af22..f71d9e8839 100644 --- a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java +++ b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java @@ -1,84 +1,84 @@ -package com.baeldung.rxjava; - -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Test; - -import io.reactivex.Observable; -import io.reactivex.plugins.RxJavaPlugins; -import io.reactivex.schedulers.Schedulers; - -public class RxJavaHooksManualTest { - - private boolean initHookCalled = false; - private boolean hookCalled = false; - - @Test - public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() { - - RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - - RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.io()) - .test(); - assertTrue(hookCalled && initHookCalled); - } - - @Test - public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() { - - RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - - RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 15) - .map(v -> v * 2) - .subscribeOn(Schedulers.newThread()) - .test(); - assertTrue(hookCalled && initHookCalled); - } - - @Test - public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() { - - RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - - RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.single()) - .test(); - assertTrue(hookCalled && initHookCalled); - - } - - @After - public void reset() { - hookCalled = false; - initHookCalled = false; - RxJavaPlugins.reset(); - } -} +package com.baeldung.rxjava; + +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Test; + +import io.reactivex.Observable; +import io.reactivex.plugins.RxJavaPlugins; +import io.reactivex.schedulers.Schedulers; + +public class RxJavaHooksManualTest { + + private boolean initHookCalled = false; + private boolean hookCalled = false; + + @Test + public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() { + + RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + + RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.io()) + .test(); + assertTrue(hookCalled && initHookCalled); + } + + @Test + public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() { + + RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + + RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 15) + .map(v -> v * 2) + .subscribeOn(Schedulers.newThread()) + .test(); + assertTrue(hookCalled && initHookCalled); + } + + @Test + public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() { + + RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + + RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + assertTrue(hookCalled && initHookCalled); + + } + + @After + public void reset() { + hookCalled = false; + initHookCalled = false; + RxJavaPlugins.reset(); + } +} diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java similarity index 96% rename from rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java index dd4287a4a9..cea6cc70f6 100644 --- a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java +++ b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java @@ -1,244 +1,244 @@ -package com.baeldung.rxjava; - -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Test; - -import io.reactivex.Completable; -import io.reactivex.Flowable; -import io.reactivex.Maybe; -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.flowables.ConnectableFlowable; -import io.reactivex.observables.ConnectableObservable; -import io.reactivex.plugins.RxJavaPlugins; -import io.reactivex.schedulers.Schedulers; - -public class RxJavaHooksUnitTest { - - private boolean initHookCalled = false; - private boolean hookCalled = false; - - @Test - public void givenObservable_whenError_shouldExecuteTheHook() { - RxJavaPlugins.setErrorHandler(throwable -> { - hookCalled = true; - }); - - Observable.error(new IllegalStateException()) - .subscribe(); - assertTrue(hookCalled); - } - - @Test - public void givenCompletable_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnCompletableAssembly(completable -> { - hookCalled = true; - return completable; - }); - Completable.fromSingle(Single.just(1)); - assertTrue(hookCalled); - } - - @Test - public void givenCompletable_whenSubscribed_shouldExecuteTheHook() { - - RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> { - hookCalled = true; - return observer; - }); - - Completable.fromSingle(Single.just(1)) - .test(); - assertTrue(hookCalled); - } - - @Test - public void givenObservable_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnObservableAssembly(observable -> { - hookCalled = true; - return observable; - }); - - Observable.range(1, 10); - assertTrue(hookCalled); - } - - @Test - public void givenObservable_whenSubscribed_shouldExecuteTheHook() { - - RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> { - hookCalled = true; - return observer; - }); - - Observable.range(1, 10) - .test(); - assertTrue(hookCalled); - } - - @Test - public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> { - hookCalled = true; - return connectableObservable; - }); - - ConnectableObservable.range(1, 10) - .publish() - .connect(); - assertTrue(hookCalled); - } - - @Test - public void givenFlowable_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnFlowableAssembly(flowable -> { - hookCalled = true; - return flowable; - }); - - Flowable.range(1, 10); - assertTrue(hookCalled); - } - - @Test - public void givenFlowable_whenSubscribed_shouldExecuteTheHook() { - - RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> { - hookCalled = true; - return observer; - }); - - Flowable.range(1, 10) - .test(); - assertTrue(hookCalled); - } - - @Test - public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> { - hookCalled = true; - return connectableFlowable; - }); - - ConnectableFlowable.range(1, 10) - .publish() - .connect(); - assertTrue(hookCalled); - } - - @Test - public void givenParallel_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> { - hookCalled = true; - return parallelFlowable; - }); - - Flowable.range(1, 10) - .parallel(); - assertTrue(hookCalled); - } - - @Test - public void givenMaybe_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnMaybeAssembly(maybe -> { - hookCalled = true; - return maybe; - }); - - Maybe.just(1); - assertTrue(hookCalled); - } - - @Test - public void givenMaybe_whenSubscribed_shouldExecuteTheHook() { - - RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> { - hookCalled = true; - return observer; - }); - - Maybe.just(1) - .test(); - assertTrue(hookCalled); - } - - @Test - public void givenSingle_whenAssembled_shouldExecuteTheHook() { - - RxJavaPlugins.setOnSingleAssembly(single -> { - hookCalled = true; - return single; - }); - - Single.just(1); - assertTrue(hookCalled); - } - - @Test - public void givenSingle_whenSubscribed_shouldExecuteTheHook() { - - RxJavaPlugins.setOnSingleSubscribe((single, observer) -> { - hookCalled = true; - return observer; - }); - - Single.just(1) - .test(); - assertTrue(hookCalled); - } - - @Test - public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() { - - RxJavaPlugins.setScheduleHandler((runnable) -> { - hookCalled = true; - return runnable; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.single()) - .test(); - hookCalled = false; - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.computation()) - .test(); - assertTrue(hookCalled); - } - - @Test - public void givenComputationScheduler_whenCalled_shouldExecuteTheHooks() { - - RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.computation()) - .test(); - assertTrue(hookCalled && initHookCalled); - } - - @After - public void reset() { - initHookCalled = false; - hookCalled = false; - RxJavaPlugins.reset(); - } -} +package com.baeldung.rxjava; + +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Test; + +import io.reactivex.Completable; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.flowables.ConnectableFlowable; +import io.reactivex.observables.ConnectableObservable; +import io.reactivex.plugins.RxJavaPlugins; +import io.reactivex.schedulers.Schedulers; + +public class RxJavaHooksUnitTest { + + private boolean initHookCalled = false; + private boolean hookCalled = false; + + @Test + public void givenObservable_whenError_shouldExecuteTheHook() { + RxJavaPlugins.setErrorHandler(throwable -> { + hookCalled = true; + }); + + Observable.error(new IllegalStateException()) + .subscribe(); + assertTrue(hookCalled); + } + + @Test + public void givenCompletable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnCompletableAssembly(completable -> { + hookCalled = true; + return completable; + }); + Completable.fromSingle(Single.just(1)); + assertTrue(hookCalled); + } + + @Test + public void givenCompletable_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> { + hookCalled = true; + return observer; + }); + + Completable.fromSingle(Single.just(1)) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenObservable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnObservableAssembly(observable -> { + hookCalled = true; + return observable; + }); + + Observable.range(1, 10); + assertTrue(hookCalled); + } + + @Test + public void givenObservable_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> { + hookCalled = true; + return observer; + }); + + Observable.range(1, 10) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> { + hookCalled = true; + return connectableObservable; + }); + + ConnectableObservable.range(1, 10) + .publish() + .connect(); + assertTrue(hookCalled); + } + + @Test + public void givenFlowable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnFlowableAssembly(flowable -> { + hookCalled = true; + return flowable; + }); + + Flowable.range(1, 10); + assertTrue(hookCalled); + } + + @Test + public void givenFlowable_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> { + hookCalled = true; + return observer; + }); + + Flowable.range(1, 10) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> { + hookCalled = true; + return connectableFlowable; + }); + + ConnectableFlowable.range(1, 10) + .publish() + .connect(); + assertTrue(hookCalled); + } + + @Test + public void givenParallel_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> { + hookCalled = true; + return parallelFlowable; + }); + + Flowable.range(1, 10) + .parallel(); + assertTrue(hookCalled); + } + + @Test + public void givenMaybe_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnMaybeAssembly(maybe -> { + hookCalled = true; + return maybe; + }); + + Maybe.just(1); + assertTrue(hookCalled); + } + + @Test + public void givenMaybe_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> { + hookCalled = true; + return observer; + }); + + Maybe.just(1) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenSingle_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnSingleAssembly(single -> { + hookCalled = true; + return single; + }); + + Single.just(1); + assertTrue(hookCalled); + } + + @Test + public void givenSingle_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnSingleSubscribe((single, observer) -> { + hookCalled = true; + return observer; + }); + + Single.just(1) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() { + + RxJavaPlugins.setScheduleHandler((runnable) -> { + hookCalled = true; + return runnable; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + hookCalled = false; + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.computation()) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenComputationScheduler_whenCalled_shouldExecuteTheHooks() { + + RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.computation()) + .test(); + assertTrue(hookCalled && initHookCalled); + } + + @After + public void reset() { + initHookCalled = false; + hookCalled = false; + RxJavaPlugins.reset(); + } +} diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/RxJavaUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/SchedulersLiveTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/SingleUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/SingleUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/SingleUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/SingleUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/SubjectUnitTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/onerror/ExceptionHandlingIntegrationTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java b/rxjava-core/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java rename to rxjava-core/src/test/java/com/baeldung/rxjava/onerror/OnErrorRetryIntegrationTest.java diff --git a/rxjava-libraries/README.md b/rxjava-libraries/README.md new file mode 100644 index 0000000000..ac8aac6908 --- /dev/null +++ b/rxjava-libraries/README.md @@ -0,0 +1,10 @@ +## RxJava Libraries + + This module contains articles about RxJava libraries + +### Related Articles: + +- [RxJava 2 – Flowable](https://www.baeldung.com/rxjava-2-flowable) +- [Introduction to RxRelay for RxJava](https://www.baeldung.com/rx-relay) +- [Introduction to rxjava-jdbc](https://www.baeldung.com/rxjava-jdbc) + diff --git a/rxjava-libraries/pom.xml b/rxjava-libraries/pom.xml new file mode 100644 index 0000000000..541d9116c8 --- /dev/null +++ b/rxjava-libraries/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + rxjava-libraries + 1.0-SNAPSHOT + rxjava-libraries + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + io.reactivex + rxjava + ${rx.java.version} + + + io.reactivex.rxjava2 + rxjava + ${rx.java2.version} + + + com.jakewharton.rxrelay2 + rxrelay + ${rxrelay.version} + + + com.github.davidmoten + rxjava-jdbc + ${rx.java.jdbc.version} + + + com.h2database + h2 + ${h2.version} + runtime + + + org.assertj + assertj-core + ${assertj.version} + + + + + + 0.7.11 + 1.2.5 + 2.0.0 + 2.2.2 + 3.8.0 + + + \ No newline at end of file diff --git a/rxjava-2/src/main/java/com/baeldung/rxjava/RandomRelay.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/RandomRelay.java similarity index 100% rename from rxjava-2/src/main/java/com/baeldung/rxjava/RandomRelay.java rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/RandomRelay.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Connector.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Connector.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Connector.java rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Connector.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Employee.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Employee.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Employee.java rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Employee.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Manager.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Manager.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Manager.java rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Manager.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/jdbc/Utils.java b/rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Utils.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/jdbc/Utils.java rename to rxjava-libraries/src/main/java/com/baeldung/rxjava/jdbc/Utils.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/FlowableIntegrationTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/RxRelayIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapClassIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/AutomapInterfaceIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/BasicQueryTypesIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertBlobIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/InsertClobIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/ReturnKeysIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java b/rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java rename to rxjava-libraries/src/test/java/com/baeldung/rxjava/jdbc/TransactionIntegrationTest.java diff --git a/rxjava/src/test/resources/actual_clob b/rxjava-libraries/src/test/resources/actual_clob similarity index 100% rename from rxjava/src/test/resources/actual_clob rename to rxjava-libraries/src/test/resources/actual_clob diff --git a/rxjava/src/test/resources/expected_clob b/rxjava-libraries/src/test/resources/expected_clob similarity index 100% rename from rxjava/src/test/resources/expected_clob rename to rxjava-libraries/src/test/resources/expected_clob diff --git a/rxjava-observables/README.md b/rxjava-observables/README.md new file mode 100644 index 0000000000..3bec990012 --- /dev/null +++ b/rxjava-observables/README.md @@ -0,0 +1,11 @@ +## RxJava Observables + + This module contains articles about RxJava Observables + +### Related Articles: + +- [Combining Observables in RxJava](https://www.baeldung.com/rxjava-combine-observables) +- [RxJava One Observable, Multiple Subscribers](https://www.baeldung.com/rxjava-multiple-subscribers-observable) +- [RxJava StringObservable](https://www.baeldung.com/rxjava-string) +- [Filtering Observables in RxJava](https://www.baeldung.com/rxjava-filtering) + diff --git a/rxjava-observables/pom.xml b/rxjava-observables/pom.xml new file mode 100644 index 0000000000..c2bf0bcd88 --- /dev/null +++ b/rxjava-observables/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + rxjava-observables + 1.0-SNAPSHOT + rxjava-observables + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + io.reactivex + rxjava + ${rx.java.version} + + + io.reactivex + rxjava-string + ${rx.java.string.version} + + + org.assertj + assertj-core + ${assertj.version} + + + + + + 1.1.1 + 1.2.5 + 3.8.0 + + + \ No newline at end of file diff --git a/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java b/rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java rename to rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersColdObs.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java b/rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java rename to rxjava-observables/src/main/java/com/baeldung/rxjava/MultipleSubscribersHotObs.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java rename to rxjava-observables/src/test/java/com/baeldung/rxjava/combine/ObservableCombineUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java rename to rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaFilterOperatorsIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java rename to rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaSkipOperatorsIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java rename to rxjava-observables/src/test/java/com/baeldung/rxjava/filters/RxJavaTimeFilteringOperatorsIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java b/rxjava-observables/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java rename to rxjava-observables/src/test/java/com/baeldung/rxjava/operators/RxStringOperatorsUnitTest.java diff --git a/rxjava-operators/README.md b/rxjava-operators/README.md new file mode 100644 index 0000000000..293d310bbd --- /dev/null +++ b/rxjava-operators/README.md @@ -0,0 +1,12 @@ +## RxJava Operators + + This module contains articles about RxJava Operators + +### Related Articles: + +- [Mathematical and Aggregate Operators in RxJava](https://www.baeldung.com/rxjava-math) +- [Observable Utility Operators in RxJava](https://www.baeldung.com/rxjava-observable-operators) +- [Implementing Custom Operators in RxJava](https://www.baeldung.com/rxjava-custom-operators) +- [Converting Synchronous and Asynchronous APIs to Observables using RxJava2](https://www.baeldung.com/rxjava-apis-to-observables) + + diff --git a/rxjava/pom.xml b/rxjava-operators/pom.xml similarity index 65% rename from rxjava/pom.xml rename to rxjava-operators/pom.xml index 85106d1127..8064613f45 100644 --- a/rxjava/pom.xml +++ b/rxjava-operators/pom.xml @@ -1,11 +1,11 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - rxjava + rxjava-operators 1.0-SNAPSHOT - rxjava - + rxjava-operators + com.baeldung parent-java @@ -19,48 +19,40 @@ rxjava ${rx.java.version} - - io.reactivex - rxjava-math - ${rx.java.math.version} + io.reactivex.rxjava2 + rxjava + ${rx.java2.version} - + - io.reactivex - rxjava-string - ${rx.java.string.version} - - - - com.jayway.awaitility - awaitility - ${awaitility.version} - - - com.github.davidmoten - rxjava-jdbc - ${rx.java.jdbc.version} - - - com.h2database - h2 - ${h2.version} - runtime + com.github.akarnokd + rxjava2-extensions + ${rxjava2.ext.version} org.assertj assertj-core ${assertj.version} + + io.reactivex + rxjava-math + ${rx.java.math.version} + + + com.jayway.awaitility + awaitility + ${awaitility.version} + + 0.20.4 + 2.2.2 3.8.0 1.2.5 - 0.7.11 1.0.0 - 1.1.1 1.7.0 diff --git a/rxjava/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java b/rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java rename to rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToCleanString.java diff --git a/rxjava/src/main/java/com/baeldung/rxjava/operator/ToLength.java b/rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToLength.java similarity index 100% rename from rxjava/src/main/java/com/baeldung/rxjava/operator/ToLength.java rename to rxjava-operators/src/main/java/com/baeldung/rxjava/operator/ToLength.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java similarity index 96% rename from rxjava-2/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java rename to rxjava-operators/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java index 90f4fe94ae..2842fab80e 100644 --- a/rxjava-2/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java +++ b/rxjava-operators/src/test/java/com/baeldung/rxjava/AsyncAndSyncToObservableIntegrationTest.java @@ -1,107 +1,107 @@ -package com.baeldung.rxjava; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - -import hu.akarnokd.rxjava2.async.AsyncObservable; -import io.reactivex.Observable; - -public class AsyncAndSyncToObservableIntegrationTest { - - AtomicInteger counter = new AtomicInteger(); - Callable callable = () -> counter.incrementAndGet(); - - /* Method will execute every time it gets subscribed*/ - @Test - public void givenSyncMethod_whenConvertedWithFromCallable_thenReturnObservable() { - - Observable source = Observable.fromCallable(callable); - - for (int i = 1; i < 5; i++) { - source.test() - .awaitDone(5, TimeUnit.SECONDS) - .assertResult(i); - - assertEquals(i, counter.get()); - } - } - - /* Method will execute only once and cache its result.*/ - @Test - public void givenSyncMethod_whenConvertedWithStart_thenReturnObservable() { - - Observable source = AsyncObservable.start(callable); - - for (int i = 1; i < 5; i++) { - source.test() - .awaitDone(5, TimeUnit.SECONDS) - .assertResult(1); - - assertEquals(1, counter.get()); - } - } - - /* Method will execute only once and cache its result.*/ - @Test - public void givenAsyncMethod_whenConvertedWithFromFuture_thenRetrunObservble() { - - ExecutorService executor = Executors.newSingleThreadExecutor(); - Future future = executor.submit(callable); - Observable source = Observable.fromFuture(future); - - for (int i = 1; i < 5; i++) { - source.test() - .awaitDone(5, TimeUnit.SECONDS) - .assertResult(1); - - assertEquals(1, counter.get()); - } - - executor.shutdown(); - } - - /* Method will execute every time it gets subscribed*/ - @Test - public void givenAsyncMethod_whenConvertedWithStartFuture_thenRetrunObservble() { - - ExecutorService executor = Executors.newSingleThreadExecutor(); - Observable source = AsyncObservable.startFuture(() -> executor.submit(callable)); - - for (int i = 1; i < 5; i++) { - source.test() - .awaitDone(5, TimeUnit.SECONDS) - .assertResult(i); - - assertEquals(i, counter.get()); - } - - executor.shutdown(); - } - - /*Method will execute only once and cache its result.*/ - @Test - public void givenAsyncMethod_whenConvertedWithDeferFuture_thenRetrunObservble() { - List list = Arrays.asList(new Integer[] { counter.incrementAndGet(), counter.incrementAndGet(), counter.incrementAndGet() }); - ExecutorService exec = Executors.newSingleThreadExecutor(); - Callable> callable = () -> Observable.fromIterable(list); - Observable source = AsyncObservable.deferFuture(() -> exec.submit(callable)); - for (int i = 1; i < 4; i++) { - source.test() - .awaitDone(5, TimeUnit.SECONDS) - .assertResult(1, 2, 3); - } - - exec.shutdown(); - } - -} +package com.baeldung.rxjava; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import hu.akarnokd.rxjava2.async.AsyncObservable; +import io.reactivex.Observable; + +public class AsyncAndSyncToObservableIntegrationTest { + + AtomicInteger counter = new AtomicInteger(); + Callable callable = () -> counter.incrementAndGet(); + + /* Method will execute every time it gets subscribed*/ + @Test + public void givenSyncMethod_whenConvertedWithFromCallable_thenReturnObservable() { + + Observable source = Observable.fromCallable(callable); + + for (int i = 1; i < 5; i++) { + source.test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(i); + + assertEquals(i, counter.get()); + } + } + + /* Method will execute only once and cache its result.*/ + @Test + public void givenSyncMethod_whenConvertedWithStart_thenReturnObservable() { + + Observable source = AsyncObservable.start(callable); + + for (int i = 1; i < 5; i++) { + source.test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(1); + + assertEquals(1, counter.get()); + } + } + + /* Method will execute only once and cache its result.*/ + @Test + public void givenAsyncMethod_whenConvertedWithFromFuture_thenRetrunObservble() { + + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = executor.submit(callable); + Observable source = Observable.fromFuture(future); + + for (int i = 1; i < 5; i++) { + source.test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(1); + + assertEquals(1, counter.get()); + } + + executor.shutdown(); + } + + /* Method will execute every time it gets subscribed*/ + @Test + public void givenAsyncMethod_whenConvertedWithStartFuture_thenRetrunObservble() { + + ExecutorService executor = Executors.newSingleThreadExecutor(); + Observable source = AsyncObservable.startFuture(() -> executor.submit(callable)); + + for (int i = 1; i < 5; i++) { + source.test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(i); + + assertEquals(i, counter.get()); + } + + executor.shutdown(); + } + + /*Method will execute only once and cache its result.*/ + @Test + public void givenAsyncMethod_whenConvertedWithDeferFuture_thenRetrunObservble() { + List list = Arrays.asList(new Integer[] { counter.incrementAndGet(), counter.incrementAndGet(), counter.incrementAndGet() }); + ExecutorService exec = Executors.newSingleThreadExecutor(); + Callable> callable = () -> Observable.fromIterable(list); + Observable source = AsyncObservable.deferFuture(() -> exec.submit(callable)); + for (int i = 1; i < 4; i++) { + source.test() + .awaitDone(5, TimeUnit.SECONDS) + .assertResult(1, 2, 3); + } + + exec.shutdown(); + } + +} diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java rename to rxjava-operators/src/test/java/com/baeldung/rxjava/RxJavaCustomOperatorUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java rename to rxjava-operators/src/test/java/com/baeldung/rxjava/UtilityOperatorsIntegrationTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java rename to rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxAggregateOperatorsUnitTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java similarity index 100% rename from rxjava-2/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java rename to rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxFlatmapAndSwitchmapUnitTest.java diff --git a/rxjava/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java b/rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java similarity index 100% rename from rxjava/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java rename to rxjava-operators/src/test/java/com/baeldung/rxjava/operators/RxMathematicalOperatorsUnitTest.java diff --git a/rxjava/README.md b/rxjava/README.md deleted file mode 100644 index c9308ddcc6..0000000000 --- a/rxjava/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## RxJava - -This module contains articles about RxJava. - -### Relevant articles: - -- [Dealing with Backpressure with RxJava](https://www.baeldung.com/rxjava-backpressure) -- [How to Test RxJava?](https://www.baeldung.com/rxjava-testing) -- [Implementing Custom Operators in RxJava](https://www.baeldung.com/rxjava-custom-operators) -- [Introduction to RxJava](https://www.baeldung.com/rx-java) -- [Observable Utility Operators in RxJava](https://www.baeldung.com/rxjava-observable-operators) -- [Introduction to rxjava-jdbc](https://www.baeldung.com/rxjava-jdbc) -- [Schedulers in RxJava](https://www.baeldung.com/rxjava-schedulers) -- [Mathematical and Aggregate Operators in RxJava](https://www.baeldung.com/rxjava-math) -- [Combining Observables in RxJava](https://www.baeldung.com/rxjava-combine-observables) -- [RxJava StringObservable](https://www.baeldung.com/rxjava-string) -- [Filtering Observables in RxJava](https://www.baeldung.com/rxjava-filtering) -- [RxJava One Observable, Multiple Subscribers](https://www.baeldung.com/rxjava-multiple-subscribers-observable) -- [Difference Between Flatmap and Switchmap in RxJava](https://www.baeldung.com/rxjava-flatmap-switchmap) -- More articles: [[next -->]](/rxjava-2) diff --git a/rxjava/src/main/resources/logback.xml b/rxjava/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/rxjava/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/ErrorHandlingApp.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/ErrorHandlingApp.java new file mode 100644 index 0000000000..72a9ec8ad7 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/ErrorHandlingApp.java @@ -0,0 +1,26 @@ +package com.baeldung.springamqp.errorhandling; + +import com.baeldung.springamqp.errorhandling.producer.MessageProducer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class ErrorHandlingApp { + + @Autowired + MessageProducer messageProducer; + + public static void main(String[] args) { + SpringApplication.run(ErrorHandlingApp.class, args); + } + + @EventListener(ApplicationReadyEvent.class) + public void doSomethingAfterStartup() { + messageProducer.sendMessage(); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXCustomAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXCustomAmqpConfiguration.java new file mode 100644 index 0000000000..708b08476d --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXCustomAmqpConfiguration.java @@ -0,0 +1,55 @@ +package com.baeldung.springamqp.errorhandling.configuration; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; + +@Configuration +@ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "dlx-custom") +public class DLXCustomAmqpConfiguration { + public static final String DLX_EXCHANGE_MESSAGES = QUEUE_MESSAGES + ".dlx"; + + @Bean + Queue messagesQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES) + .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_MESSAGES) + .build(); + } + + @Bean + FanoutExchange deadLetterExchange() { + return new FanoutExchange(DLX_EXCHANGE_MESSAGES); + } + + @Bean + Queue deadLetterQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build(); + } + + @Bean + Binding deadLetterBinding() { + return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()); + } + + @Bean + DirectExchange messagesExchange() { + return new DirectExchange(EXCHANGE_MESSAGES); + } + + @Bean + Binding bindingMessages() { + return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXParkingLotAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXParkingLotAmqpConfiguration.java new file mode 100644 index 0000000000..bff325e657 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/DLXParkingLotAmqpConfiguration.java @@ -0,0 +1,72 @@ +package com.baeldung.springamqp.errorhandling.configuration; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; + +@Configuration +@ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "parking-lot-dlx") +public class DLXParkingLotAmqpConfiguration { + public static final String DLX_EXCHANGE_MESSAGES = QUEUE_MESSAGES + ".dlx"; + public static final String QUEUE_PARKING_LOT = QUEUE_MESSAGES + ".parking-lot"; + public static final String EXCHANGE_PARKING_LOT = QUEUE_MESSAGES + "exchange.parking-lot"; + + @Bean + FanoutExchange parkingLotExchange() { + return new FanoutExchange(EXCHANGE_PARKING_LOT); + } + + @Bean + Queue parkingLotQueue() { + return QueueBuilder.durable(QUEUE_PARKING_LOT).build(); + } + + @Bean + Binding parkingLotBinding() { + return BindingBuilder.bind(parkingLotQueue()).to(parkingLotExchange()); + } + + @Bean + Queue messagesQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES) + .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_MESSAGES) + .build(); + } + + @Bean + FanoutExchange deadLetterExchange() { + return new FanoutExchange(DLX_EXCHANGE_MESSAGES); + } + + @Bean + Queue deadLetterQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build(); + } + + @Bean + Binding deadLetterBinding() { + return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()); + } + + @Bean + DirectExchange messagesExchange() { + return new DirectExchange(EXCHANGE_MESSAGES); + } + + @Bean + Binding bindingMessages() { + return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/FatalExceptionStrategyAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/FatalExceptionStrategyAmqpConfiguration.java new file mode 100644 index 0000000000..dcd76d7f72 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/FatalExceptionStrategyAmqpConfiguration.java @@ -0,0 +1,63 @@ +package com.baeldung.springamqp.errorhandling.configuration; + +import com.baeldung.springamqp.errorhandling.errorhandler.CustomFatalExceptionStrategy; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler; +import org.springframework.amqp.rabbit.listener.FatalExceptionStrategy; +import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.ErrorHandler; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES; + +@Configuration +@ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "fatal-error-strategy") +public class FatalExceptionStrategyAmqpConfiguration { + + @Bean + public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory( + ConnectionFactory connectionFactory, + SimpleRabbitListenerContainerFactoryConfigurer configurer) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + configurer.configure(factory, connectionFactory); + factory.setErrorHandler(errorHandler()); + return factory; + } + + @Bean + public ErrorHandler errorHandler() { + return new ConditionalRejectingErrorHandler(customExceptionStrategy()); + } + + @Bean + FatalExceptionStrategy customExceptionStrategy() { + return new CustomFatalExceptionStrategy(); + } + + @Bean + Queue messagesQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES) + .build(); + } + + @Bean + DirectExchange messagesExchange() { + return new DirectExchange(EXCHANGE_MESSAGES); + } + + @Bean + Binding bindingMessages() { + return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/ListenerErrorHandlerAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/ListenerErrorHandlerAmqpConfiguration.java new file mode 100644 index 0000000000..8990381da2 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/ListenerErrorHandlerAmqpConfiguration.java @@ -0,0 +1,55 @@ +package com.baeldung.springamqp.errorhandling.configuration; + +import com.baeldung.springamqp.errorhandling.errorhandler.CustomErrorHandler; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.ErrorHandler; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES; + +@Configuration +@ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "listener-error") +public class ListenerErrorHandlerAmqpConfiguration { + + @Bean + public ErrorHandler errorHandler() { + return new CustomErrorHandler(); + } + + @Bean + public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, + SimpleRabbitListenerContainerFactoryConfigurer configurer) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + configurer.configure(factory, connectionFactory); + factory.setErrorHandler(errorHandler()); + return factory; + } + + @Bean + Queue messagesQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES) + .build(); + } + + @Bean + DirectExchange messagesExchange() { + return new DirectExchange(EXCHANGE_MESSAGES); + } + + @Bean + Binding bindingMessages() { + return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/RoutingKeyDLQAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/RoutingKeyDLQAmqpConfiguration.java new file mode 100644 index 0000000000..defabed306 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/RoutingKeyDLQAmqpConfiguration.java @@ -0,0 +1,55 @@ +package com.baeldung.springamqp.errorhandling.configuration; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; + +@Configuration +@ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "routing-dlq") +public class RoutingKeyDLQAmqpConfiguration { + public static final String DLX_EXCHANGE_MESSAGES = QUEUE_MESSAGES + ".dlx"; + + @Bean + Queue messagesQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES) + .withArgument("x-dead-letter-exchange", DLX_EXCHANGE_MESSAGES) + .build(); + } + + @Bean + FanoutExchange deadLetterExchange() { + return new FanoutExchange(DLX_EXCHANGE_MESSAGES); + } + + @Bean + Queue deadLetterQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build(); + } + + @Bean + Binding deadLetterBinding() { + return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()); + } + + @Bean + DirectExchange messagesExchange() { + return new DirectExchange(EXCHANGE_MESSAGES); + } + + @Bean + Binding bindingMessages() { + return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/SimpleDLQAmqpConfiguration.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/SimpleDLQAmqpConfiguration.java new file mode 100644 index 0000000000..ea129986ca --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/configuration/SimpleDLQAmqpConfiguration.java @@ -0,0 +1,43 @@ +package com.baeldung.springamqp.errorhandling.configuration; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "simple-dlq") +public class SimpleDLQAmqpConfiguration { + public static final String QUEUE_MESSAGES = "baeldung-messages-queue"; + public static final String QUEUE_MESSAGES_DLQ = QUEUE_MESSAGES + ".dlq"; + public static final String EXCHANGE_MESSAGES = "baeldung-messages-exchange"; + + @Bean + Queue messagesQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES) + .withArgument("x-dead-letter-exchange", "") + .withArgument("x-dead-letter-routing-key", QUEUE_MESSAGES_DLQ) + .build(); + } + + @Bean + Queue deadLetterQueue() { + return QueueBuilder.durable(QUEUE_MESSAGES_DLQ).build(); + } + + @Bean + DirectExchange messagesExchange() { + return new DirectExchange(EXCHANGE_MESSAGES); + } + + @Bean + Binding bindingMessages() { + return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(QUEUE_MESSAGES); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/DLQCustomAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/DLQCustomAmqpContainer.java new file mode 100644 index 0000000000..62907abee9 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/DLQCustomAmqpContainer.java @@ -0,0 +1,35 @@ +package com.baeldung.springamqp.errorhandling.consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; +import static com.baeldung.springamqp.errorhandling.consumer.MessagesConsumer.HEADER_X_RETRIES_COUNT; + +public class DLQCustomAmqpContainer { + private static final Logger log = LoggerFactory.getLogger(DLQCustomAmqpContainer.class); + private final RabbitTemplate rabbitTemplate; + public static final int MAX_RETRIES_COUNT = 2; + + public DLQCustomAmqpContainer(RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + @RabbitListener(queues = QUEUE_MESSAGES_DLQ) + public void processFailedMessagesRetryHeaders(Message failedMessage) { + Integer retriesCnt = (Integer) failedMessage.getMessageProperties().getHeaders().get(HEADER_X_RETRIES_COUNT); + if (retriesCnt == null) + retriesCnt = 1; + if (retriesCnt > MAX_RETRIES_COUNT) { + log.info("Discarding message"); + return; + } + log.info("Retrying message for the {} time", retriesCnt); + failedMessage.getMessageProperties().getHeaders().put(HEADER_X_RETRIES_COUNT, ++retriesCnt); + rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/MessagesConsumer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/MessagesConsumer.java new file mode 100644 index 0000000000..17b65c58da --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/MessagesConsumer.java @@ -0,0 +1,63 @@ +package com.baeldung.springamqp.errorhandling.consumer; + +import com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration; +import com.baeldung.springamqp.errorhandling.errorhandler.BusinessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MessagesConsumer { + public static final String HEADER_X_RETRIES_COUNT = "x-retries-count"; + + + private static final Logger log = LoggerFactory.getLogger(MessagesConsumer.class); + private final RabbitTemplate rabbitTemplate; + + public MessagesConsumer(RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + @RabbitListener(queues = SimpleDLQAmqpConfiguration.QUEUE_MESSAGES) + public void receiveMessage(Message message) throws BusinessException { + log.info("Received message: {}", message.toString()); + throw new BusinessException(); + } + + @Bean + @ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "simple-dlq") + public SimpleDLQAmqpContainer simpleAmqpContainer() { + return new SimpleDLQAmqpContainer(rabbitTemplate); + } + + @Bean + @ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "routing-dlq") + public RoutingDLQAmqpContainer routingDLQAmqpContainer() { + return new RoutingDLQAmqpContainer(rabbitTemplate); + } + + @Bean + @ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "dlx-custom") + public DLQCustomAmqpContainer dlqAmqpContainer() { + return new DLQCustomAmqpContainer(rabbitTemplate); + } + + @Bean + @ConditionalOnProperty( + value = "amqp.configuration.current", + havingValue = "parking-lot-dlx") + public ParkingLotDLQAmqpContainer parkingLotDLQAmqpContainer() { + return new ParkingLotDLQAmqpContainer(rabbitTemplate); + } +} \ No newline at end of file diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/ParkingLotDLQAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/ParkingLotDLQAmqpContainer.java new file mode 100644 index 0000000000..34dccd408a --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/ParkingLotDLQAmqpContainer.java @@ -0,0 +1,43 @@ +package com.baeldung.springamqp.errorhandling.consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import static com.baeldung.springamqp.errorhandling.configuration.DLXParkingLotAmqpConfiguration.EXCHANGE_PARKING_LOT; +import static com.baeldung.springamqp.errorhandling.configuration.DLXParkingLotAmqpConfiguration.QUEUE_PARKING_LOT; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; +import static com.baeldung.springamqp.errorhandling.consumer.MessagesConsumer.HEADER_X_RETRIES_COUNT; + +public class ParkingLotDLQAmqpContainer { + private static final Logger log = LoggerFactory.getLogger(ParkingLotDLQAmqpContainer.class); + private final RabbitTemplate rabbitTemplate; + public static final int MAX_RETRIES_COUNT = 2; + + public ParkingLotDLQAmqpContainer(RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + @RabbitListener(queues = QUEUE_MESSAGES_DLQ) + public void processFailedMessagesRetryWithParkingLot(Message failedMessage) { + Integer retriesCnt = (Integer) failedMessage.getMessageProperties().getHeaders().get(HEADER_X_RETRIES_COUNT); + if (retriesCnt == null) + retriesCnt = 1; + if (retriesCnt > MAX_RETRIES_COUNT) { + log.info("Sending message to the parking lot queue"); + rabbitTemplate.send(EXCHANGE_PARKING_LOT, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage); + return; + } + log.info("Retrying message for the {} time", retriesCnt); + failedMessage.getMessageProperties().getHeaders().put(HEADER_X_RETRIES_COUNT, ++retriesCnt); + rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage); + } + + @RabbitListener(queues = QUEUE_PARKING_LOT) + public void processParkingLotQueue(Message failedMessage) { + log.info("Received message in parking lot queue {}", failedMessage.toString()); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/RoutingDLQAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/RoutingDLQAmqpContainer.java new file mode 100644 index 0000000000..fedce76880 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/RoutingDLQAmqpContainer.java @@ -0,0 +1,33 @@ +package com.baeldung.springamqp.errorhandling.consumer; + +import com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration; +import com.baeldung.springamqp.errorhandling.errorhandler.BusinessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; + +public class RoutingDLQAmqpContainer { + private static final Logger log = LoggerFactory.getLogger(RoutingDLQAmqpContainer.class); + private final RabbitTemplate rabbitTemplate; + + public RoutingDLQAmqpContainer(RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + @RabbitListener(queues = SimpleDLQAmqpConfiguration.QUEUE_MESSAGES) + public void receiveMessage(Message message) throws BusinessException { + log.info("Received message: {}", message.toString()); + throw new BusinessException(); + } + + @RabbitListener(queues = QUEUE_MESSAGES_DLQ) + public void processFailedMessagesRequeue(Message failedMessage) { + log.info("Received failed message, requeueing: {}", failedMessage.toString()); + rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/SimpleDLQAmqpContainer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/SimpleDLQAmqpContainer.java new file mode 100644 index 0000000000..6f9da7b587 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/consumer/SimpleDLQAmqpContainer.java @@ -0,0 +1,31 @@ +package com.baeldung.springamqp.errorhandling.consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES; +import static com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration.QUEUE_MESSAGES_DLQ; + +public class SimpleDLQAmqpContainer { + private static final Logger log = LoggerFactory.getLogger(SimpleDLQAmqpContainer.class); + private final RabbitTemplate rabbitTemplate; + + public SimpleDLQAmqpContainer(RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + @RabbitListener(queues = QUEUE_MESSAGES_DLQ) + public void processFailedMessages(Message message) { + log.info("Received failed message: {}", message.toString()); + } + + @RabbitListener(queues = QUEUE_MESSAGES_DLQ) + public void processFailedMessagesRequeue(Message failedMessage) { + log.info("Received failed message, requeueing: {}", failedMessage.toString()); + log.info("Received failed message, requeueing: {}", failedMessage.getMessageProperties().getReceivedRoutingKey()); + rabbitTemplate.send(EXCHANGE_MESSAGES, failedMessage.getMessageProperties().getReceivedRoutingKey(), failedMessage); + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/BusinessException.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/BusinessException.java new file mode 100644 index 0000000000..faec96e2aa --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/BusinessException.java @@ -0,0 +1,4 @@ +package com.baeldung.springamqp.errorhandling.errorhandler; + +public class BusinessException extends Exception { +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomErrorHandler.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomErrorHandler.java new file mode 100644 index 0000000000..5c5e9cdf13 --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomErrorHandler.java @@ -0,0 +1,14 @@ +package com.baeldung.springamqp.errorhandling.errorhandler; + +import org.springframework.amqp.AmqpRejectAndDontRequeueException; +import org.springframework.util.ErrorHandler; + +public class CustomErrorHandler implements ErrorHandler { + + @Override + public void handleError(Throwable t) { + if (!(t.getCause() instanceof BusinessException)) { + throw new AmqpRejectAndDontRequeueException("Error Handler converted exception to fatal", t); + } + } +} diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomFatalExceptionStrategy.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomFatalExceptionStrategy.java new file mode 100644 index 0000000000..e14be4e73c --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/errorhandler/CustomFatalExceptionStrategy.java @@ -0,0 +1,10 @@ +package com.baeldung.springamqp.errorhandling.errorhandler; + +import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler; + +public class CustomFatalExceptionStrategy extends ConditionalRejectingErrorHandler.DefaultExceptionStrategy { + @Override + public boolean isFatal(Throwable t) { + return !(t.getCause() instanceof BusinessException); + } +} \ No newline at end of file diff --git a/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/producer/MessageProducer.java b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/producer/MessageProducer.java new file mode 100644 index 0000000000..c14fd5bf3b --- /dev/null +++ b/spring-amqp/src/main/java/com/baeldung/springamqp/errorhandling/producer/MessageProducer.java @@ -0,0 +1,24 @@ +package com.baeldung.springamqp.errorhandling.producer; + +import com.baeldung.springamqp.errorhandling.configuration.SimpleDLQAmqpConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Service; + +@Service +public class MessageProducer { + + private static final Logger log = LoggerFactory.getLogger(MessageProducer.class); + private int messageNumber = 0; + private final RabbitTemplate rabbitTemplate; + + public MessageProducer(final RabbitTemplate rabbitTemplate) { + this.rabbitTemplate = rabbitTemplate; + } + + public void sendMessage() { + log.info("Sending message..."); + rabbitTemplate.convertAndSend(SimpleDLQAmqpConfiguration.EXCHANGE_MESSAGES, SimpleDLQAmqpConfiguration.QUEUE_MESSAGES, "Some message id:" + messageNumber++); + } +} \ No newline at end of file diff --git a/spring-amqp/src/main/resources/application.properties b/spring-amqp/src/main/resources/application.properties new file mode 100644 index 0000000000..c0c1cf1b47 --- /dev/null +++ b/spring-amqp/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.rabbitmq.listener.simple.default-requeue-rejected=false +spring.main.allow-bean-definition-overriding=true +amqp.configuration.current=parking-lot-dlx \ No newline at end of file diff --git a/spring-boot-springdoc/pom.xml b/spring-boot-springdoc/pom.xml new file mode 100644 index 0000000000..a818db6e53 --- /dev/null +++ b/spring-boot-springdoc/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + com.baeldung + spring-boot-springdoc + 0.0.1-SNAPSHOT + spring-boot-springdoc + Project for Springdoc integration + jar + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.springdoc + springdoc-openapi-core + 1.1.45 + + + org.springdoc + springdoc-openapi-ui + 1.1.45 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + integration + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.8.RELEASE + + + pre-integration-test + + start + + + + post-integration-test + + stop + + + + + + org.springdoc + springdoc-openapi-maven-plugin + 0.2 + + + integration-test + + generate + + + + + http://localhost:8080/api-docs + openapi.json + ${project.build.directory} + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/SpringdocApplication.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/SpringdocApplication.java new file mode 100644 index 0000000000..45c7c23621 --- /dev/null +++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/SpringdocApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.springdoc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringdocApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringdocApplication.class, args); + } + +} diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java new file mode 100644 index 0000000000..4d7d9e3d85 --- /dev/null +++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java @@ -0,0 +1,73 @@ +package com.baeldung.springdoc.controller; + +import java.util.Collection; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.springdoc.exception.BookNotFoundException; +import com.baeldung.springdoc.model.Book; +import com.baeldung.springdoc.repository.BookRepository; + +@RestController +@RequestMapping("/api/book") +public class BookController { + + @Autowired + private BookRepository repository; + + @GetMapping("/{id}") + public Book findById(@PathVariable long id) { + return repository.findById(id) + .orElseThrow(() -> new BookNotFoundException()); + } + + @GetMapping("/") + public Collection findBooks() { + return repository.getBooks(); + } + + @PutMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + public Book updateBook(@PathVariable("id") final String id, @RequestBody final Book book) { + return book; + } + + @PatchMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + public Book patchBook(@PathVariable("id") final String id, @RequestBody final Book book) { + return book; + } + + @PostMapping("/") + @ResponseStatus(HttpStatus.CREATED) + public Book postBook(@NotNull @Valid @RequestBody final Book book) { + return book; + } + + @RequestMapping(method = RequestMethod.HEAD, value = "/") + @ResponseStatus(HttpStatus.OK) + public Book headBook() { + return new Book(); + } + + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + public long deleteBook(@PathVariable final long id) { + return id; + } +} diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/BookNotFoundException.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/BookNotFoundException.java new file mode 100644 index 0000000000..632cb683bc --- /dev/null +++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/BookNotFoundException.java @@ -0,0 +1,10 @@ +package com.baeldung.springdoc.exception; + +@SuppressWarnings("serial") +public class BookNotFoundException extends RuntimeException { + + public BookNotFoundException() { + + } + +} \ No newline at end of file diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/GlobalControllerExceptionHandler.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/GlobalControllerExceptionHandler.java new file mode 100644 index 0000000000..c829072236 --- /dev/null +++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/exception/GlobalControllerExceptionHandler.java @@ -0,0 +1,24 @@ +package com.baeldung.springdoc.exception; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalControllerExceptionHandler { + + @ExceptionHandler(ConversionFailedException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity handleConnversion(RuntimeException ex) { + return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(BookNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ResponseEntity handleBookNotFound(RuntimeException ex) { + return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND); + } +} diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java new file mode 100644 index 0000000000..8f678a7ec2 --- /dev/null +++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/model/Book.java @@ -0,0 +1,41 @@ +package com.baeldung.springdoc.model; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +public class Book { + + private long id; + + @NotBlank + @Size(min = 0, max = 20) + private String title; + + @NotBlank + @Size(min = 0, max = 30) + private String author; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} diff --git a/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/repository/BookRepository.java b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/repository/BookRepository.java new file mode 100644 index 0000000000..4040ba28c2 --- /dev/null +++ b/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/repository/BookRepository.java @@ -0,0 +1,28 @@ +package com.baeldung.springdoc.repository; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.springframework.stereotype.Repository; + +import com.baeldung.springdoc.model.Book; + +@Repository +public class BookRepository { + + private Map books = new HashMap<>(); + + public Optional findById(long id) { + return Optional.ofNullable(books.get(id)); + } + + public void add(Book book) { + books.put(book.getId(), book); + } + + public Collection getBooks() { + return books.values(); + } +} diff --git a/spring-boot-springdoc/src/main/resources/application.properties b/spring-boot-springdoc/src/main/resources/application.properties new file mode 100644 index 0000000000..f03e90feb6 --- /dev/null +++ b/spring-boot-springdoc/src/main/resources/application.properties @@ -0,0 +1,5 @@ +# custom path for swagger-ui +springdoc.swagger-ui.path=/swagger-ui-custom.html + +# custom path for api docs +springdoc.api-docs.path=/api-docs diff --git a/rxjava-2/src/main/resources/logback.xml b/spring-boot-springdoc/src/main/resources/logback.xml similarity index 71% rename from rxjava-2/src/main/resources/logback.xml rename to spring-boot-springdoc/src/main/resources/logback.xml index 7d900d8ea8..6a07b178e9 100644 --- a/rxjava-2/src/main/resources/logback.xml +++ b/spring-boot-springdoc/src/main/resources/logback.xml @@ -7,6 +7,9 @@ + + + diff --git a/spring-boot-springdoc/src/test/java/com/baeldung/springdoc/SpringContextIntegrationTest.java b/spring-boot-springdoc/src/test/java/com/baeldung/springdoc/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..58c12dc3bc --- /dev/null +++ b/spring-boot-springdoc/src/test/java/com/baeldung/springdoc/SpringContextIntegrationTest.java @@ -0,0 +1,17 @@ +package com.baeldung.springdoc; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + + } + +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/Application.java b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/Application.java new file mode 100644 index 0000000000..0472ba4e7b --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/Application.java @@ -0,0 +1,14 @@ +package com.baeldung.flash_attributes; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java new file mode 100644 index 0000000000..6264ea0531 --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java @@ -0,0 +1,49 @@ +package com.baeldung.flash_attributes.controllers; + +import com.baeldung.flash_attributes.model.Poem; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.support.RequestContextUtils; +import org.springframework.web.servlet.view.RedirectView; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +@Controller +public class PoemSubmission { + + @GetMapping("/poem/success") + public String getSuccess(HttpServletRequest request) { + Map inputFlashMap = RequestContextUtils.getInputFlashMap(request); + if (inputFlashMap != null) { + Poem poem = (Poem) inputFlashMap.get("poem"); + return "success"; + } else { + return "redirect:/poem/submit"; + } + } + + @PostMapping("/poem/submit") + public RedirectView submitPost( + HttpServletRequest request, + @ModelAttribute Poem poem, + RedirectAttributes redirectAttributes) { + if (Poem.isValidPoem(poem)) { + redirectAttributes.addFlashAttribute("poem", poem); + return new RedirectView("/poem/success", true); + } else { + return new RedirectView("/poem/submit", true); + } + } + + @GetMapping("/poem/submit") + public String submitGet(Model model) { + model.addAttribute("poem", new Poem()); + return "submit"; + } + +} \ No newline at end of file diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/model/Poem.java b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/model/Poem.java new file mode 100644 index 0000000000..bff65456c1 --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/flash_attributes/model/Poem.java @@ -0,0 +1,39 @@ +package com.baeldung.flash_attributes.model; + +import org.apache.logging.log4j.util.Strings; + +public class Poem { + private String title; + private String author; + private String body; + + public static boolean isValidPoem(Poem poem) { + return poem != null && Strings.isNotBlank(poem.getAuthor()) && Strings.isNotBlank(poem.getBody()) + && Strings.isNotBlank(poem.getTitle()); + } + + public String getTitle() { + return this.title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return this.body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getAuthor() { + return this.author; + } + + public void setAuthor(String author) { + this.author = author; + } + +} diff --git a/spring-mvc-simple-2/src/main/resources/application.properties b/spring-mvc-simple-2/src/main/resources/application.properties index d29338d3d3..aca20f4e3c 100644 --- a/spring-mvc-simple-2/src/main/resources/application.properties +++ b/spring-mvc-simple-2/src/main/resources/application.properties @@ -1,3 +1,9 @@ spring.main.allow-bean-definition-overriding=true + spring.mail.host=localhost -spring.mail.port=8025 \ No newline at end of file +spring.mail.port=8025 + +spring.thymeleaf.cache=false +spring.thymeleaf.enabled=true +spring.thymeleaf.prefix=classpath:/templates/ +spring.thymeleaf.suffix=.html diff --git a/spring-mvc-simple-2/src/main/resources/templates/submit.html b/spring-mvc-simple-2/src/main/resources/templates/submit.html new file mode 100644 index 0000000000..0ed0107c20 --- /dev/null +++ b/spring-mvc-simple-2/src/main/resources/templates/submit.html @@ -0,0 +1,50 @@ + + + + Poetry Contest: Submission + + + +
+ + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + +