diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/rotatearray/RotateArray.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/rotatearray/RotateArray.java
new file mode 100644
index 0000000000..36490d4899
--- /dev/null
+++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/rotatearray/RotateArray.java
@@ -0,0 +1,102 @@
+package com.baeldung.algorithms.rotatearray;
+
+/**
+ * To speed up the rotation, we narrow k rotations to the remainder of k divided by the array length, or k module the array length.
+ * Therefore, a large rotation number will be translated into the relative smallest rotation.
+ * All solutions replace the original array, although they might use an extra array to compute the rotation.
+ */
+public class RotateArray {
+
+ private RotateArray() {
+ throw new IllegalStateException("Rotate array algorithm utility methods class");
+ }
+
+ /**
+ *
+ * @param arr array to apply rotation to
+ * @param k number of rotations
+ */
+ public static void bruteForce(int[] arr, int k) {
+ checkInvalidInput(arr, k);
+
+ k %= arr.length;
+ int temp;
+ int previous;
+ for (int i = 0; i < k; i++) {
+ previous = arr[arr.length - 1];
+ for (int j = 0; j < arr.length; j++) {
+ temp = arr[j];
+ arr[j] = previous;
+ previous = temp;
+ }
+ }
+ }
+
+ /**
+ *
+ * @param arr array to apply rotation to
+ * @param k number of rotations
+ */
+ public static void withExtraArray(int[] arr, int k) {
+ checkInvalidInput(arr, k);
+
+ int[] extraArray = new int[arr.length];
+ for (int i = 0; i < arr.length; i++) {
+ extraArray[(i + k) % arr.length] = arr[i];
+ }
+ System.arraycopy(extraArray, 0, arr, 0, arr.length);
+ }
+
+ /**
+ *
+ * @param arr array to apply rotation to
+ * @param k number of rotations
+ */
+ public static void cyclicReplacement(int[] arr, int k) {
+ checkInvalidInput(arr, k);
+
+ k = k % arr.length;
+ int count = 0;
+ for (int start = 0; count < arr.length; start++) {
+ int current = start;
+ int prev = arr[start];
+ do {
+ int next = (current + k) % arr.length;
+ int temp = arr[next];
+ arr[next] = prev;
+ prev = temp;
+ current = next;
+ count++;
+ } while (start != current);
+ }
+ }
+
+ /**
+ *
+ * @param arr array to apply rotation to
+ * @param k number of rotations
+ */
+ public static void reverse(int[] arr, int k) {
+ checkInvalidInput(arr, k);
+
+ k %= arr.length;
+ reverse(arr, 0, arr.length - 1);
+ reverse(arr, 0, k - 1);
+ reverse(arr, k, arr.length - 1);
+ }
+
+ private static void reverse(int[] nums, int start, int end) {
+ while (start < end) {
+ int temp = nums[start];
+ nums[start] = nums[end];
+ nums[end] = temp;
+ start++;
+ end--;
+ }
+ }
+
+ private static void checkInvalidInput(int[] arr, int rotation) {
+ if (rotation < 1 || arr == null)
+ throw new IllegalArgumentException("Rotation must be greater than zero or array must be not null");
+ }
+}
diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/rotatearray/RotateArrayUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/rotatearray/RotateArrayUnitTest.java
new file mode 100644
index 0000000000..4a98acdb75
--- /dev/null
+++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/rotatearray/RotateArrayUnitTest.java
@@ -0,0 +1,124 @@
+package com.baeldung.algorithms.rotatearray;
+
+import static com.baeldung.algorithms.rotatearray.RotateArray.bruteForce;
+import static com.baeldung.algorithms.rotatearray.RotateArray.cyclicReplacement;
+import static com.baeldung.algorithms.rotatearray.RotateArray.reverse;
+import static com.baeldung.algorithms.rotatearray.RotateArray.withExtraArray;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class RotateArrayUnitTest {
+
+ private final int[] arr = { 1, 2, 3, 4, 5, 6 };
+ private final int rotationLtArrayLength = 1;
+ private final int rotationGtArrayLength = arr.length + 2;
+ private final int[] ltArrayLengthRotation = { 6, 1, 2, 3, 4, 5 };
+ private final int[] gtArrayLengthRotation = { 5, 6, 1, 2, 3, 4 };
+
+ @Test
+ void givenInputArray_whenNoRotationOrEmptyArray_thenThrowIllegalArgumentException() {
+ final int noRotation = 0;
+ final int someRotation = arr.length - 1;
+
+ assertThrows(IllegalArgumentException.class, () -> bruteForce(arr, noRotation));
+ assertThrows(IllegalArgumentException.class, () -> withExtraArray(arr, noRotation));
+ assertThrows(IllegalArgumentException.class, () -> cyclicReplacement(arr, noRotation));
+ assertThrows(IllegalArgumentException.class, () -> reverse(arr, noRotation));
+
+ assertThrows(IllegalArgumentException.class, () -> bruteForce(null, someRotation));
+ assertThrows(IllegalArgumentException.class, () -> withExtraArray(null, someRotation));
+ assertThrows(IllegalArgumentException.class, () -> cyclicReplacement(null, someRotation));
+ assertThrows(IllegalArgumentException.class, () -> reverse(null, someRotation));
+ }
+
+ @Test
+ void givenInputArray_whenUseBruteForceRotationLtArrayLength_thenRotateArrayOk() {
+
+ bruteForce(arr, rotationLtArrayLength);
+ assertArrayEquals(ltArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseBruteForceRotationGtArrayLength_thenRotateArrayOk() {
+
+ bruteForce(arr, rotationGtArrayLength);
+ assertArrayEquals(gtArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseBruteForceRotationEqArrayLength_thenDoNothing() {
+ int[] expected = arr.clone();
+
+ bruteForce(arr, arr.length);
+ assertArrayEquals(expected, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseExtraArrayRotationLtArrayLength_thenRotateArrayOk() {
+
+ withExtraArray(arr, rotationLtArrayLength);
+ assertArrayEquals(ltArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseExtraArrayRotationGtArrayLength_thenRotateArrayOk() {
+
+ withExtraArray(arr, rotationGtArrayLength);
+ assertArrayEquals(gtArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseExtraArrayWithRotationEqArrayLength_thenDoNothing() {
+ int[] clone = arr.clone();
+
+ withExtraArray(arr, arr.length);
+ assertArrayEquals(clone, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseCyclicReplacementRotationLtArrayLength_thenRotateArrayOk() {
+
+ cyclicReplacement(arr, rotationLtArrayLength);
+ assertArrayEquals(ltArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseCyclicReplacementRotationGtArrayLength_thenRotateArrayOk() {
+
+ cyclicReplacement(arr, rotationGtArrayLength);
+ assertArrayEquals(gtArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseCyclicReplacementRotationEqArrayLength_thenDoNothing() {
+ int[] clone = arr.clone();
+
+ cyclicReplacement(arr, arr.length);
+ assertArrayEquals(clone, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseReverseRotationLtArrayLength_thenRotateArrayOk() {
+
+ reverse(arr, rotationLtArrayLength);
+ assertArrayEquals(ltArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseReverseRotationGtArrayLength_thenRotateArrayOk() {
+
+ reverse(arr, rotationGtArrayLength);
+ assertArrayEquals(gtArrayLengthRotation, arr);
+ }
+
+ @Test
+ void givenInputArray_whenUseReverseRotationEqArrayLength_thenDoNothing() {
+
+ int[] clone = arr.clone();
+
+ reverse(arr, arr.length);
+ assertArrayEquals(clone, arr);
+ }
+}
diff --git a/aws-modules/aws-dynamodb/.gitignore b/aws-modules/aws-dynamodb/.gitignore
new file mode 100644
index 0000000000..bf11a4cc38
--- /dev/null
+++ b/aws-modules/aws-dynamodb/.gitignore
@@ -0,0 +1,2 @@
+/target/
+.idea/
\ No newline at end of file
diff --git a/aws-modules/aws-dynamodb/README.md b/aws-modules/aws-dynamodb/README.md
new file mode 100644
index 0000000000..68a353e555
--- /dev/null
+++ b/aws-modules/aws-dynamodb/README.md
@@ -0,0 +1,7 @@
+## AWS DYNAMODB
+
+This module contains articles about AWS DynamoDB
+
+### Relevant articles
+- [Integration Testing with a Local DynamoDB Instance](https://www.baeldung.com/dynamodb-local-integration-tests)
+
diff --git a/aws-modules/aws-dynamodb/pom.xml b/aws-modules/aws-dynamodb/pom.xml
new file mode 100644
index 0000000000..37b88327f4
--- /dev/null
+++ b/aws-modules/aws-dynamodb/pom.xml
@@ -0,0 +1,87 @@
+
+
+ 4.0.0
+ aws-dynamodb
+ 0.1.0-SNAPSHOT
+ aws-dynamodb
+ jar
+
+
+ com.baeldung
+ aws-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ com.amazonaws
+ aws-java-sdk
+ ${aws-java-sdk.version}
+
+
+ com.amazonaws
+ DynamoDBLocal
+ ${dynamodblocal.version}
+ test
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ ${maven-shade-plugin.version}
+
+ false
+
+
+
+ package
+
+ shade
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ ${maven-plugins-version}
+
+
+ copy
+ compile
+
+ copy-dependencies
+
+
+
+ so,dll,dylib
+ native-libs
+
+
+
+
+
+
+
+
+ 2.8.0
+ 1.21.1
+ 3.1.1
+
+
+
\ No newline at end of file
diff --git a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/dynamodb/entity/ProductInfo.java b/aws-modules/aws-dynamodb/src/main/java/com/baeldung/dynamodb/entity/ProductInfo.java
similarity index 100%
rename from aws-modules/aws-miscellaneous/src/main/java/com/baeldung/dynamodb/entity/ProductInfo.java
rename to aws-modules/aws-dynamodb/src/main/java/com/baeldung/dynamodb/entity/ProductInfo.java
diff --git a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/dynamodb/repository/AbstractRepository.java b/aws-modules/aws-dynamodb/src/main/java/com/baeldung/dynamodb/repository/AbstractRepository.java
similarity index 100%
rename from aws-modules/aws-miscellaneous/src/main/java/com/baeldung/dynamodb/repository/AbstractRepository.java
rename to aws-modules/aws-dynamodb/src/main/java/com/baeldung/dynamodb/repository/AbstractRepository.java
diff --git a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/dynamodb/repository/ProductInfoRepository.java b/aws-modules/aws-dynamodb/src/main/java/com/baeldung/dynamodb/repository/ProductInfoRepository.java
similarity index 100%
rename from aws-modules/aws-miscellaneous/src/main/java/com/baeldung/dynamodb/repository/ProductInfoRepository.java
rename to aws-modules/aws-dynamodb/src/main/java/com/baeldung/dynamodb/repository/ProductInfoRepository.java
diff --git a/aws-modules/aws-dynamodb/src/main/resources/logback.xml b/aws-modules/aws-dynamodb/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/aws-modules/aws-dynamodb/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws-modules/aws-miscellaneous/src/test/java/com/baeldung/dynamodb/ProductInfoRepositoryIntegrationTest.java b/aws-modules/aws-dynamodb/src/test/java/com/baeldung/dynamodb/ProductInfoRepositoryIntegrationTest.java
similarity index 91%
rename from aws-modules/aws-miscellaneous/src/test/java/com/baeldung/dynamodb/ProductInfoRepositoryIntegrationTest.java
rename to aws-modules/aws-dynamodb/src/test/java/com/baeldung/dynamodb/ProductInfoRepositoryIntegrationTest.java
index 18f55544cd..e4dc0c65b8 100644
--- a/aws-modules/aws-miscellaneous/src/test/java/com/baeldung/dynamodb/ProductInfoRepositoryIntegrationTest.java
+++ b/aws-modules/aws-dynamodb/src/test/java/com/baeldung/dynamodb/ProductInfoRepositoryIntegrationTest.java
@@ -49,10 +49,10 @@ public class ProductInfoRepositoryIntegrationTest {
@BeforeClass
public static void setupClass() {
Properties testProperties = loadFromFileInClasspath("test.properties")
- .filter(properties -> !isEmpty(properties.getProperty(AWS_ACCESSKEY)))
- .filter(properties -> !isEmpty(properties.getProperty(AWS_SECRETKEY)))
- .filter(properties -> !isEmpty(properties.getProperty(DYNAMODB_ENDPOINT)))
- .orElseThrow(() -> new RuntimeException("Unable to get all of the required test property values"));
+ .filter(properties -> !isEmpty(properties.getProperty(AWS_ACCESSKEY)))
+ .filter(properties -> !isEmpty(properties.getProperty(AWS_SECRETKEY)))
+ .filter(properties -> !isEmpty(properties.getProperty(DYNAMODB_ENDPOINT)))
+ .orElseThrow(() -> new RuntimeException("Unable to get all of the required test property values"));
String amazonAWSAccessKey = testProperties.getProperty(AWS_ACCESSKEY);
String amazonAWSSecretKey = testProperties.getProperty(AWS_SECRETKEY);
diff --git a/aws-modules/aws-miscellaneous/src/test/java/com/baeldung/dynamodb/rule/LocalDbCreationRule.java b/aws-modules/aws-dynamodb/src/test/java/com/baeldung/dynamodb/rule/LocalDbCreationRule.java
similarity index 100%
rename from aws-modules/aws-miscellaneous/src/test/java/com/baeldung/dynamodb/rule/LocalDbCreationRule.java
rename to aws-modules/aws-dynamodb/src/test/java/com/baeldung/dynamodb/rule/LocalDbCreationRule.java
diff --git a/aws-modules/aws-miscellaneous/src/test/resources/test.properties b/aws-modules/aws-dynamodb/src/test/resources/test.properties
similarity index 100%
rename from aws-modules/aws-miscellaneous/src/test/resources/test.properties
rename to aws-modules/aws-dynamodb/src/test/resources/test.properties
diff --git a/aws-modules/aws-miscellaneous/pom.xml b/aws-modules/aws-miscellaneous/pom.xml
index 2fb7e397a0..4126256fb9 100644
--- a/aws-modules/aws-miscellaneous/pom.xml
+++ b/aws-modules/aws-miscellaneous/pom.xml
@@ -16,31 +16,9 @@
- com.amazonaws
- aws-java-sdk
- ${aws-java-sdk.version}
-
-
- com.amazonaws
- aws-lambda-java-core
- ${aws-lambda-java-core.version}
-
-
- commons-logging
- commons-logging
-
-
-
-
- com.amazonaws
- aws-lambda-java-events
- ${aws-lambda-java-events.version}
-
-
- commons-logging
- commons-logging
-
-
+ software.amazon.awssdk
+ aws-sdk-java
+ ${aws-java-sdk-v2.version}
commons-io
@@ -52,12 +30,6 @@
gson
${gson.version}
-
- com.amazonaws
- DynamoDBLocal
- ${dynamodblocal.version}
- test
-
@@ -101,8 +73,6 @@
- 1.3.0
- 1.1.0
2.8.0
1.21.1
1.10.L001
diff --git a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/ec2/EC2Application.java b/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/ec2/EC2Application.java
index 6755188fcd..e12a38e1de 100644
--- a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/ec2/EC2Application.java
+++ b/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/ec2/EC2Application.java
@@ -2,136 +2,148 @@ package com.baeldung.ec2;
import java.util.Arrays;
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.regions.Regions;
-import com.amazonaws.services.ec2.AmazonEC2;
-import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
-import com.amazonaws.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
-import com.amazonaws.services.ec2.model.CreateKeyPairRequest;
-import com.amazonaws.services.ec2.model.CreateKeyPairResult;
-import com.amazonaws.services.ec2.model.CreateSecurityGroupRequest;
-import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
-import com.amazonaws.services.ec2.model.DescribeInstancesResult;
-import com.amazonaws.services.ec2.model.DescribeKeyPairsRequest;
-import com.amazonaws.services.ec2.model.DescribeKeyPairsResult;
-import com.amazonaws.services.ec2.model.IpPermission;
-import com.amazonaws.services.ec2.model.IpRange;
-import com.amazonaws.services.ec2.model.MonitorInstancesRequest;
-import com.amazonaws.services.ec2.model.RebootInstancesRequest;
-import com.amazonaws.services.ec2.model.RunInstancesRequest;
-import com.amazonaws.services.ec2.model.StartInstancesRequest;
-import com.amazonaws.services.ec2.model.StopInstancesRequest;
-import com.amazonaws.services.ec2.model.UnmonitorInstancesRequest;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.ec2.Ec2Client;
+import software.amazon.awssdk.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
+import software.amazon.awssdk.services.ec2.model.CreateKeyPairRequest;
+import software.amazon.awssdk.services.ec2.model.CreateKeyPairResponse;
+import software.amazon.awssdk.services.ec2.model.CreateSecurityGroupRequest;
+import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
+import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
+import software.amazon.awssdk.services.ec2.model.DescribeKeyPairsRequest;
+import software.amazon.awssdk.services.ec2.model.DescribeKeyPairsResponse;
+import software.amazon.awssdk.services.ec2.model.IpPermission;
+import software.amazon.awssdk.services.ec2.model.IpRange;
+import software.amazon.awssdk.services.ec2.model.MonitorInstancesRequest;
+import software.amazon.awssdk.services.ec2.model.RebootInstancesRequest;
+import software.amazon.awssdk.services.ec2.model.RunInstancesRequest;
+import software.amazon.awssdk.services.ec2.model.RunInstancesResponse;
+import software.amazon.awssdk.services.ec2.model.StartInstancesRequest;
+import software.amazon.awssdk.services.ec2.model.StartInstancesResponse;
+import software.amazon.awssdk.services.ec2.model.StopInstancesRequest;
+import software.amazon.awssdk.services.ec2.model.UnmonitorInstancesRequest;
public class EC2Application {
- private static final AWSCredentials credentials;
-
- static {
- // put your accesskey and secretkey here
- credentials = new BasicAWSCredentials(
- "",
- ""
- );
- }
-
public static void main(String[] args) {
// Set up the client
- AmazonEC2 ec2Client = AmazonEC2ClientBuilder.standard()
- .withCredentials(new AWSStaticCredentialsProvider(credentials))
- .withRegion(Regions.US_EAST_1)
+ Ec2Client ec2Client = Ec2Client.builder()
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .region(Region.US_EAST_1)
.build();
// Create a security group
- CreateSecurityGroupRequest createSecurityGroupRequest = new CreateSecurityGroupRequest().withGroupName("BaeldungSecurityGroup")
- .withDescription("Baeldung Security Group");
+ CreateSecurityGroupRequest createSecurityGroupRequest = CreateSecurityGroupRequest.builder()
+ .groupName("BaeldungSecurityGroup")
+ .description("Baeldung Security Group")
+ .build();
+
ec2Client.createSecurityGroup(createSecurityGroupRequest);
// Allow HTTP and SSH traffic
- IpRange ipRange1 = new IpRange().withCidrIp("0.0.0.0/0");
+ IpRange ipRange1 = IpRange.builder()
+ .cidrIp("0.0.0.0/0")
+ .build();
- IpPermission ipPermission1 = new IpPermission().withIpv4Ranges(Arrays.asList(new IpRange[] { ipRange1 }))
- .withIpProtocol("tcp")
- .withFromPort(80)
- .withToPort(80);
+ IpPermission ipPermission1 = IpPermission.builder()
+ .ipRanges(Arrays.asList(ipRange1))
+ .ipProtocol("tcp")
+ .fromPort(80)
+ .toPort(80)
+ .build();
- IpPermission ipPermission2 = new IpPermission().withIpv4Ranges(Arrays.asList(new IpRange[] { ipRange1 }))
- .withIpProtocol("tcp")
- .withFromPort(22)
- .withToPort(22);
+ IpPermission ipPermission2 = IpPermission.builder()
+ .ipRanges(Arrays.asList(ipRange1))
+ .ipProtocol("tcp")
+ .fromPort(22)
+ .toPort(22)
+ .build();
- AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = new AuthorizeSecurityGroupIngressRequest()
- .withGroupName("BaeldungSecurityGroup")
- .withIpPermissions(ipPermission1, ipPermission2);
+ AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = AuthorizeSecurityGroupIngressRequest
+ .builder()
+ .groupName("BaeldungSecurityGroup")
+ .ipPermissions(ipPermission1, ipPermission2)
+ .build();
ec2Client.authorizeSecurityGroupIngress(authorizeSecurityGroupIngressRequest);
// Create KeyPair
- CreateKeyPairRequest createKeyPairRequest = new CreateKeyPairRequest()
- .withKeyName("baeldung-key-pair");
- CreateKeyPairResult createKeyPairResult = ec2Client.createKeyPair(createKeyPairRequest);
- String privateKey = createKeyPairResult
- .getKeyPair()
- .getKeyMaterial(); // make sure you keep it, the private key, Amazon doesn't store the private key
+ CreateKeyPairRequest createKeyPairRequest = CreateKeyPairRequest.builder()
+ .keyName("baeldung-key-pair")
+ .build();
+
+ CreateKeyPairResponse createKeyPairResponse = ec2Client.createKeyPair(createKeyPairRequest);
+ String privateKey = createKeyPairResponse.keyMaterial();
+ // make sure you keep it, the private key, Amazon doesn't store the private key
// See what key-pairs you've got
- DescribeKeyPairsRequest describeKeyPairsRequest = new DescribeKeyPairsRequest();
- DescribeKeyPairsResult describeKeyPairsResult = ec2Client.describeKeyPairs(describeKeyPairsRequest);
+ DescribeKeyPairsRequest describeKeyPairsRequest = DescribeKeyPairsRequest.builder()
+ .build();
+ DescribeKeyPairsResponse describeKeyPairsResponse = ec2Client.describeKeyPairs(describeKeyPairsRequest);
// Launch an Amazon Instance
- RunInstancesRequest runInstancesRequest = new RunInstancesRequest().withImageId("ami-97785bed") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/usingsharedamis-finding.html
- .withInstanceType("t2.micro") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html
- .withMinCount(1)
- .withMaxCount(1)
- .withKeyName("baeldung-key-pair") // optional - if not present, can't connect to instance
- .withSecurityGroups("BaeldungSecurityGroup");
+ RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder()
+ .imageId("ami-97785bed")
+ .instanceType("t2.micro") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html
+ .minCount(1)
+ .maxCount(1)
+ .keyName("baeldung-key-pair") // optional - if not present, can't connect to instance
+ .securityGroups("BaeldungSecurityGroup")
+ .build();
- String yourInstanceId = ec2Client.runInstances(runInstancesRequest).getReservation().getInstances().get(0).getInstanceId();
+ RunInstancesResponse runInstancesResponse = ec2Client.runInstances(runInstancesRequest);
+ String yourInstanceId = runInstancesResponse.instances().get(0).instanceId();
// Start an Instance
- StartInstancesRequest startInstancesRequest = new StartInstancesRequest()
- .withInstanceIds(yourInstanceId);
+ StartInstancesRequest startInstancesRequest = StartInstancesRequest.builder()
+ .instanceIds(yourInstanceId)
+ .build();
+
+ StartInstancesResponse startInstancesResponse = ec2Client.startInstances(startInstancesRequest);
- ec2Client.startInstances(startInstancesRequest);
// Monitor Instances
- MonitorInstancesRequest monitorInstancesRequest = new MonitorInstancesRequest()
- .withInstanceIds(yourInstanceId);
+ MonitorInstancesRequest monitorInstancesRequest = MonitorInstancesRequest.builder()
+ .instanceIds(yourInstanceId)
+ .build();
+
ec2Client.monitorInstances(monitorInstancesRequest);
- UnmonitorInstancesRequest unmonitorInstancesRequest = new UnmonitorInstancesRequest()
- .withInstanceIds(yourInstanceId);
+ UnmonitorInstancesRequest unmonitorInstancesRequest = UnmonitorInstancesRequest.builder()
+ .instanceIds(yourInstanceId)
+ .build();
ec2Client.unmonitorInstances(unmonitorInstancesRequest);
// Reboot an Instance
-
- RebootInstancesRequest rebootInstancesRequest = new RebootInstancesRequest()
- .withInstanceIds(yourInstanceId);
+ RebootInstancesRequest rebootInstancesRequest = RebootInstancesRequest.builder()
+ .instanceIds(yourInstanceId)
+ .build();
ec2Client.rebootInstances(rebootInstancesRequest);
// Stop an Instance
- StopInstancesRequest stopInstancesRequest = new StopInstancesRequest()
- .withInstanceIds(yourInstanceId);
+ StopInstancesRequest stopInstancesRequest = StopInstancesRequest.builder()
+ .instanceIds(yourInstanceId)
+ .build();
+
ec2Client.stopInstances(stopInstancesRequest)
- .getStoppingInstances()
+ .stoppingInstances()
.get(0)
- .getPreviousState()
- .getName();
+ .previousState()
+ .name();
// Describe an Instance
- DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest();
- DescribeInstancesResult response = ec2Client.describeInstances(describeInstancesRequest);
- System.out.println(response.getReservations()
+ DescribeInstancesRequest describeInstancesRequest = DescribeInstancesRequest.builder().build();
+ DescribeInstancesResponse response = ec2Client.describeInstances(describeInstancesRequest);
+ System.out.println(response.reservations()
.get(0)
- .getInstances()
+ .instances()
.get(0)
- .getKernelId());
+ .kernelId());
}
}
diff --git a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/rds/AWSRDSService.java b/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/rds/AWSRDSService.java
index d4da92f30f..09309b92bb 100644
--- a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/rds/AWSRDSService.java
+++ b/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/rds/AWSRDSService.java
@@ -1,13 +1,5 @@
package com.baeldung.rds;
-import com.amazonaws.auth.AWSCredentialsProvider;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.regions.Regions;
-import com.amazonaws.services.rds.AmazonRDS;
-import com.amazonaws.services.rds.AmazonRDSClientBuilder;
-import com.amazonaws.services.rds.model.*;
-
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
@@ -16,12 +8,22 @@ import java.util.Properties;
import java.util.UUID;
import java.util.logging.Logger;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.rds.RdsClient;
+import software.amazon.awssdk.services.rds.model.CreateDbInstanceRequest;
+import software.amazon.awssdk.services.rds.model.CreateDbInstanceResponse;
+import software.amazon.awssdk.services.rds.model.DBInstance;
+import software.amazon.awssdk.services.rds.model.DeleteDbInstanceRequest;
+import software.amazon.awssdk.services.rds.model.DeleteDbInstanceResponse;
+import software.amazon.awssdk.services.rds.model.DescribeDbInstancesResponse;
+import software.amazon.awssdk.services.rds.model.Endpoint;
+
public class AWSRDSService {
final static Logger logger = Logger.getLogger(AWSRDSService.class.getName());
- private AWSCredentialsProvider credentials;
- private AmazonRDS amazonRDS;
+ private RdsClient rdsClient;
private String db_username;
private String db_password;
private String db_database;
@@ -34,22 +36,17 @@ public class AWSRDSService {
* **/
public AWSRDSService() throws IOException {
//Init RDS client with credentials and region.
- credentials = new
- AWSStaticCredentialsProvider(new
- BasicAWSCredentials("",
- ""));
- amazonRDS = AmazonRDSClientBuilder.standard().withCredentials(credentials)
- .withRegion(Regions.AP_SOUTHEAST_2).build();
Properties prop = new Properties();
InputStream input = AWSRDSService.class.getClassLoader().getResourceAsStream("db.properties");
prop.load(input);
db_username = prop.getProperty("db_username");
db_password = prop.getProperty("db_password");
db_database = prop.getProperty("db_database");
- }
- public AWSRDSService(AmazonRDS amazonRDS){
- this.amazonRDS = amazonRDS;
+ rdsClient = RdsClient.builder()
+ .region(Region.AP_SOUTHEAST_2)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
}
/**
@@ -60,29 +57,29 @@ public class AWSRDSService {
public String launchInstance() {
String identifier = "";
- CreateDBInstanceRequest request = new CreateDBInstanceRequest();
- // RDS instance name
- request.setDBInstanceIdentifier("Sydney");
- request.setEngine("postgres");
- request.setMultiAZ(false);
- request.setMasterUsername(db_username);
- request.setMasterUserPassword(db_password);
- request.setDBName(db_database);
- request.setStorageType("gp2");
- request.setAllocatedStorage(10);
+ CreateDbInstanceRequest instanceRequest = CreateDbInstanceRequest.builder()
+ .dbInstanceIdentifier("Sydney")
+ .engine("postgres")
+ .multiAZ(false)
+ .masterUsername(db_username)
+ .masterUserPassword(db_password)
+ .dbName(db_database)
+ .storageType("gp2")
+ .allocatedStorage(10)
+ .build();
- DBInstance instance = amazonRDS.createDBInstance(request);
+ CreateDbInstanceResponse createDbInstanceResponse = rdsClient.createDBInstance(instanceRequest);
// Information about the new RDS instance
- identifier = instance.getDBInstanceIdentifier();
- String status = instance.getDBInstanceStatus();
- Endpoint endpoint = instance.getEndpoint();
- String endpoint_url = "Endpoint URL not available yet.";
+ identifier = createDbInstanceResponse.dbInstance().dbInstanceIdentifier();
+ String status = createDbInstanceResponse.dbInstance().dbInstanceStatus();
+ Endpoint endpoint = createDbInstanceResponse.dbInstance().endpoint();
+ String endpointUrl = "Endpoint URL not available yet.";
if (endpoint != null) {
- endpoint_url = endpoint.toString();
+ endpointUrl = endpoint.toString();
}
logger.info(identifier + "\t" + status);
- logger.info(endpoint_url);
+ logger.info(endpointUrl);
return identifier;
@@ -90,44 +87,44 @@ public class AWSRDSService {
// Describe DB instances
public void listInstances() {
- DescribeDBInstancesResult result = amazonRDS.describeDBInstances();
- List instances = result.getDBInstances();
+ DescribeDbInstancesResponse response = rdsClient.describeDBInstances();
+ List instances = response.dbInstances();
for (DBInstance instance : instances) {
// Information about each RDS instance
- String identifier = instance.getDBInstanceIdentifier();
- String engine = instance.getEngine();
- String status = instance.getDBInstanceStatus();
- Endpoint endpoint = instance.getEndpoint();
- String endpoint_url = "Endpoint URL not available yet.";
+ String identifier = instance.dbInstanceIdentifier();
+ String engine = instance.engine();
+ String status = instance.dbInstanceStatus();
+ Endpoint endpoint = instance.endpoint();
+ String endpointUrl = "Endpoint URL not available yet.";
if (endpoint != null) {
- endpoint_url = endpoint.toString();
+ endpointUrl = endpoint.toString();
}
logger.info(identifier + "\t" + engine + "\t" + status);
- logger.info("\t" + endpoint_url);
+ logger.info("\t" + endpointUrl);
}
-
}
//Delete RDS instance
public void terminateInstance(String identifier) {
- DeleteDBInstanceRequest request = new DeleteDBInstanceRequest();
- request.setDBInstanceIdentifier(identifier);
- request.setSkipFinalSnapshot(true);
+ DeleteDbInstanceRequest request = DeleteDbInstanceRequest.builder()
+ .dbInstanceIdentifier(identifier)
+ .skipFinalSnapshot(true)
+ .build();
// Delete the RDS instance
- DBInstance instance = amazonRDS.deleteDBInstance(request);
+ DeleteDbInstanceResponse response = rdsClient.deleteDBInstance(request);
// Information about the RDS instance being deleted
- String status = instance.getDBInstanceStatus();
- Endpoint endpoint = instance.getEndpoint();
- String endpoint_url = "Endpoint URL not available yet.";
+ String status = response.dbInstance().dbInstanceStatus();
+ Endpoint endpoint = response.dbInstance().endpoint();
+ String endpointUrl = "Endpoint URL not available yet.";
if (endpoint != null) {
- endpoint_url = endpoint.toString();
+ endpointUrl = endpoint.toString();
}
logger.info(identifier + "\t" + status);
- logger.info(endpoint_url);
+ logger.info(endpointUrl);
}
diff --git a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/sqs/SQSApplication.java b/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/sqs/SQSApplication.java
index 978506a24f..3b78d73f60 100644
--- a/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/sqs/SQSApplication.java
+++ b/aws-modules/aws-miscellaneous/src/main/java/com/baeldung/sqs/SQSApplication.java
@@ -5,140 +5,190 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.regions.Regions;
-import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
-import com.amazonaws.services.sqs.model.CreateQueueRequest;
-import com.amazonaws.services.sqs.model.DeleteMessageRequest;
-import com.amazonaws.services.sqs.model.GetQueueAttributesRequest;
-import com.amazonaws.services.sqs.model.GetQueueAttributesResult;
-import com.amazonaws.services.sqs.model.MessageAttributeValue;
-import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
-import com.amazonaws.services.sqs.model.SendMessageBatchRequest;
-import com.amazonaws.services.sqs.model.SendMessageRequest;
-import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;
-import com.amazonaws.services.sqs.model.SendMessageBatchRequestEntry;
-import com.amazonaws.services.sqs.model.Message;
-import com.amazonaws.services.sqs.AmazonSQS;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.CreateQueueRequest;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
+import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest;
+import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse;
+import software.amazon.awssdk.services.sqs.model.GetQueueUrlRequest;
+import software.amazon.awssdk.services.sqs.model.GetQueueUrlResponse;
+import software.amazon.awssdk.services.sqs.model.Message;
+import software.amazon.awssdk.services.sqs.model.MessageAttributeValue;
+import software.amazon.awssdk.services.sqs.model.QueueAttributeName;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry;
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
+import software.amazon.awssdk.services.sqs.model.SetQueueAttributesRequest;
public class SQSApplication {
- private static final AWSCredentials credentials;
-
- static {
- // put your accesskey and secretkey here
- credentials = new BasicAWSCredentials(
- "",
- ""
- );
- }
+ private static final String STANDARD_QUEUE_NAME = "baeldung-queue";
+ private static final String FIFO_QUEUE_NAME = "baeldung-queue.fifo";
+ private static final String DEAD_LETTER_QUEUE_NAME = "baeldung-dead-letter-queue";
public static void main(String[] args) {
// Set up the client
- AmazonSQS sqs = AmazonSQSClientBuilder.standard()
- .withCredentials(new AWSStaticCredentialsProvider(credentials))
- .withRegion(Regions.US_EAST_1)
+ SqsClient sqsClient = SqsClient.builder()
+ .region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create())
.build();
// Create a standard queue
+ CreateQueueRequest createStandardQueueRequest = CreateQueueRequest.builder()
+ .queueName(STANDARD_QUEUE_NAME)
+ .build();
- CreateQueueRequest createStandardQueueRequest = new CreateQueueRequest("baeldung-queue");
- String standardQueueUrl = sqs.createQueue(createStandardQueueRequest)
- .getQueueUrl();
+ sqsClient.createQueue(createStandardQueueRequest);
+
+ System.out.println("\nGet queue url");
+
+ GetQueueUrlResponse getQueueUrlResponse = sqsClient.getQueueUrl(GetQueueUrlRequest.builder()
+ .queueName(STANDARD_QUEUE_NAME)
+ .build());
+ String standardQueueUrl = getQueueUrlResponse.queueUrl();
System.out.println(standardQueueUrl);
// Create a fifo queue
+ Map queueAttributes = new HashMap<>();
+ queueAttributes.put(QueueAttributeName.FIFO_QUEUE, "true");
+ queueAttributes.put(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, "true");
- Map queueAttributes = new HashMap();
- queueAttributes.put("FifoQueue", "true");
- queueAttributes.put("ContentBasedDeduplication", "true");
+ CreateQueueRequest createFifoQueueRequest = CreateQueueRequest.builder()
+ .queueName(FIFO_QUEUE_NAME)
+ .attributes(queueAttributes)
+ .build();
- CreateQueueRequest createFifoQueueRequest = new CreateQueueRequest("baeldung-queue.fifo").withAttributes(queueAttributes);
- String fifoQueueUrl = sqs.createQueue(createFifoQueueRequest)
- .getQueueUrl();
+ sqsClient.createQueue(createFifoQueueRequest);
+
+ GetQueueUrlResponse getFifoQueueUrlResponse = sqsClient.getQueueUrl(GetQueueUrlRequest.builder()
+ .queueName(FIFO_QUEUE_NAME)
+ .build());
+
+ String fifoQueueUrl = getFifoQueueUrlResponse.queueUrl();
System.out.println(fifoQueueUrl);
// Set up a dead letter queue
+ CreateQueueRequest createDeadLetterQueueRequest = CreateQueueRequest.builder()
+ .queueName(DEAD_LETTER_QUEUE_NAME)
+ .build();
- String deadLetterQueueUrl = sqs.createQueue("baeldung-dead-letter-queue")
- .getQueueUrl();
+ String deadLetterQueueUrl = sqsClient.createQueue(createDeadLetterQueueRequest)
+ .queueUrl();
- GetQueueAttributesResult deadLetterQueueAttributes = sqs.getQueueAttributes(new GetQueueAttributesRequest(deadLetterQueueUrl).withAttributeNames("QueueArn"));
+ GetQueueAttributesRequest getQueueAttributesRequest = GetQueueAttributesRequest.builder()
+ .queueUrl(deadLetterQueueUrl)
+ .attributeNames(QueueAttributeName.QUEUE_ARN)
+ .build();
- String deadLetterQueueARN = deadLetterQueueAttributes.getAttributes()
+ GetQueueAttributesResponse deadLetterQueueAttributes = sqsClient.getQueueAttributes(getQueueAttributesRequest);
+
+ String deadLetterQueueARN = deadLetterQueueAttributes.attributes()
.get("QueueArn");
- SetQueueAttributesRequest queueAttributesRequest = new SetQueueAttributesRequest().withQueueUrl(standardQueueUrl)
- .addAttributesEntry("RedrivePolicy", "{\"maxReceiveCount\":\"2\", " + "\"deadLetterTargetArn\":\"" + deadLetterQueueARN + "\"}");
+ Map attributes = new HashMap<>();
+ attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\"maxReceiveCount\":\"5\", \"deadLetterTargetArn\":\"" + deadLetterQueueARN + "\"}");
- sqs.setQueueAttributes(queueAttributesRequest);
+ SetQueueAttributesRequest queueAttributesRequest = SetQueueAttributesRequest.builder()
+ .queueUrl(standardQueueUrl)
+ .attributes(attributes)
+ .build();
+
+ sqsClient.setQueueAttributes(queueAttributesRequest);
// Send a message to a standard queue
Map messageAttributes = new HashMap<>();
+ MessageAttributeValue messageAttributeValue = MessageAttributeValue.builder()
+ .stringValue("This is an attribute")
+ .dataType("String")
+ .build();
- messageAttributes.put("AttributeOne", new MessageAttributeValue().withStringValue("This is an attribute")
- .withDataType("String"));
+ messageAttributes.put("AttributeOne", messageAttributeValue);
- SendMessageRequest sendMessageStandardQueue = new SendMessageRequest().withQueueUrl(standardQueueUrl)
- .withMessageBody("A simple message.")
- .withDelaySeconds(30) // Message will arrive in the queue after 30 seconds. We can use this only in standard queues
- .withMessageAttributes(messageAttributes);
+ SendMessageRequest sendMessageStandardQueue = SendMessageRequest.builder()
+ .queueUrl(standardQueueUrl)
+ .messageBody("A simple message.")
+ .delaySeconds(30) // Message will arrive in the queue after 30 seconds. We can use this only in standard queues
+ .messageAttributes(messageAttributes)
+ .build();
- sqs.sendMessage(sendMessageStandardQueue);
+ sqsClient.sendMessage(sendMessageStandardQueue);
// Send a message to a fifo queue
- SendMessageRequest sendMessageFifoQueue = new SendMessageRequest().withQueueUrl(fifoQueueUrl)
- .withMessageBody("FIFO Queue")
- .withMessageGroupId("baeldung-group-1")
- .withMessageAttributes(messageAttributes);
+ SendMessageRequest sendMessageFifoQueue = SendMessageRequest.builder()
+ .queueUrl(fifoQueueUrl)
+ .messageBody("FIFO Queue")
+ .messageGroupId("baeldung-group-1")
+ .messageAttributes(messageAttributes)
+ .build();
- sqs.sendMessage(sendMessageFifoQueue);
+ sqsClient.sendMessage(sendMessageFifoQueue);
// Send multiple messages
List messageEntries = new ArrayList<>();
- messageEntries.add(new SendMessageBatchRequestEntry().withId("id-1")
- .withMessageBody("batch-1")
- .withMessageGroupId("baeldung-group-1"));
- messageEntries.add(new SendMessageBatchRequestEntry().withId("id-2")
- .withMessageBody("batch-2")
- .withMessageGroupId("baeldung-group-1"));
+ SendMessageBatchRequestEntry messageBatchRequestEntry1 = SendMessageBatchRequestEntry.builder()
+ .id("id-1")
+ .messageBody("batch-1")
+ .messageGroupId("baeldung-group-1")
+ .build();
- SendMessageBatchRequest sendMessageBatchRequest = new SendMessageBatchRequest(fifoQueueUrl, messageEntries);
- sqs.sendMessageBatch(sendMessageBatchRequest);
+ SendMessageBatchRequestEntry messageBatchRequestEntry2 = SendMessageBatchRequestEntry.builder()
+ .id("id-2")
+ .messageBody("batch-2")
+ .messageGroupId("baeldung-group-1")
+ .build();
+
+ messageEntries.add(messageBatchRequestEntry1);
+ messageEntries.add(messageBatchRequestEntry2);
+
+ SendMessageBatchRequest sendMessageBatchRequest = SendMessageBatchRequest.builder()
+ .queueUrl(fifoQueueUrl)
+ .entries(messageEntries)
+ .build();
+
+ sqsClient.sendMessageBatch(sendMessageBatchRequest);
// Read a message from a queue
- ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(fifoQueueUrl).withWaitTimeSeconds(10) // Long polling;
- .withMaxNumberOfMessages(1); // Max is 10
+ ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
+ .waitTimeSeconds(10)
+ .maxNumberOfMessages(10)
+ .build();
- List sqsMessages = sqs.receiveMessage(receiveMessageRequest)
- .getMessages();
+ List sqsMessages = sqsClient.receiveMessage(receiveMessageRequest)
+ .messages();
sqsMessages.get(0)
- .getAttributes();
+ .attributes();
sqsMessages.get(0)
- .getBody();
+ .body();
// Delete a message from a queue
+ DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
+ .queueUrl(fifoQueueUrl)
+ .receiptHandle(sqsMessages.get(0)
+ .receiptHandle())
+ .build();
- sqs.deleteMessage(new DeleteMessageRequest().withQueueUrl(fifoQueueUrl)
- .withReceiptHandle(sqsMessages.get(0)
- .getReceiptHandle()));
+ sqsClient.deleteMessage(deleteMessageRequest);
// Monitoring
- GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest(standardQueueUrl).withAttributeNames("All");
- GetQueueAttributesResult getQueueAttributesResult = sqs.getQueueAttributes(getQueueAttributesRequest);
- System.out.println(String.format("The number of messages on the queue: %s", getQueueAttributesResult.getAttributes()
+ GetQueueAttributesRequest getQueueAttributesRequestForMonitoring = GetQueueAttributesRequest.builder()
+ .queueUrl(standardQueueUrl)
+ .build();
+
+ GetQueueAttributesResponse attributesResponse = sqsClient.getQueueAttributes(getQueueAttributesRequestForMonitoring);
+ System.out.println(String.format("The number of messages on the queue: %s", attributesResponse.attributes()
.get("ApproximateNumberOfMessages")));
- System.out.println(String.format("The number of messages in flight: %s", getQueueAttributesResult.getAttributes()
+ System.out.println(String.format("The number of messages in flight: %s", attributesResponse.attributes()
.get("ApproximateNumberOfMessagesNotVisible")));
}
diff --git a/aws-modules/pom.xml b/aws-modules/pom.xml
index b94faafa86..66fa4bffa1 100644
--- a/aws-modules/pom.xml
+++ b/aws-modules/pom.xml
@@ -5,6 +5,14 @@
4.0.0
aws-modules
aws-modules
+
+
+ com.amazonaws
+ aws-java-sdk-dynamodb
+ 1.12.523
+ compile
+
+
pom
@@ -15,6 +23,7 @@
aws-app-sync
+ aws-dynamodb
aws-lambda-modules
aws-miscellaneous
aws-reactive
@@ -24,6 +33,7 @@
1.12.331
+ 2.20.147
3.0.0
diff --git a/core-java-modules/core-java-11-2/README.md b/core-java-modules/core-java-11-2/README.md
index ab8331f41c..b9dc82bc7f 100644
--- a/core-java-modules/core-java-11-2/README.md
+++ b/core-java-modules/core-java-11-2/README.md
@@ -5,7 +5,6 @@ This module contains articles about Java 11 core features
### Relevant articles
- [Guide To Java 8 Optional](https://www.baeldung.com/java-optional)
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
-- [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors)
- [New Features in Java 11](https://www.baeldung.com/java-11-new-features)
- [Getting the Java Version at Runtime](https://www.baeldung.com/get-java-version-runtime)
- [Invoking a SOAP Web Service in Java](https://www.baeldung.com/java-soap-web-service)
diff --git a/core-java-modules/core-java-16/README.md b/core-java-modules/core-java-16/README.md
index 11b0fba8d3..a0392dcfed 100644
--- a/core-java-modules/core-java-16/README.md
+++ b/core-java-modules/core-java-16/README.md
@@ -4,5 +4,4 @@
- [Guide to mapMulti in Stream API](https://www.baeldung.com/java-mapmulti)
- [Collecting Stream Elements into a List in Java](https://www.baeldung.com/java-stream-to-list-collecting)
- [New Features in Java 16](https://www.baeldung.com/java-16-new-features)
-- [Guide to Java 8 groupingBy Collector](https://www.baeldung.com/java-groupingby-collector)
- [Value-Based Classes in Java](https://www.baeldung.com/java-value-based-classes)
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java
index 13e2238274..a3055985af 100644
--- a/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java
@@ -30,6 +30,11 @@ public final class Point {
return new Point(x, y, z);
}
+ @Override
+ public String toString() {
+ return "Point{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
+ }
+
@Override
public boolean equals(Object other) {
if (other == null || getClass() != other.getClass())
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java
index 781f368982..fe031a652f 100644
--- a/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java
@@ -1,14 +1,17 @@
package com.baeldung.value_based_class;
+import java.util.ArrayList;
+import java.util.List;
+
import org.junit.Assert;
import org.junit.Test;
public class ValueBasedClassUnitTest {
@Test
public void givenAutoboxedAndPrimitive_whenCompared_thenReturnEquals() {
- int primitive_a = 125;
- Integer obj_a = 125; // this is autoboxed
- Assert.assertSame(primitive_a, obj_a);
+ List list = new ArrayList<>();
+ list.add(1); // this is autoboxed
+ Assert.assertEquals(list.get(0), Integer.valueOf(1));
}
@Test
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/recordproperties/ReadRecordPropertiesByReflectionUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/recordproperties/ReadRecordPropertiesByReflectionUnitTest.java
new file mode 100644
index 0000000000..4ffe3ecbeb
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/recordproperties/ReadRecordPropertiesByReflectionUnitTest.java
@@ -0,0 +1,89 @@
+package com.baeldung.recordproperties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.RecordComponent;
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.Test;
+
+record Player(String name, int age, Long score) {
+}
+
+public class ReadRecordPropertiesByReflectionUnitTest {
+ private static final Player ERIC = new Player("Eric", 28, 4242L);
+
+ @Test
+ void whenUsingRecordComponent_thenGetExpectedResult() {
+ var fields = new ArrayList();
+ RecordComponent[] components = Player.class.getRecordComponents();
+ for (var comp : components) {
+ try {
+ Field field = ERIC.getClass()
+ .getDeclaredField(comp.getName());
+ field.setAccessible(true);
+ fields.add(field);
+ } catch (NoSuchFieldException e) {
+ // for simplicity, error handling is skipped
+ }
+ }
+
+ assertEquals(3, fields.size());
+
+ var nameField = fields.get(0);
+ var ageField = fields.get(1);
+ var scoreField = fields.get(2);
+ try {
+ assertEquals("name", nameField.getName());
+ assertEquals(String.class, nameField.getType());
+ assertEquals("Eric", nameField.get(ERIC));
+
+ assertEquals("age", ageField.getName());
+ assertEquals(int.class, ageField.getType());
+ assertEquals(28, ageField.get(ERIC));
+
+ assertEquals("score", scoreField.getName());
+ assertEquals(Long.class, scoreField.getType());
+ assertEquals(4242L, scoreField.get(ERIC));
+ } catch (IllegalAccessException exception) {
+ // for simplicity, error handling is skipped
+ }
+
+ }
+
+ @Test
+ void whenUsingClassGetDeclaredField_thenGetExpectedResult() {
+ // record has no public fields
+ assertEquals(0, Player.class.getFields().length);
+
+ var fields = new ArrayList();
+ for (var field : Player.class.getDeclaredFields()) {
+ field.setAccessible(true);
+ fields.add(field);
+ }
+
+ assertEquals(3, fields.size());
+ var nameField = fields.get(0);
+ var ageField = fields.get(1);
+ var scoreField = fields.get(2);
+
+ try {
+ assertEquals("name", nameField.getName());
+ assertEquals(String.class, nameField.getType());
+ assertEquals("Eric", nameField.get(ERIC));
+
+ assertEquals("age", ageField.getName());
+ assertEquals(int.class, ageField.getType());
+ assertEquals(28, ageField.get(ERIC));
+
+ assertEquals("score", scoreField.getName());
+ assertEquals(Long.class, scoreField.getType());
+ assertEquals(4242L, scoreField.get(ERIC));
+ } catch (IllegalAccessException ex) {
+ // for simplicity, error handling is skipped
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-18/README.md b/core-java-modules/core-java-18/README.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/core-java-modules/core-java-18/pom.xml b/core-java-modules/core-java-18/pom.xml
new file mode 100644
index 0000000000..7af6258497
--- /dev/null
+++ b/core-java-modules/core-java-18/pom.xml
@@ -0,0 +1,55 @@
+
+
+ 4.0.0
+ core-java-18
+ core-java-18
+ jar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.release}
+ --enable-preview
+ ${maven.compiler.source.version}
+ ${maven.compiler.target.version}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${surefire.plugin.version}
+
+ 1
+
+
+
+ org.apache.maven.surefire
+ surefire-api
+ ${surefire.plugin.version}
+
+
+
+
+
+
+
+ 18
+ 18
+ 18
+ 3.0.0-M5
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/FinalizationExamples.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/FinalizationExamples.java
new file mode 100644
index 0000000000..3ff77c37d6
--- /dev/null
+++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/FinalizationExamples.java
@@ -0,0 +1,27 @@
+package com.baeldung.finalization_closeable_cleaner;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class FinalizationExamples {
+ FileInputStream fis = null;
+
+ public void readFileOperationWithFinalization() throws IOException {
+ try {
+ fis = new FileInputStream("input.txt");
+ // perform operation on the file
+ System.out.println(fis.readAllBytes().length);
+
+ } finally {
+ if (fis != null)
+ fis.close();
+ }
+ }
+
+ public void readFileOperationWithTryWith() throws IOException {
+ try (FileInputStream fis = new FileInputStream("input.txt")) {
+ // perform operations
+ System.out.println(fis.readAllBytes().length);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyCleanerResourceClass.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyCleanerResourceClass.java
new file mode 100644
index 0000000000..1dcdd216cb
--- /dev/null
+++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyCleanerResourceClass.java
@@ -0,0 +1,48 @@
+package com.baeldung.finalization_closeable_cleaner;
+
+import java.lang.ref.Cleaner;
+
+public class MyCleanerResourceClass implements AutoCloseable {
+ private static Resource resource;
+
+ private static final Cleaner cleaner = Cleaner.create();
+ private final Cleaner.Cleanable cleanable;
+
+ public MyCleanerResourceClass() {
+ resource = new Resource();
+ this.cleanable = cleaner.register(this, new CleaningState());
+ }
+
+ public void useResource() {
+ // using the resource here
+ resource.use();
+ }
+
+ @Override
+ public void close() {
+ // perform actions to close all underlying resources
+ this.cleanable.clean();
+ }
+
+ static class CleaningState implements Runnable {
+ CleaningState() {
+ // constructor
+ }
+
+ @Override
+ public void run() {
+ // some cleanup action
+ System.out.println("Cleanup done");
+ }
+ }
+
+ static class Resource {
+ void use() {
+ System.out.println("Using the resource");
+ }
+
+ void close() {
+ System.out.println("Cleanup done");
+ }
+ }
+}
diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyCloseableResourceClass.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyCloseableResourceClass.java
new file mode 100644
index 0000000000..b11cb4e49e
--- /dev/null
+++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyCloseableResourceClass.java
@@ -0,0 +1,25 @@
+package com.baeldung.finalization_closeable_cleaner;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+public class MyCloseableResourceClass implements AutoCloseable {
+
+ private final FileInputStream fis;
+
+ public MyCloseableResourceClass() throws FileNotFoundException {
+ this.fis = new FileInputStream("src/main/resources/file.txt");
+
+ }
+
+ public int getByteLength() throws IOException {
+ System.out.println("Some operation");
+ return this.fis.readAllBytes().length;
+ }
+ @Override
+ public void close() throws IOException {
+ System.out.println("Finalized object");
+ this.fis.close();
+ }
+}
diff --git a/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyFinalizableResourceClass.java b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyFinalizableResourceClass.java
new file mode 100644
index 0000000000..a2c6a123b4
--- /dev/null
+++ b/core-java-modules/core-java-18/src/main/java/com/baeldung/finalization_closeable_cleaner/MyFinalizableResourceClass.java
@@ -0,0 +1,24 @@
+package com.baeldung.finalization_closeable_cleaner;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+public class MyFinalizableResourceClass {
+ private FileInputStream fis;
+
+ public MyFinalizableResourceClass() throws FileNotFoundException {
+ this.fis = new FileInputStream("src/main/resources/file.txt");
+ }
+
+ public int getByteLength() throws IOException {
+ System.out.println("Some operation");
+ return this.fis.readAllBytes().length;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ System.out.println("Finalized object");
+ this.fis.close();
+ }
+}
diff --git a/core-java-modules/core-java-18/src/main/resources/file.txt b/core-java-modules/core-java-18/src/main/resources/file.txt
new file mode 100644
index 0000000000..af27ff4986
--- /dev/null
+++ b/core-java-modules/core-java-18/src/main/resources/file.txt
@@ -0,0 +1 @@
+This is a test file.
\ No newline at end of file
diff --git a/core-java-modules/core-java-18/src/test/java/com/baeldung/finalization_closeable_cleaner/FinalizationCloseableCleanerUnitTest.java b/core-java-modules/core-java-18/src/test/java/com/baeldung/finalization_closeable_cleaner/FinalizationCloseableCleanerUnitTest.java
new file mode 100644
index 0000000000..22ff228227
--- /dev/null
+++ b/core-java-modules/core-java-18/src/test/java/com/baeldung/finalization_closeable_cleaner/FinalizationCloseableCleanerUnitTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.finalization_closeable_cleaner;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FinalizationCloseableCleanerUnitTest {
+
+ @Test
+ public void givenMyFinalizationResource_whenUsingFinalize_thenShouldClean() {
+ assertDoesNotThrow(() -> {
+ MyFinalizableResourceClass mfr = new MyFinalizableResourceClass();
+ mfr.getByteLength();
+ });
+ }
+ @Test
+ public void givenMyCleanerResource_whenUsingCleanerAPI_thenShouldClean() {
+ assertDoesNotThrow(() -> {
+ try (MyCleanerResourceClass myCleanerResourceClass = new MyCleanerResourceClass()) {
+ myCleanerResourceClass.useResource();
+ }
+ });
+ }
+
+ @Test
+ public void givenCloseableResource_whenUsingTryWith_thenShouldClose() throws IOException {
+ int length = 0;
+ try (MyCloseableResourceClass mcr = new MyCloseableResourceClass()) {
+ length = mcr.getByteLength();
+ }
+ Assert.assertEquals(20, length);
+ }
+}
diff --git a/core-java-modules/core-java-arrays-convert/README.md b/core-java-modules/core-java-arrays-convert/README.md
index dcaaaac12e..2e34829525 100644
--- a/core-java-modules/core-java-arrays-convert/README.md
+++ b/core-java-modules/core-java-arrays-convert/README.md
@@ -10,3 +10,4 @@ This module contains articles about arrays conversion in Java
- [Convert Java Array to Iterable](https://www.baeldung.com/java-array-convert-to-iterable)
- [Converting an int[] to HashSet in Java](https://www.baeldung.com/java-converting-int-array-to-hashset)
- [Convert an ArrayList of String to a String Array in Java](https://www.baeldung.com/java-convert-string-arraylist-array)
+- [Convert Char Array to Int Array in Java](https://www.baeldung.com/java-convert-char-int-array)
diff --git a/core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/CharArrayToIntArrayUtils.java b/core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/CharArrayToIntArrayUtils.java
new file mode 100644
index 0000000000..fbd76a0113
--- /dev/null
+++ b/core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/CharArrayToIntArrayUtils.java
@@ -0,0 +1,67 @@
+package com.baeldung.array.conversions;
+
+import java.util.Arrays;
+
+public class CharArrayToIntArrayUtils {
+
+ static int[] usingGetNumericValueMethod(char[] chars) {
+ if (chars == null) {
+ return null;
+ }
+
+ int[] ints = new int[chars.length];
+ for (int i = 0; i < chars.length; i++) {
+ ints[i] = Character.getNumericValue(chars[i]);
+ }
+
+ return ints;
+ }
+
+ static int[] usingDigitMethod(char[] chars) {
+ if (chars == null) {
+ return null;
+ }
+
+ int[] ints = new int[chars.length];
+ for (int i = 0; i < chars.length; i++) {
+ ints[i] = Character.digit(chars[i], 10);
+ }
+
+ return ints;
+ }
+
+ static int[] usingStreamApiMethod(char[] chars) {
+ if (chars == null) {
+ return null;
+ }
+
+ return new String(chars).chars()
+ .map(c -> c - 48)
+ .toArray();
+ }
+
+ static int[] usingParseIntMethod(char[] chars) {
+ if (chars == null) {
+ return null;
+ }
+
+ int[] ints = new int[chars.length];
+ for (int i = 0; i < chars.length; i++) {
+ ints[i] = Integer.parseInt(String.valueOf(chars[i]));
+ }
+
+ return ints;
+ }
+
+ static int[] usingArraysSetAllMethod(char[] chars) {
+ if (chars == null) {
+ return null;
+ }
+
+ int[] ints = new int[chars.length];
+ Arrays.setAll(ints, i -> Character.getNumericValue(chars[i]));
+
+ return ints;
+ }
+
+}
diff --git a/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/CharArrayToIntArrayUtilsUnitTest.java b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/CharArrayToIntArrayUtilsUnitTest.java
new file mode 100644
index 0000000000..534dc3893f
--- /dev/null
+++ b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/CharArrayToIntArrayUtilsUnitTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.array.conversions;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.api.Test;
+
+class CharArrayToIntArrayUtilsUnitTest {
+
+ @Test
+ void givenCharArray_whenUsingGetNumericValueMethod_shouldGetIntArray() {
+ int[] expected = { 2, 3, 4, 5 };
+ char[] chars = { '2', '3', '4', '5' };
+ int[] result = CharArrayToIntArrayUtils.usingGetNumericValueMethod(chars);
+
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void givenCharArray_whenUsingDigitMethod_shouldGetIntArray() {
+ int[] expected = { 1, 2, 3, 6 };
+ char[] chars = { '1', '2', '3', '6' };
+ int[] result = CharArrayToIntArrayUtils.usingDigitMethod(chars);
+
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void givenCharArray_whenUsingStreamApi_shouldGetIntArray() {
+ int[] expected = { 9, 8, 7, 6 };
+ char[] chars = { '9', '8', '7', '6' };
+ int[] result = CharArrayToIntArrayUtils.usingStreamApiMethod(chars);
+
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void givenCharArray_whenUsingParseIntMethod_shouldGetIntArray() {
+ int[] expected = { 9, 8, 7, 6 };
+ char[] chars = { '9', '8', '7', '6' };
+ int[] result = CharArrayToIntArrayUtils.usingParseIntMethod(chars);
+
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void givenCharArray_whenUsingArraysSetAllMethod_shouldGetIntArray() {
+ int[] expected = { 4, 9, 2, 3 };
+ char[] chars = { '4', '9', '2', '3' };
+ int[] result = CharArrayToIntArrayUtils.usingArraysSetAllMethod(chars);
+
+ assertArrayEquals(expected, result);
+ }
+
+}
diff --git a/core-java-modules/core-java-httpclient/src/main/java/com/baeldung/httpclient/HttpClientPost.java b/core-java-modules/core-java-httpclient/src/main/java/com/baeldung/httpclient/HttpClientPost.java
index d08a7bf183..5c62bf73d9 100644
--- a/core-java-modules/core-java-httpclient/src/main/java/com/baeldung/httpclient/HttpClientPost.java
+++ b/core-java-modules/core-java-httpclient/src/main/java/com/baeldung/httpclient/HttpClientPost.java
@@ -123,6 +123,7 @@ public class HttpClientPost {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
+ .header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(getFormDataAsString(formData)))
.build();
diff --git a/core-java-modules/core-java-io-5/src/test/java/com/baeldung/rmlinebreaks/RemoveLinebreaksUnitTest.java b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/rmlinebreaks/RemoveLinebreaksUnitTest.java
new file mode 100644
index 0000000000..7cfc7ede79
--- /dev/null
+++ b/core-java-modules/core-java-io-5/src/test/java/com/baeldung/rmlinebreaks/RemoveLinebreaksUnitTest.java
@@ -0,0 +1,72 @@
+package com.baeldung.rmlinebreaks;
+
+import org.junit.jupiter.api.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+public class RemoveLinebreaksUnitTest {
+
+ private Path file1Path() throws Exception {
+ return Paths.get(this.getClass().getClassLoader().getResource("multiple-line-1.txt").toURI());
+ }
+
+ private Path file2Path() throws Exception {
+ return Paths.get(this.getClass().getClassLoader().getResource("multiple-line-2.txt").toURI());
+ }
+
+ @Test
+ void whenRemovingLineSeparatorFromFile1_thenGetTheExpectedResult() throws Exception {
+ String content = Files.readString(file1Path(), StandardCharsets.UTF_8);
+
+ String result = content.replace(System.getProperty("line.separator"), "");
+ assertEquals("A, B, C, D, E, F", result);
+ }
+
+ @Test
+ void whenRemovingLineSeparatorFromFile2_thenNotGetTheExpectedResult() throws Exception {
+ String content = Files.readString(file2Path(), StandardCharsets.UTF_8);
+
+ String result = content.replace(System.getProperty("line.separator"), "");
+ assertNotEquals("A, B, C, D, E, F", result); // <-- NOT equals assertion!
+ }
+
+ @Test
+ void whenRemovingAllLinebreaks_thenGetTheExpectedResult() throws Exception {
+ String content1 = Files.readString(file1Path(), StandardCharsets.UTF_8);
+
+ // file contains CRLF
+ String content2 = Files.readString(file2Path(), StandardCharsets.UTF_8);
+
+ String result1 = content1.replace("\r", "").replace("\n", "");
+ String result2 = content2.replace("\r", "").replace("\n", "");
+
+ assertEquals("A, B, C, D, E, F", result1);
+ assertEquals("A, B, C, D, E, F", result2);
+
+ String resultReplaceAll = content2.replaceAll("[\\n\\r]", "");
+ assertEquals("A, B, C, D, E, F", resultReplaceAll);
+
+ }
+
+ @Test
+ void whenUsingReadAllLinesAndJoin_thenGetExpectedResult() throws Exception {
+ List lines1 = Files.readAllLines(file1Path(), StandardCharsets.UTF_8);
+
+ // file contains CRLF
+ List lines2 = Files.readAllLines(file2Path(), StandardCharsets.UTF_8);
+
+ String result1 = String.join("", lines1);
+ String result2 = String.join("", lines2);
+
+ assertEquals("A, B, C, D, E, F", result1);
+ assertEquals("A, B, C, D, E, F", result2);
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-5/src/test/resources/multiple-line-1.txt b/core-java-modules/core-java-io-5/src/test/resources/multiple-line-1.txt
new file mode 100644
index 0000000000..42e87e734e
--- /dev/null
+++ b/core-java-modules/core-java-io-5/src/test/resources/multiple-line-1.txt
@@ -0,0 +1,6 @@
+A,
+ B,
+ C,
+ D,
+ E,
+ F
diff --git a/core-java-modules/core-java-io-5/src/test/resources/multiple-line-2.txt b/core-java-modules/core-java-io-5/src/test/resources/multiple-line-2.txt
new file mode 100644
index 0000000000..4fe5d5f4ed
--- /dev/null
+++ b/core-java-modules/core-java-io-5/src/test/resources/multiple-line-2.txt
@@ -0,0 +1,4 @@
+A,
B,
+ C,
+ D,
E,
+ F
diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/Book.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/Book.java
new file mode 100644
index 0000000000..73762758e5
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/Book.java
@@ -0,0 +1,7 @@
+package com.baeldung.encapsulation;
+
+public class Book {
+ public String author;
+ public int isbn;
+
+}
diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookDetails.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookDetails.java
new file mode 100644
index 0000000000..9df45b1f14
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookDetails.java
@@ -0,0 +1,8 @@
+package com.baeldung.encapsulation;
+
+public class BookDetails {
+
+ public String bookDetails(Book book) {
+ return "author name: " + book.author + " ISBN: " + book.isbn;
+ }
+}
diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookEncapsulation.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookEncapsulation.java
new file mode 100644
index 0000000000..c39ca4bab4
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookEncapsulation.java
@@ -0,0 +1,17 @@
+package com.baeldung.encapsulation;
+
+public class BookEncapsulation {
+ public String author;
+ public int isbn;
+ public int id = 1;
+
+ public BookEncapsulation(String author, int isbn) {
+ this.author = author;
+ this.isbn = isbn;
+ }
+
+ public String getBookDetails() {
+ return "author id: " + id + " author name: " + author + " ISBN: " + isbn;
+ }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookInformationHiding.java b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookInformationHiding.java
new file mode 100644
index 0000000000..2d670a358d
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-others/src/main/java/com/baeldung/encapsulation/BookInformationHiding.java
@@ -0,0 +1,36 @@
+package com.baeldung.encapsulation;
+
+public class BookInformationHiding {
+ private String author;
+ private int isbn;
+ private int id = 1;
+
+ public BookInformationHiding(String author, int isbn) {
+ setAuthor(author);
+ setIsbn(isbn);
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public int getIsbn() {
+ return isbn;
+ }
+
+ public void setIsbn(int isbn) {
+ if (isbn < 0) {
+ throw new IllegalArgumentException("ISBN can't be negative");
+ }
+ this.isbn = isbn;
+ }
+
+ public String getBookDetails() {
+ return "author id: " + id + " author name: " + author + " ISBN: " + isbn;
+ }
+
+}
diff --git a/core-java-modules/core-java-lang-oop-others/src/test/java/com/baeldung/encapsulation/EncapsulationAndInformationHidingUnitTest.java b/core-java-modules/core-java-lang-oop-others/src/test/java/com/baeldung/encapsulation/EncapsulationAndInformationHidingUnitTest.java
new file mode 100644
index 0000000000..6106d1a406
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-others/src/test/java/com/baeldung/encapsulation/EncapsulationAndInformationHidingUnitTest.java
@@ -0,0 +1,35 @@
+package com.baeldung.encapsulation;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class EncapsulationAndInformationHidingUnitTest {
+
+ @Test
+ public void givenUnencapsulatedClass_whenImplementationClassIsSeparate_thenReturnResult() {
+ Book myBook = new Book();
+ myBook.author = "J.K Rowlings";
+ myBook.isbn = 67890;
+ BookDetails details = new BookDetails();
+ String result = details.bookDetails(myBook);
+ assertEquals("author name: " + myBook.author + " ISBN: " + myBook.isbn, result);
+
+ }
+
+ @Test
+ public void givenEncapsulatedClass_whenDataIsNotHidden_thenReturnResult() {
+ BookEncapsulation myBook = new BookEncapsulation("J.K Rowlings", 67890);
+ String result = myBook.getBookDetails();
+ assertEquals("author id: " + 1 + " author name: " + myBook.author + " ISBN: " + myBook.isbn, result);
+ }
+
+ @Test
+ public void givenEncapsulatedClass_whenDataIsHidden_thenReturnResult() {
+ BookInformationHiding myBook = new BookInformationHiding("J.K Rowlings", 67890);
+ String result = myBook.getBookDetails();
+ assertEquals("author id: " + 1 + " author name: " + myBook.getAuthor() + " ISBN: " + myBook.getIsbn(), result);
+ }
+
+}
diff --git a/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java
index 87d9d7a620..ca04263689 100644
--- a/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java
+++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java
@@ -2,10 +2,15 @@ package com.baeldung.networking.url;
import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import java.io.IOException;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Map;
import org.apache.http.client.utils.URIBuilder;
@@ -149,4 +154,24 @@ public class UrlUnitTest {
assertEquals("http://baeldung.com:9090/articles?topic=java&version=8", url.toString());
}
+ @Test
+ public void givenURI_whenConvertingToURL_thenCorrect() throws IOException, URISyntaxException {
+ String aURIString = "http://courses.baeldung.com";
+ URI uri = new URI(aURIString);
+ URL url = uri.toURL();
+ assertNotNull(url);
+ assertEquals(aURIString, url.toString());
+ }
+
+ @Test
+ public void givenPath_whenConvertingToURIAndThenURL_thenCorrect() throws IOException, URISyntaxException {
+ String finalPath = "file:/D:/baeldung/java-url";
+ Path path = Paths.get("/baeldung/java-url");
+ URI uri = path.toUri();
+ URL url = uri.toURL();
+ assertNotNull(url);
+ // Adapt the finalPath value to match your own path
+ // assertEquals(finalPath, url.toString());
+ }
+
}
\ No newline at end of file
diff --git a/core-java-modules/core-java-numbers-3/src/test/java/com/baeldung/integerToBinary/IntegerToBinaryUnitTest.java b/core-java-modules/core-java-numbers-3/src/test/java/com/baeldung/integerToBinary/IntegerToBinaryUnitTest.java
index 38ae79f2f5..9439f012e3 100644
--- a/core-java-modules/core-java-numbers-3/src/test/java/com/baeldung/integerToBinary/IntegerToBinaryUnitTest.java
+++ b/core-java-modules/core-java-numbers-3/src/test/java/com/baeldung/integerToBinary/IntegerToBinaryUnitTest.java
@@ -1,6 +1,8 @@
package com.baeldung.integerToBinary;
+import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
+
import static org.junit.Assert.assertEquals;
public class IntegerToBinaryUnitTest {
@@ -24,4 +26,18 @@ public class IntegerToBinaryUnitTest {
String binaryString = Integer.toString(n, 2);
assertEquals("111", binaryString);
}
-}
+
+ @Test
+ public void givenAnInteger_whenFormatAndReplaceCalled_thenZeroPaddedBinaryString() {
+ int n = 7;
+ String binaryString = String.format("%8s", Integer.toBinaryString(n)).replace(" ", "0");
+ assertEquals("00000111", binaryString);
+ }
+
+ @Test
+ public void givenAnInteger_whenUsingApacheStringUtils_thenZeroPaddedBinaryString() {
+ int n = 7;
+ String binaryString = StringUtils.leftPad(Integer.toBinaryString(n), 8, "0");
+ assertEquals("00000111", binaryString);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-numbers-6/README.md b/core-java-modules/core-java-numbers-6/README.md
index 3bd9fe6ddb..e3d5454d60 100644
--- a/core-java-modules/core-java-numbers-6/README.md
+++ b/core-java-modules/core-java-numbers-6/README.md
@@ -5,4 +5,5 @@
- [Does Java Read Integers in Little Endian or Big Endian?](https://www.baeldung.com/java-integers-little-big-endian)
- [How to Split an Integer Number Into Digits in Java](https://www.baeldung.com/java-integer-individual-digits)
- [Java Double vs. BigDecimal](https://www.baeldung.com/java-double-vs-bigdecimal)
+- [Finding the Square Root of a BigInteger in Java](https://www.baeldung.com/java-find-square-root-biginteger)
- More articles: [[<-- prev]](../core-java-numbers-5)
diff --git a/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/BigDecimalConversionUnitTest.java b/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/BigDecimalConversionUnitTest.java
new file mode 100644
index 0000000000..76c218d85f
--- /dev/null
+++ b/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/BigDecimalConversionUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.javadoublevsbigdecimal;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+import org.junit.jupiter.api.Test;
+
+public class BigDecimalConversionUnitTest {
+
+ @Test
+ void whenConvertingDoubleToBigDecimal_thenConversionIsCorrect() {
+ double doubleValue = 123.456;
+ BigDecimal bigDecimalValue = BigDecimal.valueOf(doubleValue);
+ BigDecimal expected = new BigDecimal("123.456").setScale(3, RoundingMode.HALF_UP);
+ assertEquals(expected, bigDecimalValue.setScale(3, RoundingMode.HALF_UP));
+ }
+
+ @Test
+ void givenDecimalPlacesGreaterThan15_whenConvertingBigDecimalToDouble_thenPrecisionIsLost() {
+ BigDecimal bigDecimalValue = new BigDecimal("789.1234567890123456");
+ double doubleValue = bigDecimalValue.doubleValue();
+ BigDecimal convertedBackToBigDecimal = BigDecimal.valueOf(doubleValue);
+ assertNotEquals(bigDecimalValue, convertedBackToBigDecimal);
+ }
+}
diff --git a/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/BigDecimalUnitTest.java b/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/BigDecimalUnitTest.java
new file mode 100644
index 0000000000..3ee611f315
--- /dev/null
+++ b/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/BigDecimalUnitTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.javadoublevsbigdecimal;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+import org.junit.jupiter.api.Test;
+
+public class BigDecimalUnitTest {
+
+ private BigDecimal bigDecimal1 = new BigDecimal("124567890.0987654321");
+ private BigDecimal bigDecimal2 = new BigDecimal("987654321.123456789");
+
+ @Test
+ public void givenTwoBigDecimals_whenAdd_thenCorrect() {
+ BigDecimal expected = new BigDecimal("1112222211.2222222211");
+ BigDecimal actual = bigDecimal1.add(bigDecimal2);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void givenTwoBigDecimals_whenMultiply_thenCorrect() {
+ BigDecimal expected = new BigDecimal("123030014929277547.5030955772112635269");
+ BigDecimal actual = bigDecimal1.multiply(bigDecimal2);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void givenTwoBigDecimals_whenSubtract_thenCorrect() {
+ BigDecimal expected = new BigDecimal("-863086431.0246913569");
+ BigDecimal actual = bigDecimal1.subtract(bigDecimal2);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void givenTwoBigDecimals_whenDivide_thenCorrect() {
+ BigDecimal expected = new BigDecimal("0.13");
+ BigDecimal actual = bigDecimal1.divide(bigDecimal2, 2, RoundingMode.HALF_UP);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/JavaDoubleUnitTest.java b/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/JavaDoubleUnitTest.java
new file mode 100644
index 0000000000..8697e1bfce
--- /dev/null
+++ b/core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/javadoublevsbigdecimal/JavaDoubleUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.javadoublevsbigdecimal;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+public class JavaDoubleUnitTest {
+
+ @Test
+ public void givenDoubleLiteral_whenAssigningToDoubleVariable_thenValueIsNotExactlyEqual() {
+ double doubleValue = 0.1;
+ double epsilon = 0.0000000000000001;
+ assertEquals(0.1, doubleValue, epsilon);
+ }
+}
diff --git a/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floatdoubleconversions/FloatDoubleConversionsTest.java b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floatdoubleconversions/FloatDoubleConversionsTest.java
index 10e9fd4c36..9c6b01e9de 100644
--- a/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floatdoubleconversions/FloatDoubleConversionsTest.java
+++ b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floatdoubleconversions/FloatDoubleConversionsTest.java
@@ -9,25 +9,21 @@ public class FloatDoubleConversionsTest {
public void whenDoubleType_thenFloatTypeSuccess(){
double interestRatesYearly = 13.333333333333334;
float interest = (float) interestRatesYearly;
- System.out.println(interest); //13.333333
- Assert.assertTrue(Float.class.isInstance(interest));//true
+ Assert.assertEquals(13.333333f, interest, 0.000004f);
Double monthlyRates = 2.111111111111112;
float rates = monthlyRates.floatValue();
- System.out.println(rates); //2.1111112
- Assert.assertTrue(Float.class.isInstance(rates));//true
+ Assert.assertEquals(2.1111112f, rates, 0.00000013);
}
@Test
public void whenFloatType_thenDoubleTypeSuccess(){
float gradeAverage =2.05f;
double average = gradeAverage;
- System.out.println(average); //2.049999952316284
- Assert.assertTrue(Double.class.isInstance(average));//true
+ Assert.assertEquals(2.05, average, 0.06);
Float monthlyRates = 2.1111112f;
Double rates = monthlyRates.doubleValue();
- System.out.println(rates); //2.1111112
- Assert.assertTrue(Double.class.isInstance(rates));//true
+ Assert.assertEquals(2.11111112, rates, 0.0000002);//true
}
}
diff --git a/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floattobigdecimal/FloatToBigDecimalUnitTest.java b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floattobigdecimal/FloatToBigDecimalUnitTest.java
new file mode 100644
index 0000000000..f783d00976
--- /dev/null
+++ b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/floattobigdecimal/FloatToBigDecimalUnitTest.java
@@ -0,0 +1,49 @@
+package com.baeldung.floattobigdecimal;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.math.BigDecimal;
+
+import org.junit.jupiter.api.Test;
+
+class FloatToBigDecimalUnitTest {
+
+ @Test
+ public void whenFloatComparedWithDifferentValues_thenCouldMatch() {
+ assertNotEquals(1.1f, 1.09f);
+ assertEquals(1.1f, 1.09999999f);
+ }
+
+ @Test
+ public void whenCreatedFromFloat_thenMatchesInternallyStoredValue() {
+ float floatToConvert = 1.10000002384185791015625f;
+ BigDecimal bdFromFloat = new BigDecimal(floatToConvert);
+ assertEquals("1.10000002384185791015625", bdFromFloat.toString());
+ }
+
+ @Test
+ public void whenCreatedFromString_thenPreservesTheOriginal() {
+ BigDecimal bdFromString = new BigDecimal("1.1");
+ assertEquals("1.1", bdFromString.toString());
+ }
+
+ @Test
+ public void whenCreatedFromFloatConvertedToString_thenFloatInternalValueGetsTruncated() {
+ String floatValue = Float.toString(1.10000002384185791015625f);
+ BigDecimal bdFromString = new BigDecimal(floatValue);
+ assertEquals("1.1", floatValue);
+ assertEquals("1.1", bdFromString.toString());
+ }
+
+ @Test
+ public void whenCreatedByValueOf_thenFloatValueGetsTruncated() {
+ assertEquals("1.100000023841858", BigDecimal.valueOf(1.10000002384185791015625f).toString());
+ }
+
+ @Test
+ public void whenDoubleConvertsFloatToString_thenFloatValueGetsTruncated() {
+ assertEquals("1.100000023841858", Double.toString(1.10000002384185791015625f));
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-reflection-3/README.md b/core-java-modules/core-java-reflection-3/README.md
new file mode 100644
index 0000000000..d997aa22f1
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/README.md
@@ -0,0 +1,2 @@
+### Relevant Articles:
+- [Is Java Reflection Bad Practice?](https://www.baeldung.com/java-reflection-bad-practice)
diff --git a/core-java-modules/core-java-reflection-3/pom.xml b/core-java-modules/core-java-reflection-3/pom.xml
new file mode 100644
index 0000000000..fa5fe897e0
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+ core-java-reflection-3
+ core-java-reflection-3
+ jar
+
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
+
+ org.reflections
+ reflections
+ ${reflections.version}
+
+
+
+
+ core-java-reflection-3
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${source.version}
+ ${target.version}
+ -parameters
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.8
+
+
+
+ prepare-agent
+
+
+
+ report
+ prepare-package
+
+ report
+
+
+
+
+
+
+
+
+ 0.9.12
+ 1.8
+ 1.8
+ 5.3.4
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/encapsulation/MyClass.java b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/encapsulation/MyClass.java
new file mode 100644
index 0000000000..680079adea
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/encapsulation/MyClass.java
@@ -0,0 +1,11 @@
+package com.baeldung.reflection.disadvantages.encapsulation;
+
+public class MyClass {
+
+ private String veryPrivateField;
+
+ public MyClass() {
+
+ this.veryPrivateField = "Secret Information";
+ }
+}
diff --git a/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/BenchmarkRunner.java b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/BenchmarkRunner.java
new file mode 100644
index 0000000000..1de026f796
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/BenchmarkRunner.java
@@ -0,0 +1,7 @@
+package com.baeldung.reflection.disadvantages.performance;
+
+public class BenchmarkRunner {
+ public static void main(String[] args) throws Exception {
+ org.openjdk.jmh.Main.main(args);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/InitializationBenchmark.java b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/InitializationBenchmark.java
new file mode 100644
index 0000000000..e6c0c3daea
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/InitializationBenchmark.java
@@ -0,0 +1,29 @@
+package com.baeldung.reflection.disadvantages.performance;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.TimeUnit;
+
+public class InitializationBenchmark {
+
+ @Benchmark
+ @Fork(value = 1, warmups = 1)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void directInit() {
+
+ Person person = new Person("John", "Doe", 50);
+ }
+
+ @Benchmark
+ @Fork(value = 1, warmups = 1)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void reflectiveInit() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+
+ Constructor constructor = Person.class.getDeclaredConstructor(String.class, String.class, Integer.class);
+ Person person = constructor.newInstance("John", "Doe", 50);
+ }
+}
diff --git a/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/MethodInvocationBenchmark.java b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/MethodInvocationBenchmark.java
new file mode 100644
index 0000000000..1128cf8f33
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/MethodInvocationBenchmark.java
@@ -0,0 +1,48 @@
+package com.baeldung.reflection.disadvantages.performance;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+public class MethodInvocationBenchmark {
+
+ @Benchmark
+ @Fork(value = 1, warmups = 1)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void directCall() {
+
+ directCall(new Person("John", "Doe", 50));
+ }
+
+ @Benchmark
+ @Fork(value = 1, warmups = 1)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void reflectiveCall() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+
+ reflectiveCall(new Person("John", "Doe", 50));
+ }
+
+
+ private void directCall(Person person) {
+
+ person.getFirstName();
+ person.getLastName();
+ person.getAge();
+ }
+
+ private void reflectiveCall(Person person) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+
+ Method getFirstNameMethod = Person.class.getMethod("getFirstName");
+ getFirstNameMethod.invoke(person);
+
+ Method getLastNameMethod = Person.class.getMethod("getLastName");
+ getLastNameMethod.invoke(person);
+
+ Method getAgeMethod = Person.class.getMethod("getAge");
+ getAgeMethod.invoke(person);
+ }
+}
diff --git a/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/Person.java b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/Person.java
new file mode 100644
index 0000000000..014c82ba45
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/src/main/java/com/baeldung/reflection/disadvantages/performance/Person.java
@@ -0,0 +1,38 @@
+package com.baeldung.reflection.disadvantages.performance;
+
+public class Person {
+
+ private String firstName;
+ private String lastName;
+ private Integer age;
+
+ public Person(String firstName, String lastName, Integer age) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.age = age;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+}
diff --git a/core-java-modules/core-java-reflection-3/src/test/java/com/baeldung/reflection/disadvantages/encapsulation/ReflectionEncapsulationUnitTest.java b/core-java-modules/core-java-reflection-3/src/test/java/com/baeldung/reflection/disadvantages/encapsulation/ReflectionEncapsulationUnitTest.java
new file mode 100644
index 0000000000..efb0a7da31
--- /dev/null
+++ b/core-java-modules/core-java-reflection-3/src/test/java/com/baeldung/reflection/disadvantages/encapsulation/ReflectionEncapsulationUnitTest.java
@@ -0,0 +1,21 @@
+package com.baeldung.reflection.disadvantages.encapsulation;
+
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Field;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ReflectionEncapsulationUnitTest {
+
+ @Test
+ public void givenPrivateField_whenUsingReflection_thenIsAccessible() throws IllegalAccessException, NoSuchFieldException {
+ MyClass myClassInstance = new MyClass();
+
+ Field privateField = MyClass.class.getDeclaredField("veryPrivateField");
+ privateField.setAccessible(true);
+
+ String accessedField = privateField.get(myClassInstance).toString();
+ assertEquals(accessedField, "Secret Information");
+ }
+}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java
index 36dee603eb..6f2e3250fc 100644
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java
+++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java
@@ -7,7 +7,7 @@ import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class SecureConnection {
-
+
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Use: SecureConnection host port");
@@ -20,20 +20,20 @@ public class SecureConnection {
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(host, port);
InputStream in = sslsocket.getInputStream();
OutputStream out = sslsocket.getOutputStream();
-
+
out.write(1);
-
+
while (in.available() > 0) {
System.out.print(in.read());
}
-
+
System.out.println("Secured connection performed successfully");
-
+
} catch (Exception exception) {
exception.printStackTrace();
}
}
-
+
/**
* Get the host from arguments
* @param args the arguments
@@ -42,7 +42,7 @@ public class SecureConnection {
private static String getHost(String[] args) {
return args[0];
}
-
+
/**
* Get the port from arguments
* @param args the arguments
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java
index d6efc34c3e..cf9a76b39a 100644
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java
+++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java
@@ -15,10 +15,8 @@ public class SimpleClient {
SocketFactory factory = SSLSocketFactory.getDefault();
try (Socket connection = factory.createSocket(host, port)) {
- ((SSLSocket) connection).setEnabledCipherSuites(
- new String[] { "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"});
- ((SSLSocket) connection).setEnabledProtocols(
- new String[] { "TLSv1.2"});
+ ((SSLSocket) connection).setEnabledCipherSuites(new String[] { "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" });
+ ((SSLSocket) connection).setEnabledProtocols(new String[] { "TLSv1.2" });
SSLParameters sslParams = new SSLParameters();
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
((SSLSocket) connection).setSSLParameters(sslParams);
@@ -28,6 +26,7 @@ public class SimpleClient {
}
public static void main(String[] args) throws IOException {
+ System.setProperty("javax.net.debug", "ssl:handshake");
System.out.println(startClient("localhost", 8443));
}
}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java
index 27d15d04d7..83946ccc1f 100644
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java
+++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java
@@ -14,11 +14,10 @@ public class SimpleServer {
ServerSocketFactory factory = SSLServerSocketFactory.getDefault();
try (ServerSocket listener = factory.createServerSocket(port)) {
+ System.setProperty("javax.net.debug", "ssl:handshake");
((SSLServerSocket) listener).setNeedClientAuth(true);
- ((SSLServerSocket) listener).setEnabledCipherSuites(
- new String[] { "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"});
- ((SSLServerSocket) listener).setEnabledProtocols(
- new String[] { "TLSv1.2"});
+ ((SSLServerSocket) listener).setEnabledCipherSuites(new String[] { "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" });
+ ((SSLServerSocket) listener).setEnabledProtocols(new String[] { "TLSv1.2" });
while (true) {
try (Socket socket = listener.accept()) {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
@@ -29,6 +28,7 @@ public class SimpleServer {
}
public static void main(String[] args) throws IOException {
+ System.setProperty("javax.net.debug", "ssl:handshake");
startServer(8443);
}
}
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-2/README.md b/core-java-modules/core-java-streams-2/README.md
index 2ff95045c3..2de80ebc67 100644
--- a/core-java-modules/core-java-streams-2/README.md
+++ b/core-java-modules/core-java-streams-2/README.md
@@ -4,12 +4,9 @@ This module contains articles about the Stream API in Java.
### Relevant Articles:
- [The Java 8 Stream API Tutorial](https://www.baeldung.com/java-8-streams)
-- [Introduction to Java 8 Streams](https://www.baeldung.com/java-8-streams-introduction)
- [Java 8 Stream findFirst() vs. findAny()](https://www.baeldung.com/java-stream-findfirst-vs-findany)
-- [Guide to Stream.reduce()](https://www.baeldung.com/java-stream-reduce)
- [Java IntStream Conversions](https://www.baeldung.com/java-intstream-convert)
- [Java 8 Streams peek() API](https://www.baeldung.com/java-streams-peek-api)
-- [Working With Maps Using Streams](https://www.baeldung.com/java-maps-streams)
- [Collect a Java Stream to an Immutable Collection](https://www.baeldung.com/java-stream-immutable-collection)
- [How to Add a Single Element to a Stream](https://www.baeldung.com/java-stream-append-prepend)
- [Operating on and Removing an Item from Stream](https://www.baeldung.com/java-use-remove-item-stream)
diff --git a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Java8StreamApiUnitTest.java b/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Java8StreamApiUnitTest.java
index c4e1f2b3cb..53978f04b5 100644
--- a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Java8StreamApiUnitTest.java
+++ b/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Java8StreamApiUnitTest.java
@@ -1,6 +1,7 @@
package com.baeldung.streams;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,6 +38,7 @@ public class Java8StreamApiUnitTest {
assertEquals(list.size() - 1, size);
}
+ @Ignore
@Test
public void checkOrder_whenChangeQuantityOfMethodCalls_thenCorrect() {
diff --git a/core-java-modules/core-java-streams-3/README.md b/core-java-modules/core-java-streams-3/README.md
index 48ebf145d2..70d9e68a5e 100644
--- a/core-java-modules/core-java-streams-3/README.md
+++ b/core-java-modules/core-java-streams-3/README.md
@@ -2,8 +2,7 @@
This module contains articles about the Stream API in Java.
-### Relevant Articles:
-- [The Difference Between map() and flatMap()](https://www.baeldung.com/java-difference-map-and-flatmap)
+### Relevant Articles:
- [How to Use if/else Logic in Java 8 Streams](https://www.baeldung.com/java-8-streams-if-else-logic)
- [The Difference Between Collection.stream().forEach() and Collection.forEach()](https://www.baeldung.com/java-collection-stream-foreach)
- [Primitive Type Streams in Java 8](https://www.baeldung.com/java-8-primitive-streams)
@@ -12,5 +11,4 @@ This module contains articles about the Stream API in Java.
- [Should We Close a Java Stream?](https://www.baeldung.com/java-stream-close)
- [Returning Stream vs. Collection](https://www.baeldung.com/java-return-stream-collection)
- [Convert a Java Enumeration Into a Stream](https://www.baeldung.com/java-enumeration-to-stream)
-- [When to Use a Parallel Stream in Java](https://www.baeldung.com/java-when-to-use-parallel-stream)
- More articles: [[<-- prev>]](/../core-java-streams-2)
diff --git a/core-java-modules/core-java-streams-5/README.md b/core-java-modules/core-java-streams-5/README.md
index dec4a7a0cb..e7c58a0eb2 100644
--- a/core-java-modules/core-java-streams-5/README.md
+++ b/core-java-modules/core-java-streams-5/README.md
@@ -3,3 +3,4 @@
- [Working With Empty Stream in Java](https://www.baeldung.com/java-empty-stream)
- [Aggregate Runtime Exceptions in Java Streams](https://www.baeldung.com/java-streams-aggregate-exceptions)
- [Streams vs. Loops in Java](https://www.baeldung.com/java-streams-vs-loops)
+- [Partition a Stream in Java](https://www.baeldung.com/java-partition-stream)
diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java
new file mode 100644
index 0000000000..8f36550bdc
--- /dev/null
+++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java
@@ -0,0 +1,32 @@
+package com.baeldung.skippingelements;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collector;
+
+class SkippingCollector {
+ private static final BinaryOperator IGNORE_COMBINE = (a, b) -> a;
+ private final int skip;
+ private final List list = new ArrayList<>();
+ private int currentIndex = 0;
+ private SkippingCollector(int skip) {
+ this.skip = skip;
+ }
+
+ private void accept(String item) {
+ final int index = ++currentIndex % skip;
+ if (index == 0)
+ list.add(item);
+ }
+ private List getResult() {
+ return list;
+ }
+
+ public static Collector> collector(int skip) {
+ return Collector.of(() -> new SkippingCollector(skip),
+ SkippingCollector::accept,
+ IGNORE_COMBINE,
+ SkippingCollector::getResult);
+ }
+}
diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java
new file mode 100644
index 0000000000..eb382367cc
--- /dev/null
+++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java
@@ -0,0 +1,65 @@
+package com.baeldung.skippingelements;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class SkippingElements {
+
+ private SkippingElements() {
+ }
+
+ public static List skipNthElementInListWithFilter(List sourceList, int n) {
+return IntStream.range(0, sourceList.size())
+ .filter(s -> (s + 1) % n == 0)
+ .mapToObj(sourceList::get)
+ .collect(Collectors.toList());
+ }
+
+ public static List skipNthElementInListWithIterate(List sourceList, int n) {
+int limit = sourceList.size() / n;
+return IntStream.iterate(n - 1, i -> (i + n))
+ .limit(limit)
+ .mapToObj(sourceList::get)
+ .collect(Collectors.toList());
+ }
+
+ public static List skipNthElementInListWithSublist(List sourceList, int n) {
+int limit = sourceList.size() / n;
+return Stream.iterate(sourceList, s -> s.subList(n, s.size()))
+ .limit(limit)
+ .map(s -> s.get(n - 1))
+ .collect(Collectors.toList());
+ }
+
+ public static List skipNthElementInListWithFor(List sourceList, int n) {
+List result = new ArrayList<>();
+for (int i = n - 1; i < sourceList.size(); i += n) {
+ result.add(sourceList.get(i));
+}
+return result;
+ }
+
+ public static List skipNthElementInListWithIterator(Stream sourceStream, int n) {
+List result = new ArrayList<>();
+final Iterator iterator = sourceStream.iterator();
+int count = 0;
+while (iterator.hasNext()) {
+ if (count % n == n - 1) {
+ result.add(iterator.next());
+ } else {
+ iterator.next();
+ }
+ ++count;
+}
+return result;
+ }
+
+public static List skipNthElementInStreamWithCollector(Stream sourceStream, int n) {
+ return sourceStream.collect(SkippingCollector.collector(n));
+}
+
+}
diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java
new file mode 100644
index 0000000000..2fd6adb0cf
--- /dev/null
+++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java
@@ -0,0 +1,114 @@
+package com.baeldung.skippingelements;
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class SkippingElementsUnitTest {
+
+ private static Stream testSource() {
+ return Stream.of(
+ Arguments.of(
+ List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
+ "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
+ "Thirty One", "Thirty Two", "Thirty Three"),
+ List.of("Three", "Six", "Nine", "Twelve", "Fifteen", "Eighteen", "Twenty One", "Twenty Four", "Twenty Seven", "Thirty", "Thirty Three"),
+ 3),
+ Arguments.of(
+ List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
+ "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
+ "Thirty One", "Thirty Two", "Thirty Three"),
+ List.of("Five", "Ten", "Fifteen", "Twenty", "Twenty Five", "Thirty"),
+ 5),
+ Arguments.of(
+ List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
+ "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
+ "Thirty One", "Thirty Two", "Thirty Three"),
+ List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+ "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
+ "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
+ "Thirty One", "Thirty Two", "Thirty Three"),
+ 1),
+ Arguments.of(
+ List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ List.of("Wednesday", "Saturday"),
+ 3),
+ Arguments.of(
+ List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ List.of("Friday"),
+ 5),
+ Arguments.of(
+ List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ 1),
+ Arguments.of(
+ List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ "December"),
+ List.of("March", "June", "September", "December"),
+ 3),
+ Arguments.of(
+ List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ "December"),
+ List.of("May", "October"),
+ 5),
+ Arguments.of(
+ List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ "December"),
+ List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
+ "December"),
+ 1)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testSource")
+ void givenListSkipNthElementInListWithFilterTestShouldFilterNthElement(List input, List expected, int n) {
+ final List actual = SkippingElements.skipNthElementInListWithFilter(input, n);
+ assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testSource")
+ void givenListSkipNthElementInListWithIterateTestShouldFilterNthElement(List input, List expected, int n) {
+ final List actual = SkippingElements.skipNthElementInListWithIterate(input, n);
+ assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testSource")
+ void givenListSkipNthElementInListWithSublistTestShouldFilterNthElement(List input, List expected, int n) {
+ final List actual = SkippingElements.skipNthElementInListWithSublist(input, n);
+ assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testSource")
+ void givenListSkipNthElementInListWithForTestShouldFilterNthElement(List input, List expected, int n) {
+ final List actual = SkippingElements.skipNthElementInListWithFor(input, n);
+ assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testSource")
+ void givenListSkipNthElementInStreamWithIteratorTestShouldFilterNthElement(List input, List expected, int n) {
+ final Stream inputStream = input.stream();
+ final List actual = SkippingElements.skipNthElementInListWithIterator(inputStream, n);
+ assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testSource")
+ void givenListSkipNthElementInStreamWithCollectorShouldFilterNthElement(List input, List expected, int n) {
+ final Stream inputStream = input.stream();
+ final List actual = SkippingElements.skipNthElementInStreamWithCollector(inputStream, n);
+ assertEquals(expected, actual);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-simple/README.md b/core-java-modules/core-java-streams-simple/README.md
new file mode 100644
index 0000000000..94d74f4c49
--- /dev/null
+++ b/core-java-modules/core-java-streams-simple/README.md
@@ -0,0 +1,14 @@
+## Java Streams Ebook
+
+This module contains articles about Streams that are part of the Java Streams Ebook.
+
+### Relevant Articles
+
+- [Introduction to Java 8 Streams](https://www.baeldung.com/java-8-streams-introduction)
+- [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors)
+- [Java Stream Filter with Lambda Expression](https://www.baeldung.com/java-stream-filter-lambda)
+- [Working With Maps Using Streams](https://www.baeldung.com/java-maps-streams)
+- [The Difference Between map() and flatMap()](https://www.baeldung.com/java-difference-map-and-flatmap)
+- [When to Use a Parallel Stream in Java](https://www.baeldung.com/java-when-to-use-parallel-stream)
+- [Guide to Java 8 groupingBy Collector](https://www.baeldung.com/java-groupingby-collector)
+- [Guide to Stream.reduce()](https://www.baeldung.com/java-stream-reduce)
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-simple/pom.xml b/core-java-modules/core-java-streams-simple/pom.xml
new file mode 100644
index 0000000000..5910e9daf2
--- /dev/null
+++ b/core-java-modules/core-java-streams-simple/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+ core-java-streams-simple
+ core-java-streams-simple
+ jar
+
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+ com.pivovarit
+ throwing-function
+ ${throwing-function.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+ core-java-streams-simple
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+
+
+ 1.5.1
+ 17
+ 17
+ 17
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/filter/Customer.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/filter/Customer.java
new file mode 100644
index 0000000000..51756c0067
--- /dev/null
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/filter/Customer.java
@@ -0,0 +1,56 @@
+package com.baeldung.streams.filter;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import javax.net.ssl.HttpsURLConnection;
+
+public class Customer {
+ private String name;
+ private int points;
+ private String profilePhotoUrl;
+
+ public Customer(String name, int points) {
+ this(name, points, "");
+ }
+
+ public Customer(String name, int points, String profilePhotoUrl) {
+ this.name = name;
+ this.points = points;
+ this.profilePhotoUrl = profilePhotoUrl;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getPoints() {
+ return points;
+ }
+
+ public boolean hasOver(int points) {
+ return this.points > points;
+ }
+
+ public boolean hasOverHundredPoints() {
+ return this.points > 100;
+ }
+
+ public boolean hasValidProfilePhoto() throws IOException {
+ URL url = new URL(this.profilePhotoUrl);
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+ return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
+ }
+
+ public boolean hasValidProfilePhotoWithoutCheckedException() {
+ try {
+ URL url = new URL(this.profilePhotoUrl);
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+ return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPost.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/BlogPost.java
similarity index 95%
rename from core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPost.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/BlogPost.java
index 314fbeeeb5..f22a20e67f 100644
--- a/core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPost.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/BlogPost.java
@@ -1,4 +1,4 @@
-package com.baeldung.java_16_features.groupingby;
+package com.baeldung.streams.groupingby;
import java.util.IntSummaryStatistics;
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPostType.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/BlogPostType.java
similarity index 51%
rename from core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPostType.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/BlogPostType.java
index df38b7e1c4..9bc5d95422 100644
--- a/core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPostType.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/BlogPostType.java
@@ -1,4 +1,4 @@
-package com.baeldung.java_16_features.groupingby;
+package com.baeldung.streams.groupingby;
public enum BlogPostType {
NEWS, REVIEW, GUIDE
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/Tuple.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/Tuple.java
similarity index 94%
rename from core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/Tuple.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/Tuple.java
index ad41207aa4..e57a9190ec 100644
--- a/core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/Tuple.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/groupingby/Tuple.java
@@ -1,4 +1,4 @@
-package com.baeldung.java_16_features.groupingby;
+package com.baeldung.streams.groupingby;
import java.util.Objects;
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/BenchmarkRunner.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/BenchmarkRunner.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/BenchmarkRunner.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/BenchmarkRunner.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/DifferentSourceSplitting.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/DifferentSourceSplitting.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/DifferentSourceSplitting.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/DifferentSourceSplitting.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/FileSearchCost.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/FileSearchCost.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/FileSearchCost.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/FileSearchCost.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/MemoryLocalityCosts.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/MemoryLocalityCosts.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/MemoryLocalityCosts.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/MemoryLocalityCosts.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/MergingCosts.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/MergingCosts.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/MergingCosts.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/MergingCosts.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/ParallelStream.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/ParallelStream.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/ParallelStream.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/ParallelStream.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/SequentialStream.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/SequentialStream.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/SequentialStream.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/SequentialStream.java
diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/SplittingCosts.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/SplittingCosts.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/parallel/SplittingCosts.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/parallel/SplittingCosts.java
diff --git a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/application/Application.java
similarity index 90%
rename from core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/application/Application.java
index 62d080c32c..2ea91edddd 100644
--- a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/application/Application.java
@@ -1,8 +1,7 @@
-package com.baeldung.reduce.application;
+package com.baeldung.streams.reduce.application;
+
+import com.baeldung.streams.reduce.entities.User;
-import com.baeldung.reduce.entities.User;
-import com.baeldung.reduce.utilities.NumberUtils;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
diff --git a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/benchmarks/JMHStreamReduceBenchMark.java
similarity index 94%
rename from core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/benchmarks/JMHStreamReduceBenchMark.java
index ecb0347e96..3c11643bce 100644
--- a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/benchmarks/JMHStreamReduceBenchMark.java
@@ -1,6 +1,6 @@
-package com.baeldung.reduce.benchmarks;
+package com.baeldung.streams.reduce.benchmarks;
-import com.baeldung.reduce.entities.User;
+import com.baeldung.streams.reduce.entities.User;
import java.util.ArrayList;
import java.util.List;
import org.openjdk.jmh.annotations.Benchmark;
diff --git a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/Rating.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/Rating.java
similarity index 95%
rename from core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/Rating.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/Rating.java
index 566691d442..400322c9ce 100644
--- a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/Rating.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/Rating.java
@@ -1,4 +1,4 @@
-package com.baeldung.reduce.entities;
+package com.baeldung.streams.reduce.entities;
import java.util.ArrayList;
import java.util.List;
diff --git a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/Review.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/Review.java
similarity index 90%
rename from core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/Review.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/Review.java
index b889a5f154..6d623127cf 100644
--- a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/Review.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/Review.java
@@ -1,4 +1,4 @@
-package com.baeldung.reduce.entities;
+package com.baeldung.streams.reduce.entities;
public class Review {
diff --git a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/User.java
similarity index 89%
rename from core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/User.java
index 6e0a529de6..610bd93b22 100644
--- a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/entities/User.java
@@ -1,4 +1,4 @@
-package com.baeldung.reduce.entities;
+package com.baeldung.streams.reduce.entities;
public class User {
diff --git a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/utilities/NumberUtils.java
similarity index 97%
rename from core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java
rename to core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/utilities/NumberUtils.java
index 38d5b50120..ed77bfe635 100644
--- a/core-java-modules/core-java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java
+++ b/core-java-modules/core-java-streams-simple/src/main/java/com/baeldung/streams/reduce/utilities/NumberUtils.java
@@ -1,4 +1,4 @@
-package com.baeldung.reduce.utilities;
+package com.baeldung.streams.reduce.utilities;
import java.util.List;
import java.util.function.BiFunction;
diff --git a/core-java-modules/core-java-streams-simple/src/main/resources/logback.xml b/core-java-modules/core-java-streams-simple/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/core-java-modules/core-java-streams-simple/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Detail.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/Detail.java
similarity index 100%
rename from core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Detail.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/Detail.java
diff --git a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Java8StreamsUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/Java8StreamsUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/Java8StreamsUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/Java8StreamsUnitTest.java
diff --git a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/collectors/Java8CollectorsUnitTest.java
similarity index 99%
rename from core-java-modules/core-java-11-2/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/collectors/Java8CollectorsUnitTest.java
index 7990b1fdb7..085c1b5d7f 100644
--- a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
+++ b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/collectors/Java8CollectorsUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.collectors;
+package com.baeldung.streams.collectors;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
diff --git a/core-java-modules/core-java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/filter/StreamFilterUnitTest.java
similarity index 92%
rename from core-java-modules/core-java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/filter/StreamFilterUnitTest.java
index 3f3922e015..be7162217f 100644
--- a/core-java-modules/core-java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java
+++ b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/filter/StreamFilterUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.stream.filter;
+package com.baeldung.streams.filter;
import org.junit.jupiter.api.Test;
import com.pivovarit.function.ThrowingPredicate;
@@ -14,10 +14,10 @@ import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
-public class StreamFilterUnitTest {
+class StreamFilterUnitTest {
@Test
- public void givenListOfCustomers_whenFilterByPoints_thenGetTwo() {
+ void givenListOfCustomers_whenFilterByPoints_thenGetTwo() {
Customer john = new Customer("John P.", 15);
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
@@ -53,7 +53,7 @@ public class StreamFilterUnitTest {
}
@Test
- public void givenListOfCustomers_whenFilterByMethodReference_thenGetTwo() {
+ void givenListOfCustomers_whenFilterByMethodReference_thenGetTwo() {
Customer john = new Customer("John P.", 15);
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
@@ -70,7 +70,7 @@ public class StreamFilterUnitTest {
}
@Test
- public void givenListOfCustomersWithOptional_whenFilterBy100Points_thenGetTwo() {
+ void givenListOfCustomersWithOptional_whenFilterBy100Points_thenGetTwo() {
Optional john = Optional.of(new Customer("John P.", 15));
Optional sarah = Optional.of(new Customer("Sarah M.", 200));
Optional mary = Optional.of(new Customer("Mary T.", 300));
@@ -89,7 +89,7 @@ public class StreamFilterUnitTest {
}
@Test
- public void givenListOfCustomers_whenFilterWithCustomHandling_thenThrowException() {
+ void givenListOfCustomers_whenFilterWithCustomHandling_thenThrowException() {
Customer john = new Customer("John P.", 15, "https://images.unsplash.com/photo-1543320485-d0d5a49c2b2e");
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
@@ -103,7 +103,7 @@ public class StreamFilterUnitTest {
}
@Test
- public void givenListOfCustomers_whenFilterWithThrowingFunction_thenThrowException() {
+ void givenListOfCustomers_whenFilterWithThrowingFunction_thenThrowException() {
Customer john = new Customer("John P.", 15, "https://images.unsplash.com/photo-1543320485-d0d5a49c2b2e");
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
diff --git a/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/flatmap/map/Java8MapAndFlatMapUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/flatmap/map/Java8MapAndFlatMapUnitTest.java
similarity index 73%
rename from core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/flatmap/map/Java8MapAndFlatMapUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/flatmap/map/Java8MapAndFlatMapUnitTest.java
index 1b09ea25c6..6de0f73351 100644
--- a/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/flatmap/map/Java8MapAndFlatMapUnitTest.java
+++ b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/flatmap/map/Java8MapAndFlatMapUnitTest.java
@@ -1,6 +1,7 @@
package com.baeldung.streams.flatmap.map;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collection;
@@ -10,12 +11,12 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
-import static org.junit.Assert.assertEquals;
-public class Java8MapAndFlatMapUnitTest {
+
+class Java8MapAndFlatMapUnitTest {
@Test
- public void givenStream_whenCalledMap_thenProduceList() {
+ void givenStream_whenCalledMap_thenProduceList() {
List myList = Stream.of("a", "b")
.map(String::toUpperCase)
.collect(Collectors.toList());
@@ -23,7 +24,7 @@ public class Java8MapAndFlatMapUnitTest {
}
@Test
- public void givenStream_whenCalledFlatMap_thenProduceFlattenedList() throws Exception {
+ void givenStream_whenCalledFlatMap_thenProduceFlattenedList() {
List> list = Arrays.asList(Arrays.asList("a"), Arrays.asList("b"));
System.out.println(list);
@@ -33,13 +34,13 @@ public class Java8MapAndFlatMapUnitTest {
}
@Test
- public void givenOptional_whenCalledMap_thenProduceOptional() {
+ void givenOptional_whenCalledMap_thenProduceOptional() {
Optional s = Optional.of("test");
assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));
}
@Test
- public void givenOptional_whenCalledFlatMap_thenProduceFlattenedOptional() {
+ void givenOptional_whenCalledFlatMap_thenProduceFlattenedOptional() {
assertEquals(Optional.of(Optional.of("STRING")), Optional.of("string")
.map(s -> Optional.of("STRING")));
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/java_16_features/groupingby/JavaGroupingByCollectorUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/groupingby/JavaGroupingByCollectorUnitTest.java
similarity index 89%
rename from core-java-modules/core-java-16/src/test/java/com/baeldung/java_16_features/groupingby/JavaGroupingByCollectorUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/groupingby/JavaGroupingByCollectorUnitTest.java
index 603bebb7c5..be5d176c50 100644
--- a/core-java-modules/core-java-16/src/test/java/com/baeldung/java_16_features/groupingby/JavaGroupingByCollectorUnitTest.java
+++ b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/groupingby/JavaGroupingByCollectorUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java_16_features.groupingby;
+package com.baeldung.streams.groupingby;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.averagingInt;
@@ -33,13 +33,13 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;
-public class JavaGroupingByCollectorUnitTest {
+class JavaGroupingByCollectorUnitTest {
private static final List posts = Arrays.asList(new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5),
new BlogPost("Programming guide", "Author 1", BlogPostType.GUIDE, 20), new BlogPost("News item 2", "Author 2", BlogPostType.NEWS, 35), new BlogPost("Tech review 2", "Author 1", BlogPostType.REVIEW, 15));
@Test
- public void givenAListOfPosts_whenGroupedByType_thenGetAMapBetweenTypeAndPosts() {
+ void givenAListOfPosts_whenGroupedByType_thenGetAMapBetweenTypeAndPosts() {
Map> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType));
@@ -52,7 +52,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeAndTheirTitlesAreJoinedInAString_thenGetAMapBetweenTypeAndCsvTitles() {
+ void givenAListOfPosts_whenGroupedByTypeAndTheirTitlesAreJoinedInAString_thenGetAMapBetweenTypeAndCsvTitles() {
Map postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]"))));
@@ -62,7 +62,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeAndSumTheLikes_thenGetAMapBetweenTypeAndPostLikes() {
+ void givenAListOfPosts_whenGroupedByTypeAndSumTheLikes_thenGetAMapBetweenTypeAndPostLikes() {
Map likesPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes)));
@@ -75,7 +75,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeInAnEnumMap_thenGetAnEnumMapBetweenTypeAndPosts() {
+ void givenAListOfPosts_whenGroupedByTypeInAnEnumMap_thenGetAnEnumMapBetweenTypeAndPosts() {
EnumMap> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, () -> new EnumMap<>(BlogPostType.class), toList()));
@@ -88,7 +88,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeInSets_thenGetAMapBetweenTypesAndSetsOfPosts() {
+ void givenAListOfPosts_whenGroupedByTypeInSets_thenGetAMapBetweenTypesAndSetsOfPosts() {
Map> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, toSet()));
@@ -101,7 +101,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeConcurrently_thenGetAMapBetweenTypeAndPosts() {
+ void givenAListOfPosts_whenGroupedByTypeConcurrently_thenGetAMapBetweenTypeAndPosts() {
ConcurrentMap> postsPerType = posts.parallelStream()
.collect(groupingByConcurrent(BlogPost::getType));
@@ -114,7 +114,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeAndAveragingLikes_thenGetAMapBetweenTypeAndAverageNumberOfLikes() {
+ void givenAListOfPosts_whenGroupedByTypeAndAveragingLikes_thenGetAMapBetweenTypeAndAverageNumberOfLikes() {
Map averageLikesPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes)));
@@ -127,7 +127,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeAndCounted_thenGetAMapBetweenTypeAndNumberOfPosts() {
+ void givenAListOfPosts_whenGroupedByTypeAndCounted_thenGetAMapBetweenTypeAndNumberOfPosts() {
Map numberOfPostsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, counting()));
@@ -140,7 +140,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeAndMaxingLikes_thenGetAMapBetweenTypeAndMaximumNumberOfLikes() {
+ void givenAListOfPosts_whenGroupedByTypeAndMaxingLikes_thenGetAMapBetweenTypeAndMaximumNumberOfLikes() {
Map> maxLikesPerPostType = posts.stream()
.collect(groupingBy(BlogPost::getType, maxBy(comparingInt(BlogPost::getLikes))));
@@ -164,7 +164,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByAuthorAndThenByType_thenGetAMapBetweenAuthorAndMapsBetweenTypeAndBlogPosts() {
+ void givenAListOfPosts_whenGroupedByAuthorAndThenByType_thenGetAMapBetweenAuthorAndMapsBetweenTypeAndBlogPosts() {
Map>> map = posts.stream()
.collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType)));
@@ -189,7 +189,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() {
+ void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() {
Map likeStatisticsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes)));
@@ -203,7 +203,7 @@ public class JavaGroupingByCollectorUnitTest {
}
@Test
- public void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetweenPairAndList() {
+ void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetweenPairAndList() {
Map, List> postsPerTypeAndAuthor = posts.stream()
.collect(groupingBy(post -> new ImmutablePair<>(post.getType(), post.getAuthor())));
diff --git a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/StreamMapUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/map/StreamMapUnitTest.java
similarity index 98%
rename from core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/StreamMapUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/map/StreamMapUnitTest.java
index 509a3a3569..c493ed903d 100644
--- a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/streams/StreamMapUnitTest.java
+++ b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/map/StreamMapUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.streams;
+package com.baeldung.streams.map;
import org.junit.Before;
import org.junit.Test;
diff --git a/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/parallel/ForkJoinUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/parallel/ForkJoinUnitTest.java
similarity index 100%
rename from core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/parallel/ForkJoinUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/parallel/ForkJoinUnitTest.java
diff --git a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/reduce/StreamReduceUnitTest.java b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/reduce/StreamReduceUnitTest.java
similarity index 67%
rename from core-java-modules/core-java-streams-2/src/test/java/com/baeldung/reduce/StreamReduceUnitTest.java
rename to core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/reduce/StreamReduceUnitTest.java
index 21eedf953e..009dd2ee37 100644
--- a/core-java-modules/core-java-streams-2/src/test/java/com/baeldung/reduce/StreamReduceUnitTest.java
+++ b/core-java-modules/core-java-streams-simple/src/test/java/com/baeldung/streams/reduce/StreamReduceUnitTest.java
@@ -1,79 +1,80 @@
-package com.baeldung.reduce;
+package com.baeldung.streams.reduce;
-import com.baeldung.reduce.entities.User;
-import com.baeldung.reduce.utilities.NumberUtils;
-import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.baeldung.streams.reduce.entities.User;
+import com.baeldung.streams.reduce.utilities.NumberUtils;
+
+import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class StreamReduceUnitTest {
+class StreamReduceUnitTest {
@Test
- public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() {
+ void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result = numbers.stream().reduce(0, (subtotal, element) -> subtotal + element);
assertThat(result).isEqualTo(21);
}
@Test
- public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() {
+ void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result = numbers.stream().reduce(0, Integer::sum);
assertThat(result).isEqualTo(21);
}
@Test
- public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() {
+ void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() {
List letters = Arrays.asList("a", "b", "c", "d", "e");
String result = letters.stream().reduce("", (partialString, element) -> partialString + element);
assertThat(result).isEqualTo("abcde");
}
@Test
- public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() {
+ void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() {
List letters = Arrays.asList("a", "b", "c", "d", "e");
String result = letters.stream().reduce("", String::concat);
assertThat(result).isEqualTo("abcde");
}
@Test
- public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() {
+ void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() {
List letters = Arrays.asList("a", "b", "c", "d", "e");
String result = letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase());
assertThat(result).isEqualTo("ABCDE");
}
@Test
- public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() {
+ void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() {
List users = Arrays.asList(new User("John", 30), new User("Julie", 35));
int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
assertThat(result).isEqualTo(65);
}
@Test
- public void givenStringList_whenReduceWithParallelStream_thenCorrect() {
+ void givenStringList_whenReduceWithParallelStream_thenCorrect() {
List letters = Arrays.asList("a", "b", "c", "d", "e");
String result = letters.parallelStream().reduce("", String::concat);
assertThat(result).isEqualTo("abcde");
}
@Test
- public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() {
+ void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21);
}
@Test
- public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() {
+ void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21);
}
@Test
- public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() {
+ void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21);
}
diff --git a/core-java-modules/core-java-streams/README.md b/core-java-modules/core-java-streams/README.md
index 360f7190ea..adb4c1dda1 100644
--- a/core-java-modules/core-java-streams/README.md
+++ b/core-java-modules/core-java-streams/README.md
@@ -9,7 +9,6 @@ This module contains articles about the Stream API in Java.
- [Iterable to Stream in Java](https://www.baeldung.com/java-iterable-to-stream)
- [How to Iterate Over a Stream With Indices](https://www.baeldung.com/java-stream-indices)
- [Stream Ordering in Java](https://www.baeldung.com/java-stream-ordering)
-- [Java Stream Filter with Lambda Expression](https://www.baeldung.com/java-stream-filter-lambda)
- [Counting Matches on a Stream Filter](https://www.baeldung.com/java-stream-filter-count)
- [Summing Numbers with Java Streams](https://www.baeldung.com/java-stream-sum)
- [How to Find All Getters Returning Null](https://www.baeldung.com/java-getters-returning-null)
diff --git a/core-java-modules/core-java-streams/pom.xml b/core-java-modules/core-java-streams/pom.xml
index c7282dda21..005968d214 100644
--- a/core-java-modules/core-java-streams/pom.xml
+++ b/core-java-modules/core-java-streams/pom.xml
@@ -29,11 +29,6 @@
streamex
${streamex.version}
-
- com.pivovarit
- throwing-function
- ${throwing-function.version}
-
@@ -62,8 +57,6 @@
0.10.4
1.16
0.8.1
- 1.5.1
-
17
17
diff --git a/core-java-modules/core-java-string-apis/src/test/java/com/baeldung/charsequence/CharSequenceVsStringUnitTest.java b/core-java-modules/core-java-string-apis/src/test/java/com/baeldung/charsequence/CharSequenceVsStringUnitTest.java
index aa15345bcb..13a0407a98 100644
--- a/core-java-modules/core-java-string-apis/src/test/java/com/baeldung/charsequence/CharSequenceVsStringUnitTest.java
+++ b/core-java-modules/core-java-string-apis/src/test/java/com/baeldung/charsequence/CharSequenceVsStringUnitTest.java
@@ -1,11 +1,11 @@
package com.baeldung.charsequence;
-import org.junit.Test;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
public class CharSequenceVsStringUnitTest {
@Test
@@ -44,4 +44,43 @@ public class CharSequenceVsStringUnitTest {
assertEquals(firstAddressOfTest, secondAddressOfTest);
}
+
+ @Test
+ public void givenCharSequenceAsString_whenConvertingUsingCasting_thenCorrect() {
+ String expected = "baeldung";
+ CharSequence charSequence = "baeldung";
+ String explicitCastedString = (String) charSequence;
+
+ assertEquals(expected, charSequence);
+ assertEquals(expected, explicitCastedString);
+ }
+
+ @Test(expected = ClassCastException.class)
+ public void givenCharSequenceAsStringBuiler_whenConvertingUsingCasting_thenThrowException() {
+ CharSequence charSequence = new StringBuilder("baeldung");
+ String castedString = (String) charSequence;
+ }
+
+ @Test
+ public void givenCharSequence_whenConvertingUsingToString_thenCorrect() {
+ String expected = "baeldung";
+ CharSequence charSequence1 = "baeldung";
+ CharSequence charSequence2 = new StringBuilder("baeldung");
+
+ assertEquals(expected, charSequence1.toString());
+ assertEquals(expected, charSequence2.toString());
+ }
+
+ @Test
+ public void givenCharSequence_whenConvertingUsingValueOf_thenCorrect() {
+ String expected = "baeldung";
+ CharSequence charSequence1 = "baeldung";
+ CharSequence charSequence2 = new StringBuilder("baeldung");
+ CharSequence charSequence3 = null;
+
+ assertEquals(expected, String.valueOf(charSequence1));
+ assertEquals(expected, String.valueOf(charSequence2));
+ assertEquals("null", String.valueOf(charSequence3));
+ }
+
}
diff --git a/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/joinasnl/JoinStringsAsNaturalLangUnitTest.java b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/joinasnl/JoinStringsAsNaturalLangUnitTest.java
new file mode 100644
index 0000000000..f3ca5a3e2b
--- /dev/null
+++ b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/joinasnl/JoinStringsAsNaturalLangUnitTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.joinasnl;
+
+import static java.util.Collections.emptyList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+public class JoinStringsAsNaturalLangUnitTest {
+ String joinItemsAsNaturalLanguage(List list, boolean oxfordComma) {
+ if (list.size() < 3) {
+ return String.join(" and ", list);
+ }
+ // list has at least three elements
+ int lastIdx = list.size() - 1;
+ StringBuilder sb = new StringBuilder();
+ return sb.append(String.join(", ", list.subList(0, lastIdx)))
+ .append(oxfordComma ? ", and " : " and ")
+ .append(list.get(lastIdx))
+ .toString();
+ }
+
+ @Test
+ void whenCallingJoinByGrammar_thenGetTheExpectedResult() {
+ assertEquals("", joinItemsAsNaturalLanguage(emptyList(), false));
+ assertEquals("A", joinItemsAsNaturalLanguage(List.of("A"), false));
+ assertEquals("A and B", joinItemsAsNaturalLanguage(List.of("A", "B"), false));
+ assertEquals("A, B, C, D and I have a comma (,)", joinItemsAsNaturalLanguage(List.of("A", "B", "C", "D", "I have a comma (,)"), false));
+ // with oxford comma = true
+ assertEquals("", joinItemsAsNaturalLanguage(emptyList(), true));
+ assertEquals("A", joinItemsAsNaturalLanguage(List.of("A"), true));
+ assertEquals("A and B", joinItemsAsNaturalLanguage(List.of("A", "B"), true));
+ assertEquals("A, B, C, D, and I have a comma (,)", joinItemsAsNaturalLanguage(List.of("A", "B", "C", "D", "I have a comma (,)"), true));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/stringsplitkeyvalue/StringSplitKeyValueUnitTest.java b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/stringsplitkeyvalue/StringSplitKeyValueUnitTest.java
new file mode 100644
index 0000000000..25f68ff373
--- /dev/null
+++ b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/stringsplitkeyvalue/StringSplitKeyValueUnitTest.java
@@ -0,0 +1,80 @@
+package com.baeldung.stringsplitkeyvalue;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class StringSplitKeyValueUnitTest {
+
+@Test
+public void givenStringData_whenUsingTokenizer_thenTokenizeAndValidate() {
+ String data = "name=John age=30 city=NewYork";
+ StringTokenizer tokenizer = new StringTokenizer(data);
+
+ // Create a map to store key-value pairs
+ Map keyValueMap = new HashMap<>();
+
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ String[] keyValue = token.split("=");
+
+ if (keyValue.length == 2) {
+ String key = keyValue[0];
+ String value = keyValue[1];
+
+ // Store key-value pairs in the map
+ keyValueMap.put(key, value);
+ }
+ }
+
+ // Use assertions to validate the key-value pairs in the map
+ assertEquals("John", keyValueMap.get("name"));
+ assertEquals("30", keyValueMap.get("age"));
+ assertEquals("NewYork", keyValueMap.get("city"));
+}
+
+
+@Test
+public void givenDataWithPattern_whenUsingMatcher_thenPerformPatternMatching() {
+ String data = "name=John,age=30;city=NewYork";
+ Pattern pattern = Pattern.compile("\\b(\\w+)=(\\w+)\\b");
+ Matcher matcher = pattern.matcher(data);
+
+ // Create a map to store key-value pairs
+ Map keyValueMap = new HashMap<>();
+
+ while (matcher.find()) {
+ String key = matcher.group(1);
+ String value = matcher.group(2);
+
+ // Store key-value pairs in the map
+ keyValueMap.put(key, value);
+ }
+
+ // Use assertions to validate the key-value pairs in the map
+ assertEquals("John", keyValueMap.get("name"));
+ assertEquals("30", keyValueMap.get("age"));
+ assertEquals("NewYork", keyValueMap.get("city"));
+}
+
+ @Test
+ public void givenStringData_whenUsingJavaMap_thenSplitAndValidate() {
+ String data = "name=John age=30 city=NewYork";
+ Map keyValueMap = Arrays.stream(data.split(" "))
+ .map(kv -> kv.split("="))
+ .filter(kvArray -> kvArray.length == 2)
+ .collect(Collectors.toMap(kv -> kv[0], kv -> kv[1]));
+
+ assertEquals("John", keyValueMap.get("name"));
+ assertEquals("30", keyValueMap.get("age"));
+ assertEquals("NewYork", keyValueMap.get("city"));
+ }
+}
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index cd31bb5845..5b37db6e1a 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -83,6 +83,7 @@
core-java-collections-maps
core-java-collections-maps-2
core-java-collections-maps-3
+ core-java-collections-maps-7
core-java-compiler
core-java-concurrency-2
core-java-concurrency-advanced
@@ -157,6 +158,7 @@
core-java-properties
core-java-reflection
core-java-reflection-2
+ core-java-reflection-3
core-java-scanner
core-java-security-2
core-java-security-3
@@ -164,6 +166,7 @@
core-java-security-algorithms
core-java-serialization
core-java-streams
+ core-java-streams-simple
core-java-streams-3
core-java-string-algorithms
core-java-string-algorithms-2
diff --git a/javaxval/README.md b/javaxval/README.md
index be8c3b51b7..188c2e59d0 100644
--- a/javaxval/README.md
+++ b/javaxval/README.md
@@ -7,7 +7,7 @@ This module contains articles about Bean Validation.
- [Validating Container Elements with Jakarta Bean Validation 3.0](https://www.baeldung.com/bean-validation-container-elements)
- [Validations for Enum Types](https://www.baeldung.com/javax-validations-enums)
- [Javax BigDecimal Validation](https://www.baeldung.com/javax-bigdecimal-validation)
-- [Grouping Javax Validation Constraints](https://www.baeldung.com/javax-validation-groups)
+- [Grouping Jakarta (Javax) Validation Constraints](https://www.baeldung.com/javax-validation-groups)
- [Constraint Composition with Bean Validation](https://www.baeldung.com/java-bean-validation-constraint-composition)
- [Using @NotNull on a Method Parameter](https://www.baeldung.com/java-notnull-method-parameter)
- [Difference Between @NotNull, @NotEmpty, and @NotBlank Constraints in Bean Validation](https://www.baeldung.com/java-bean-validation-not-null-empty-blank)
diff --git a/jersey/pom.xml b/jersey/pom.xml
index c2b37f7118..d279406e9a 100644
--- a/jersey/pom.xml
+++ b/jersey/pom.xml
@@ -76,6 +76,11 @@
jersey-apache-connector
${jersey.version}
+
+ org.glassfish.jersey.media
+ jersey-media-multipart
+ ${jersey.version}
+
@@ -102,4 +107,4 @@
3.1.1
-
\ No newline at end of file
+
diff --git a/jersey/src/main/java/com/baeldung/jersey/server/form/FormExampleResource.java b/jersey/src/main/java/com/baeldung/jersey/server/form/FormExampleResource.java
new file mode 100644
index 0000000000..15e82679ef
--- /dev/null
+++ b/jersey/src/main/java/com/baeldung/jersey/server/form/FormExampleResource.java
@@ -0,0 +1,61 @@
+package com.baeldung.jersey.server.form;
+
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+@Path("form")
+public class FormExampleResource
+{
+ @GET
+ @Path("/example1")
+ @Produces({MediaType.TEXT_HTML})
+ public InputStream getExample1() throws Exception
+ {
+ File f = new File("src/main/resources/html/example1.html");
+ return new FileInputStream(f);
+ }
+
+ @GET
+ @Path("/example2")
+ @Produces({MediaType.TEXT_HTML})
+ public InputStream getExample2() throws Exception
+ {
+ File f = new File("src/main/resources/html/example2.html");
+ return new FileInputStream(f);
+ }
+
+ @POST
+ @Path("/example1")
+ public String example1(@FormParam("first_name") String firstName,
+ @FormParam("last_name") String lastName,
+ @FormParam("age") String age)
+ {
+ return "Got: First = " + firstName + ", Last = " + lastName + ", Age = " + age;
+ }
+
+ @POST
+ @Path("/example2")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public String example2(@FormDataParam("first_name") String firstName,
+ @FormDataParam("last_name") String lastName,
+ @FormDataParam("age") String age,
+ @FormDataParam("photo") InputStream photo)
+ throws Exception
+ {
+ int len;
+ int size = 1024;
+ byte[] buf;
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ buf = new byte[size];
+ while ((len = photo.read(buf, 0, size)) != -1)
+ bos.write(buf, 0, len);
+ buf = bos.toByteArray();
+ return "Got: First = " + firstName + ", Last = " + lastName + ", Age = " + age + ", Photo (# of bytes) = " + buf.length;
+ }
+}
diff --git a/jersey/src/main/resources/formexamples/example1.html b/jersey/src/main/resources/formexamples/example1.html
new file mode 100644
index 0000000000..6335dcce08
--- /dev/null
+++ b/jersey/src/main/resources/formexamples/example1.html
@@ -0,0 +1,16 @@
+
+
+ Example 1 using @FormParam
+
+
+
+
+
diff --git a/jersey/src/main/resources/formexamples/example2.html b/jersey/src/main/resources/formexamples/example2.html
new file mode 100644
index 0000000000..4875c652a4
--- /dev/null
+++ b/jersey/src/main/resources/formexamples/example2.html
@@ -0,0 +1,18 @@
+
+
+ Example 2 using @FormDataParam
+
+
+
+
+
diff --git a/mapstruct/src/main/java/com/baeldung/expression/dto/LicenseDto.java b/mapstruct/src/main/java/com/baeldung/expression/dto/LicenseDto.java
index 025df1a4f6..1d7cacaead 100644
--- a/mapstruct/src/main/java/com/baeldung/expression/dto/LicenseDto.java
+++ b/mapstruct/src/main/java/com/baeldung/expression/dto/LicenseDto.java
@@ -11,6 +11,8 @@ public class LicenseDto {
private LocalDateTime endDate;
+ private String licenseType;
+
public UUID getId() {
return id;
}
@@ -35,4 +37,12 @@ public class LicenseDto {
this.endDate = endDate;
}
+ public String getLicenseType() {
+ return licenseType;
+ }
+
+ public void setLicenseType(String licenseType) {
+ this.licenseType = licenseType;
+ }
+
}
diff --git a/mapstruct/src/main/java/com/baeldung/expression/mapper/LicenseMapper.java b/mapstruct/src/main/java/com/baeldung/expression/mapper/LicenseMapper.java
index 100588b45d..0d8904e220 100644
--- a/mapstruct/src/main/java/com/baeldung/expression/mapper/LicenseMapper.java
+++ b/mapstruct/src/main/java/com/baeldung/expression/mapper/LicenseMapper.java
@@ -6,6 +6,7 @@ import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import org.mapstruct.AfterMapping;
+import org.mapstruct.Condition;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
@@ -40,4 +41,13 @@ public interface LicenseMapper {
.toDays() <= 14;
}
-}
+ @Condition
+ default boolean mapsToExpectedLicenseType(String licenseType) {
+ try {
+ return licenseType != null && License.LicenseType.valueOf(licenseType) != null;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/mapstruct/src/main/java/com/baeldung/expression/model/License.java b/mapstruct/src/main/java/com/baeldung/expression/model/License.java
index 71e4f086c0..e36e278a57 100644
--- a/mapstruct/src/main/java/com/baeldung/expression/model/License.java
+++ b/mapstruct/src/main/java/com/baeldung/expression/model/License.java
@@ -3,7 +3,6 @@ package com.baeldung.expression.model;
import java.time.OffsetDateTime;
import java.util.UUID;
-
public class License {
private UUID id;
@@ -16,6 +15,8 @@ public class License {
private boolean renewalRequired;
+ private LicenseType licenseType;
+
public UUID getId() {
return id;
}
@@ -55,4 +56,16 @@ public class License {
public void setRenewalRequired(boolean renewalRequired) {
this.renewalRequired = renewalRequired;
}
-}
+
+ public enum LicenseType {
+ INDIVIDUAL, FAMILY
+ }
+
+ public LicenseType getLicenseType() {
+ return licenseType;
+ }
+
+ public void setLicenseType(LicenseType licenseType) {
+ this.licenseType = licenseType;
+ }
+}
\ No newline at end of file
diff --git a/mapstruct/src/test/java/com/baeldung/expression/mapper/LicenseMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/expression/mapper/LicenseMapperUnitTest.java
index dcdda5c1ac..d7521e81f5 100644
--- a/mapstruct/src/test/java/com/baeldung/expression/mapper/LicenseMapperUnitTest.java
+++ b/mapstruct/src/test/java/com/baeldung/expression/mapper/LicenseMapperUnitTest.java
@@ -6,6 +6,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
@@ -74,4 +75,31 @@ class LicenseMapperUnitTest {
assertThat(license.getId()).isSameAs(id);
}
+ @Test
+ void givenLicenseDtoWithoutLicenseTypeString_whenMapperMethodIsInvoked_thenLicenseShouldBePopulatedWithoutLicenseType() {
+ LicenseDto licenseDto = new LicenseDto();
+ License license = licenseMapper.toLicense(licenseDto);
+ assertThat(license).isNotNull();
+ Assertions.assertNull(license.getLicenseType());
+ }
+
+ @Test
+ void givenLicenseDtoWithInvalidLicenseTypeString_whenMapperMethodIsInvoked_thenLicenseShouldBePopulatedWithoutLicenseType() {
+ LicenseDto licenseDto = new LicenseDto();
+ licenseDto.setLicenseType("invalid_license_type");
+ License license = licenseMapper.toLicense(licenseDto);
+ assertThat(license).isNotNull();
+ Assertions.assertNull(license.getLicenseType());
+ }
+
+ @Test
+ void givenLicenseDtoWithValidLicenseTypeString_whenMapperMethodIsInvoked_thenLicenseShouldBePopulatedWithMatchingLicenseType() {
+ LicenseDto licenseDto = new LicenseDto();
+ licenseDto.setLicenseType("INDIVIDUAL");
+ License license = licenseMapper.toLicense(licenseDto);
+ assertThat(license).isNotNull();
+ Assertions.assertNotNull(license.getLicenseType());
+ assertThat(license.getLicenseType()).isEqualTo(License.LicenseType.INDIVIDUAL);
+ }
+
}
\ No newline at end of file
diff --git a/microservices-modules/micronaut/README.md b/microservices-modules/micronaut/README.md
index 1ab31d0c0c..f784f8ad70 100644
--- a/microservices-modules/micronaut/README.md
+++ b/microservices-modules/micronaut/README.md
@@ -5,3 +5,4 @@ This module contains articles about Micronaut.
### Relevant Articles:
- [Introduction to Micronaut Framework](https://www.baeldung.com/micronaut)
- [Micronaut vs. Spring Boot](https://www.baeldung.com/micronaut-vs-spring-boot)
+- [API Versioning in Micronaut](https://www.baeldung.com/java-api-versioning-micronaut)
diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml
index 58b4dd8b9e..3c77386ddd 100644
--- a/persistence-modules/spring-boot-persistence/pom.xml
+++ b/persistence-modules/spring-boot-persistence/pom.xml
@@ -9,9 +9,9 @@
com.baeldung
- parent-boot-2
+ parent-boot-3
0.0.1-SNAPSHOT
- ../../parent-boot-2
+ ../../parent-boot-3
@@ -49,10 +49,7 @@
mysql
mysql-connector-java
-
-
- javax.validation
- validation-api
+ ${mysql-connector-java.version}
org.xerial
@@ -66,11 +63,17 @@
org.hsqldb
hsqldb
+
+ jakarta.validation
+ jakarta.validation-api
+
2.23.0
2.0.1.Final
+ 8.0.31
+ com.baeldung.boot.Application
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java
index d3a09c08ff..96cb9ae975 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java
@@ -13,7 +13,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
-import javax.persistence.EntityManagerFactory;
+import jakarta.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java
index 736c12fb07..ba75269c29 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java
@@ -1,8 +1,8 @@
package com.baeldung.boot.domain;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
/**
* @author paullatzelsperger
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java
index 59227f6412..fcea52221f 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java
@@ -1,11 +1,11 @@
package com.baeldung.boot.domain;
-import static javax.persistence.GenerationType.IDENTITY;
+import static jakarta.persistence.GenerationType.IDENTITY;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
@Entity
public class Country {
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Employee.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Employee.java
index 07e69a6f62..cef959fbfd 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Employee.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Employee.java
@@ -1,9 +1,9 @@
package com.baeldung.boot.domain;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
/**
* @author harshavs
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java
index a2a676200a..ba38aadeef 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java
@@ -1,9 +1,9 @@
package com.baeldung.boot.domain;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
@Entity
public class GenericEntity {
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java
index bdbe75cd0c..a5a6fb0160 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java
@@ -1,9 +1,9 @@
package com.baeldung.boot.domain;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
@Entity
@Table(name = "users")
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java
index 00e90a5ec9..cef2241cdd 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java
@@ -1,9 +1,9 @@
package com.baeldung.boot.naming.entity;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.OneToMany;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
import java.util.List;
@Entity
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java
index 7711156864..3bbe0069a8 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java
@@ -1,8 +1,8 @@
package com.baeldung.boot.naming.entity;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.ManyToOne;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToOne;
@Entity
public class Preference {
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/dataloading/model/Country.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/dataloading/model/Country.java
index 692d48caf0..db5b242e69 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/dataloading/model/Country.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/dataloading/model/Country.java
@@ -1,11 +1,11 @@
package com.baeldung.dataloading.model;
-import static javax.persistence.GenerationType.IDENTITY;
+import static jakarta.persistence.GenerationType.IDENTITY;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
@Entity
public class Country {
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/controllers/UserController.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/controllers/UserController.java
index c55f1083ba..afc548f700 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/controllers/UserController.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/controllers/UserController.java
@@ -2,7 +2,7 @@ package com.baeldung.springbootcrudapp.application.controllers;
import com.baeldung.springbootcrudapp.application.repositories.UserRepository;
import com.baeldung.springbootcrudapp.application.entities.User;
-import javax.validation.Valid;
+import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/entities/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/entities/User.java
index 145f251158..4120c505a6 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/entities/User.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootcrudapp/application/entities/User.java
@@ -1,10 +1,10 @@
package com.baeldung.springbootcrudapp.application.entities;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.validation.constraints.NotBlank;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.validation.constraints.NotBlank;
@Entity
public class User {
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java
index 84a9ae74ff..e35879fdd2 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java
@@ -1,10 +1,10 @@
package com.baeldung.springbootdatasourceconfig.application.entities;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
@Entity
@Table(name = "users")
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java
index 7562c072c7..5afc55a09b 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java
@@ -1,8 +1,8 @@
package com.baeldung.springboothibernate.application.models;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
@Entity
public class Book {
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java
index 2feee10980..2922bb9167 100644
--- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java
@@ -35,13 +35,13 @@ public class LegacyJpaImplNamingIntegrationTest extends NamingConfig {
String tableNameCreated = table.getName();
boolean columnNameIsQuoted = table
- .getColumn(3)
+ .getColumn(2)
.isQuoted();
String physicalNameCreated = table
- .getColumn(3)
+ .getColumn(2)
.getName();
String implicitNameCreated = table
- .getColumn(2)
+ .getColumn(3)
.getName();
SoftAssertions.assertSoftly(softly -> {
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java
index c5c320f70c..4fb13a1798 100644
--- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java
@@ -16,10 +16,6 @@ import com.baeldung.boot.naming.entity.Account;
@RunWith(SpringRunner.class)
@DataJpaTest
-@TestPropertySource(properties = {
- "spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy",
- "spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy"
-})
@Import(Config.class)
public class SpringBootDefaultNamingIntegrationTest extends NamingConfig {
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java
index ef978e5a98..8269e6c34a 100644
--- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java
@@ -1,6 +1,5 @@
package com.baeldung.boot.naming;
-import com.baeldung.boot.naming.MetadataExtractorIntegrator;
import com.baeldung.boot.naming.NamingConfig.Config;
import com.baeldung.boot.naming.entity.Preference;
@@ -47,7 +46,7 @@ public class StrategyLegacyHbmImplIntegrationTest extends NamingConfig {
String implicitNameExpected = "account";
String implicitNameCreated = preferenceTable
- .getColumn(3)
+ .getColumn(1)
.getName();
String tableNameCreated = accountPreferencesTable.getName();
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java
index 515350fe0a..2a90f36a7c 100644
--- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java
@@ -12,7 +12,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
-import javax.persistence.EntityManagerFactory;
+import jakarta.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
diff --git a/persistence-modules/spring-data-jpa-enterprise/pom.xml b/persistence-modules/spring-data-jpa-enterprise/pom.xml
index 16294cd3cc..6bd89032fa 100644
--- a/persistence-modules/spring-data-jpa-enterprise/pom.xml
+++ b/persistence-modules/spring-data-jpa-enterprise/pom.xml
@@ -54,6 +54,11 @@
spring-security-test
test
+
+ org.postgresql
+ postgresql
+ runtime
+
org.testcontainers
@@ -61,6 +66,12 @@
${testcontainers.version}
test
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainers.version}
+ test
+
@@ -87,7 +98,7 @@
1.3.1.Final
- 1.17.3
+ 1.19.1
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties
index 0ca1872207..875253c79e 100644
--- a/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties
+++ b/persistence-modules/spring-data-jpa-enterprise/src/main/resources/application.properties
@@ -12,4 +12,5 @@ spring.datasource.url=jdbc:h2:mem:baeldung
spring.jpa.show-sql=false
#hibernate.dialect=org.hibernate.dialect.H2Dialect
+spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.id.new_generator_mappings=false
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java
index e8841d921c..45be598153 100644
--- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java
+++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java
@@ -1,8 +1,9 @@
package com.baeldung.boot.daos;
-import org.junit.After;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@@ -25,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.*;
+@SpringBootTest
public class UserRepositoryCommon {
final String USER_EMAIL = "email@example.com";
@@ -274,7 +276,7 @@ public class UserRepositoryCommon {
.getName()).isEqualTo(USER_NAME_ADAM);
}
- @Test(expected = PropertyReferenceException.class)
+ @Test
public void givenUsersInDB_WhenFindAllSortWithFunction_ThenThrowException() {
userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
@@ -282,10 +284,7 @@ public class UserRepositoryCommon {
userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
- List usersSortByNameLength = userRepository.findAll(Sort.by("LENGTH(name)"));
-
- assertThat(usersSortByNameLength.get(0)
- .getName()).isEqualTo(USER_NAME_ADAM);
+ assertThrows(PropertyReferenceException.class, () -> userRepository.findAll(Sort.by("LENGTH(name)")));
}
@Test
@@ -556,7 +555,7 @@ public class UserRepositoryCommon {
assertEquals(0, nativeQuery.getResultList().get(0));
}
- @After
+ @AfterEach
public void cleanUp() {
userRepository.deleteAll();
}
diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java
index 1b1d264574..c4d9d65746 100644
--- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java
@@ -2,11 +2,10 @@ package com.baeldung.boot.daos;
import com.baeldung.boot.Application;
import com.baeldung.boot.domain.User;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
@@ -16,7 +15,6 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Created by adam.
*/
-@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@DirtiesContext
public class UserRepositoryIntegrationTest extends UserRepositoryCommon {
diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java
index 99eabc8271..056b3cea28 100644
--- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java
+++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java
@@ -3,14 +3,15 @@ package com.baeldung.boot.daos;
import com.baeldung.boot.Application;
import com.baeldung.boot.domain.User;
import com.baeldung.util.BaeldungPostgresqlContainer;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.LocalDate;
@@ -19,12 +20,12 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Created by adam.
*/
-@RunWith(SpringRunner.class)
+@Testcontainers
@SpringBootTest(classes = Application.class)
@ActiveProfiles({"tc", "tc-auto"})
public class UserRepositoryTCAutoLiveTest extends UserRepositoryCommon {
- @ClassRule
+ @Container
public static PostgreSQLContainer postgreSQLContainer = BaeldungPostgresqlContainer.getInstance();
@Test
diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java
index c976590966..f4af7284bd 100644
--- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java
+++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCJdbcLiveTest.java
@@ -1,21 +1,21 @@
package com.baeldung.boot.daos;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.LocalDate;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.transaction.annotation.Transactional;
+
import com.baeldung.boot.Application;
import com.baeldung.boot.daos.user.UserRepository;
import com.baeldung.boot.domain.User;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.transaction.annotation.Transactional;
-import java.time.LocalDate;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@RunWith(SpringRunner.class)
@ActiveProfiles("tc-jdbc")
@SpringBootTest(classes = Application.class)
public class UserRepositoryTCJdbcLiveTest {
diff --git a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java
index be8843c166..33f4bbeeff 100644
--- a/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java
+++ b/persistence-modules/spring-data-jpa-enterprise/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java
@@ -1,33 +1,29 @@
package com.baeldung.boot.daos;
-import com.baeldung.boot.Application;
-import com.baeldung.boot.domain.User;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.util.TestPropertyValues;
-import org.springframework.context.ApplicationContextInitializer;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.transaction.annotation.Transactional;
-import org.testcontainers.containers.PostgreSQLContainer;
-
-import java.time.LocalDate;
-
import static org.assertj.core.api.Assertions.assertThat;
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes = Application.class)
+import java.time.LocalDate;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.springframework.transaction.annotation.Transactional;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import com.baeldung.boot.domain.User;
+
+@Testcontainers
+@SpringBootTest
@ActiveProfiles("tc")
-@ContextConfiguration(initializers = {UserRepositoryTCLiveTest.Initializer.class})
public class UserRepositoryTCLiveTest extends UserRepositoryCommon {
- @ClassRule
+ @Container
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:11.1")
- .withDatabaseName("integration-tests-db")
+ .withDatabaseName("integration-tests-db")
.withUsername("sa")
.withPassword("sa");
@@ -45,14 +41,10 @@ public class UserRepositoryTCLiveTest extends UserRepositoryCommon {
assertThat(updatedUsersSize).isEqualTo(2);
}
- static class Initializer
- implements ApplicationContextInitializer {
- public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
- TestPropertyValues.of(
- "spring.datasource.url=" + postgreSQLContainer.getJdbcUrl(),
- "spring.datasource.username=" + postgreSQLContainer.getUsername(),
- "spring.datasource.password=" + postgreSQLContainer.getPassword()
- ).applyTo(configurableApplicationContext.getEnvironment());
- }
+ @DynamicPropertySource
+ static void registerPgProperties(DynamicPropertyRegistry registry) {
+ registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
+ registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
+ registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
}
}
diff --git a/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceManualTest.java b/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceManualTest.java
new file mode 100644
index 0000000000..895dd52afb
--- /dev/null
+++ b/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceManualTest.java
@@ -0,0 +1,90 @@
+package com.baeldung.shardingsphere;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.MySQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.util.List;
+
+
+/**
+ * This Manual test requires: Docker service running.
+ */
+@Testcontainers
+@SpringBootTest
+class OrderServiceManualTest {
+
+ @Container
+ static MySQLContainer> mySQLContainer1 = new MySQLContainer<>("mysql:8.0.23")
+ .withDatabaseName("ds0")
+ .withUsername("test")
+ .withPassword("test");
+
+ @Container
+ static MySQLContainer> mySQLContainer2 = new MySQLContainer<>("mysql:8.0.23")
+ .withDatabaseName("ds1")
+ .withUsername("test")
+ .withPassword("test");
+
+ static {
+ mySQLContainer2.setPortBindings(List.of("13307:3306"));
+ mySQLContainer1.setPortBindings(List.of("13306:3306"));
+ }
+ @Autowired
+ private OrderService orderService;
+
+ @Autowired
+ private OrderRepository orderRepository;
+
+ @DynamicPropertySource
+ static void setProperties(DynamicPropertyRegistry registry) {
+ registry.add("spring.jpa.hibernate.ddl-auto", () -> "create-drop");
+ }
+
+ @Test
+ void shouldFindOrderInCorrectShard() {
+ // given
+ Order order1 = new Order(1L, 1L, BigDecimal.TEN, Status.PROCESSING, LocalDate.now(), "123 Main St");
+ Order order2 = new Order(2L, 2L, BigDecimal.valueOf(12.5), Status.SHIPPED, LocalDate.now(), "456 Main St");
+
+ // when
+ Order savedOrder1 = orderService.createOrder(order1);
+ Order savedOrder2 = orderService.createOrder(order2);
+
+ // then
+ // Assuming the sharding strategy is based on the order id, data for order1 should be present only in ds0
+ // and data for order2 should be present only in ds1
+ Assertions.assertThat(orderService.getOrder(savedOrder1.getOrderId())).isEqualTo(savedOrder1);
+ Assertions.assertThat(orderService.getOrder(savedOrder2.getOrderId())).isEqualTo(savedOrder2);
+
+ // Verify that the orders are not present in the wrong shards.
+ // You would need to implement these methods in your OrderService.
+ // They should use a JdbcTemplate or EntityManager to execute SQL directly against each shard.
+ Assertions.assertThat(assertOrderInShard(savedOrder1, mySQLContainer2)).isTrue();
+ Assertions.assertThat(assertOrderInShard(savedOrder2, mySQLContainer1)).isTrue();
+ }
+
+ private boolean assertOrderInShard(Order order, MySQLContainer> container) {
+ try (Connection conn = DriverManager.getConnection(container.getJdbcUrl(), container.getUsername(), container.getPassword())) {
+ PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `order` WHERE order_id = ?");
+ stmt.setLong(1, order.getOrderId());
+ ResultSet rs = stmt.executeQuery();
+ return rs.next();
+ } catch (SQLException ex) {
+ throw new RuntimeException("Error querying order in shard", ex);
+ }
+ }
+}
diff --git a/persistence-modules/spring-hibernate-6/README.md b/persistence-modules/spring-hibernate-6/README.md
index 08fe6216fd..86a1c919f3 100644
--- a/persistence-modules/spring-hibernate-6/README.md
+++ b/persistence-modules/spring-hibernate-6/README.md
@@ -6,4 +6,4 @@ This module contains articles about Hibernate 6 with Spring.
- [Programmatic Transactions in the Spring TestContext Framework](https://www.baeldung.com/spring-test-programmatic-transactions)
- [@DynamicUpdate with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-dynamicupdate)
-- [Bootstrapping Hibernate 5 with Spring](https://www.baeldung.com/hibernate-5-spring)
+- [Bootstrapping Hibernate with Spring](https://www.baeldung.com/hibernate-spring)
diff --git a/pom.xml b/pom.xml
index 6853b10587..5d8358f05e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -726,9 +726,11 @@
spring-cloud-modules/spring-cloud-circuit-breaker
spring-cloud-modules/spring-cloud-contract
spring-cloud-modules/spring-cloud-data-flow
+ spring-cloud-modules/spring-cloud-eureka
spring-cloud-modules/spring-cloud-netflix-feign
spring-cloud-modules/spring-cloud-stream-starters
spring-cloud-modules/spring-cloud-zuul-eureka-integration
+
spring-exceptions
spring-jenkins-pipeline
spring-core
@@ -1004,10 +1006,13 @@
spring-drools
spring-cloud-modules/spring-cloud-azure
spring-cloud-modules/spring-cloud-circuit-breaker
+ spring-cloud-modules/spring-cloud-eureka
spring-cloud-modules/spring-cloud-contract
+ spring-cloud-modules/spring-cloud-data-flow
spring-cloud-modules/spring-cloud-netflix-feign
spring-cloud-modules/spring-cloud-stream-starters
spring-cloud-modules/spring-cloud-zuul-eureka-integration
+
spring-exceptions
spring-jenkins-pipeline
spring-core
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java
index e8818c1019..2633f227d4 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/DynamicPropertiesLiveTest.java
@@ -25,6 +25,8 @@ import com.baeldung.testcontainers.support.MiddleEarthCharactersRepository;
@Testcontainers
@SpringBootTest(webEnvironment = DEFINED_PORT)
@DirtiesContext(classMode = AFTER_CLASS)
+// Testcontainers require a valid docker installation.
+// When running the tests, ensure you have a valid Docker environment
class DynamicPropertiesLiveTest {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java
index a94c0f772a..1b6fe32c97 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/LocalDevApplication.java
@@ -8,6 +8,9 @@ import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.utility.DockerImageName;
+
+// Testcontainers require a valid docker installation.
+// When running the app locally, ensure you have a valid Docker environment
class LocalDevApplication {
public static void main(String[] args) {
diff --git a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java
index 838ee127f6..51b69c44b3 100644
--- a/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java
+++ b/spring-boot-modules/spring-boot-3-testcontainers/src/test/java/com/baeldung/testcontainers/ServiceConnectionLiveTest.java
@@ -24,6 +24,8 @@ import com.baeldung.testcontainers.support.MiddleEarthCharactersRepository;
@Testcontainers
@SpringBootTest(webEnvironment = DEFINED_PORT)
@DirtiesContext(classMode = AFTER_CLASS)
+// Testcontainers require a valid docker installation.
+// When running the tests, ensure you have a valid Docker environment
class ServiceConnectionLiveTest {
@Container
diff --git a/spring-boot-modules/spring-boot-3/pom.xml b/spring-boot-modules/spring-boot-3/pom.xml
index 7dd44c89dc..bb8c5dd53c 100644
--- a/spring-boot-modules/spring-boot-3/pom.xml
+++ b/spring-boot-modules/spring-boot-3/pom.xml
@@ -60,7 +60,11 @@
org.junit.jupiter
junit-jupiter-params
${jupiter.version}
- test
+
+
+ org.junit.platform
+ junit-platform-commons
+ 1.10.0
org.mock-server
@@ -204,7 +208,7 @@
19
1.5.2.Final
- 2.0.0
+ 2.2.0
3.0.0-M7
com.baeldung.sample.TodoApplication
5.14.0
diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/Article.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/Article.java
index a69d5989af..892cf3b5ae 100644
--- a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/Article.java
+++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/Article.java
@@ -6,6 +6,8 @@ public class Article {
Integer id;
String title;
+ public Article() {}
+
public Article(Integer id, String title) {
this.id = id;
this.title = title;
@@ -19,6 +21,14 @@ public class Article {
return title;
}
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleController.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleController.java
index 62922bdcee..5e1dff6fd7 100644
--- a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleController.java
+++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleController.java
@@ -1,5 +1,6 @@
package com.baeldung.restclient;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
@@ -13,13 +14,21 @@ public class ArticleController {
Map database = new HashMap<>();
@GetMapping
- public Collection getArticles() {
- return database.values();
+ public ResponseEntity> getArticles() {
+ Collection values = database.values();
+ if (values.isEmpty()) {
+ return ResponseEntity.noContent().build();
+ }
+ return ResponseEntity.ok(values);
}
@GetMapping("/{id}")
- public Article getArticle(@PathVariable Integer id) {
- return database.get(id);
+ public ResponseEntity getArticle(@PathVariable("id") Integer id) {
+ Article article = database.get(id);
+ if (article == null) {
+ return ResponseEntity.notFound().build();
+ }
+ return ResponseEntity.ok(article);
}
@PostMapping
@@ -28,7 +37,7 @@ public class ArticleController {
}
@PutMapping("/{id}")
- public void updateArticle(@PathVariable Integer id, @RequestBody Article article) {
+ public void updateArticle(@PathVariable("id") Integer id, @RequestBody Article article) {
assert Objects.equals(id, article.getId());
database.remove(id);
database.put(id, article);
diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleNotFoundException.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleNotFoundException.java
new file mode 100644
index 0000000000..cdd13b8330
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/ArticleNotFoundException.java
@@ -0,0 +1,6 @@
+package com.baeldung.restclient;
+
+public class ArticleNotFoundException extends RuntimeException {
+ public ArticleNotFoundException() {
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/InvalidArticleResponseException.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/InvalidArticleResponseException.java
new file mode 100644
index 0000000000..26ca75036e
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/restclient/InvalidArticleResponseException.java
@@ -0,0 +1,6 @@
+package com.baeldung.restclient;
+
+public class InvalidArticleResponseException extends RuntimeException {
+ public InvalidArticleResponseException() {
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java
index 92474c88f0..1a615faf4e 100644
--- a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java
+++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/restclient/RestClientIntegrationTest.java
@@ -1,17 +1,23 @@
package com.baeldung.restclient;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClient;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@@ -22,7 +28,10 @@ public class RestClientIntegrationTest {
private String uriBase;
RestClient restClient = RestClient.create();
- @BeforeAll
+ @Autowired
+ ObjectMapper objectMapper;
+
+ @BeforeEach
public void setup() {
uriBase = "http://localhost:" + port;
}
@@ -42,7 +51,7 @@ public class RestClientIntegrationTest {
.retrieve()
.body(String.class);
- assertThat(articlesAsString).isEqualTo("[]");
+ assertThat(articlesAsString).isEqualTo("");
}
@Test
@@ -63,6 +72,48 @@ public class RestClientIntegrationTest {
assertThat(articles).isEqualTo(List.of(article));
}
+ @Test
+ void shouldPostAndGetArticlesWithExchange() {
+ assertThatThrownBy(this::getArticlesWithExchange).isInstanceOf(ArticleNotFoundException.class);
+
+ Article article = new Article(1, "How to use RestClient");
+ restClient.post()
+ .uri(uriBase + "/articles")
+ .contentType(MediaType.APPLICATION_JSON)
+ .body(article)
+ .retrieve()
+ .toBodilessEntity();
+
+ List articles = getArticlesWithExchange();
+
+ assertThat(articles).isEqualTo(List.of(article));
+ }
+
+ private List getArticlesWithExchange() {
+ return restClient.get()
+ .uri(uriBase + "/articles")
+ .exchange((request, response) -> {
+ if (response.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(204))) {
+ throw new ArticleNotFoundException();
+ } else if (response.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
+ return objectMapper.readValue(response.getBody(), new TypeReference<>() {});
+ } else {
+ throw new InvalidArticleResponseException();
+ }
+ });
+ }
+
+ @Test
+ void shouldPostAndGetArticlesWithErrorHandling() {
+ assertThatThrownBy(() -> {
+ restClient.get()
+ .uri(uriBase + "/articles/1234")
+ .retrieve()
+ .onStatus(status -> status.value() == 404, (request, response) -> { throw new ArticleNotFoundException(); })
+ .body(new ParameterizedTypeReference<>() {});
+ }).isInstanceOf(ArticleNotFoundException.class);
+ }
+
@Test
void shouldPostAndPutAndGetArticles() {
Article article = new Article(1, "How to use RestClient");
@@ -79,7 +130,7 @@ public class RestClientIntegrationTest {
.contentType(MediaType.APPLICATION_JSON)
.body(articleChanged)
.retrieve()
- .toBodilessEntity();
+ .toBodilessEntity();
List articles = restClient.get()
.uri(uriBase + "/articles")
@@ -104,11 +155,12 @@ public class RestClientIntegrationTest {
.retrieve()
.toBodilessEntity();
- List articles = restClient.get()
+ ResponseEntity entity = restClient.get()
.uri(uriBase + "/articles")
+ .accept(MediaType.APPLICATION_JSON)
.retrieve()
- .body(new ParameterizedTypeReference<>() {});
+ .toBodilessEntity();
- assertThat(articles).isEqualTo(List.of());
+ assertThat(entity.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(204));
}
}
diff --git a/spring-boot-modules/spring-boot-bootstrap/pom.xml b/spring-boot-modules/spring-boot-bootstrap/pom.xml
index 4ceae26f60..da16f79a2a 100644
--- a/spring-boot-modules/spring-boot-bootstrap/pom.xml
+++ b/spring-boot-modules/spring-boot-bootstrap/pom.xml
@@ -9,9 +9,10 @@
Demo project for Spring Boot
- com.baeldung.spring-boot-modules
- spring-boot-modules
- 1.0.0-SNAPSHOT
+ com.baeldung
+ parent-boot-3
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-3
@@ -47,13 +48,12 @@
io.rest-assured
rest-assured
- ${rest-assured.version}
test
- javax.servlet
- javax.servlet-api
- ${servlet.version}
+ org.springframework.boot
+ spring-boot-starter-cloud-connectors
+ ${spring-boot-cloud-connectors.version}
@@ -332,6 +332,7 @@
4.0.0
Greenwich.RELEASE
1.0.0.RELEASE
+ 2.2.13.RELEASE
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/config/SecurityConfig.java b/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/config/SecurityConfig.java
index ecb21cdf4b..c876e1c3d4 100644
--- a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/config/SecurityConfig.java
+++ b/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/config/SecurityConfig.java
@@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@@ -12,12 +13,11 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http.authorizeRequests()
- .anyRequest()
- .permitAll()
- .and()
- .csrf()
- .disable();
+ http.authorizeHttpRequests(expressionInterceptUrlRegistry ->
+ expressionInterceptUrlRegistry
+ .anyRequest()
+ .permitAll())
+ .csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}
diff --git a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/persistence/model/Book.java b/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/persistence/model/Book.java
index 6be27d4cf0..d599c64567 100644
--- a/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/persistence/model/Book.java
+++ b/spring-boot-modules/spring-boot-bootstrap/src/main/java/com/baeldung/persistence/model/Book.java
@@ -1,10 +1,10 @@
package com.baeldung.persistence.model;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
@Entity
public class Book {
diff --git a/spring-boot-modules/spring-boot-keycloak/pom.xml b/spring-boot-modules/spring-boot-keycloak/pom.xml
index bada9ab52d..13339c9de1 100644
--- a/spring-boot-modules/spring-boot-keycloak/pom.xml
+++ b/spring-boot-modules/spring-boot-keycloak/pom.xml
@@ -102,7 +102,7 @@
- com.baeldung.keycloak.SpringBoot
+ com.baeldung.keycloak.SpringBootKeycloakApp
4.0.0
1.6.3
2.5.0
diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBoot.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBootKeycloakApp.java
similarity index 80%
rename from spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBoot.java
rename to spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBootKeycloakApp.java
index 90d7e774a4..a6f978fb3f 100644
--- a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBoot.java
+++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBootKeycloakApp.java
@@ -6,11 +6,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
-
-public class SpringBoot {
+public class SpringBootKeycloakApp {
public static void main(String[] args) {
- SpringApplication.run(SpringBoot.class, args);
+ SpringApplication.run(SpringBootKeycloakApp.class, args);
}
@Bean
diff --git a/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakContextIntegrationTest.java b/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakContextIntegrationTest.java
index 336c8364aa..116516acfe 100644
--- a/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakContextIntegrationTest.java
+++ b/spring-boot-modules/spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakContextIntegrationTest.java
@@ -4,10 +4,9 @@ import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import com.baeldung.keycloak.SpringBoot;
@ExtendWith(SpringExtension.class)
-@SpringBootTest(classes = { SpringBoot.class })
+@SpringBootTest(classes = { SpringBootKeycloakApp.class })
public class KeycloakContextIntegrationTest {
@Test
diff --git a/spring-boot-modules/spring-boot-security-2/README.md b/spring-boot-modules/spring-boot-security-2/README.md
new file mode 100644
index 0000000000..2774f60c43
--- /dev/null
+++ b/spring-boot-modules/spring-boot-security-2/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles
+- [Difference Between permitAll() and anonymous() in Spring Security](https://www.baeldung.com/spring-security-permitall-vs-anonymous)
diff --git a/spring-boot-modules/spring-boot-security-2/pom.xml b/spring-boot-modules/spring-boot-security-2/pom.xml
new file mode 100644
index 0000000000..db094f33a6
--- /dev/null
+++ b/spring-boot-modules/spring-boot-security-2/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+ spring-boot-security-2
+ spring-boot-security-1
+ jar
+ Spring Boot Security Auto-Configuration
+
+
+ com.baeldung.spring-boot-modules
+ spring-boot-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/SecuredEcommerceApplication.java b/spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/SecuredEcommerceApplication.java
similarity index 100%
rename from spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/SecuredEcommerceApplication.java
rename to spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/SecuredEcommerceApplication.java
diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/controller/EcommerceController.java b/spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/controller/EcommerceController.java
similarity index 92%
rename from spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/controller/EcommerceController.java
rename to spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/controller/EcommerceController.java
index 8f20baee10..d76075016a 100644
--- a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/controller/EcommerceController.java
+++ b/spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/controller/EcommerceController.java
@@ -13,7 +13,7 @@ public class EcommerceController {
return "Show Cart";
}
- //can we accessed by both anonymous and authenticated users
+ //can be accessed by both anonymous and authenticated users
@GetMapping("/public/showProducts")
public @ResponseBody String listProducts() {
return "List Products";
diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/filter/AuditInterceptor.java b/spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/filter/AuditInterceptor.java
similarity index 100%
rename from spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/filter/AuditInterceptor.java
rename to spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/filter/AuditInterceptor.java
diff --git a/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/security/EcommerceWebSecurityConfig.java b/spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/security/EcommerceWebSecurityConfig.java
similarity index 100%
rename from spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/permitallanonymous/security/EcommerceWebSecurityConfig.java
rename to spring-boot-modules/spring-boot-security-2/src/main/java/com/baeldung/permitallanonymous/security/EcommerceWebSecurityConfig.java
diff --git a/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/permitallanonymous/SecureEcommerceApplicationUnitTest.java b/spring-boot-modules/spring-boot-security-2/src/test/java/com/baeldung/permitallanonymous/SecureEcommerceApplicationUnitTest.java
similarity index 100%
rename from spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/permitallanonymous/SecureEcommerceApplicationUnitTest.java
rename to spring-boot-modules/spring-boot-security-2/src/test/java/com/baeldung/permitallanonymous/SecureEcommerceApplicationUnitTest.java
diff --git a/spring-boot-modules/spring-boot-security/README.md b/spring-boot-modules/spring-boot-security/README.md
index 2fd9e77c92..64a7a69e3a 100644
--- a/spring-boot-modules/spring-boot-security/README.md
+++ b/spring-boot-modules/spring-boot-security/README.md
@@ -11,7 +11,6 @@ This module contains articles about Spring Boot Security
- [Disable Security for a Profile in Spring Boot](https://www.baeldung.com/spring-security-disable-profile)
- [Spring @EnableWebSecurity vs. @EnableGlobalMethodSecurity](https://www.baeldung.com/spring-enablewebsecurity-vs-enableglobalmethodsecurity)
- [Spring Security – Configuring Different URLs](https://www.baeldung.com/spring-security-configuring-urls)
-- [Difference Between permitAll() and anonymous() in Spring Security](https://www.baeldung.com/spring-security-permitall-vs-anonymous)
### Spring Boot Security Auto-Configuration
diff --git a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java
index 5c24368ce6..9a1bf547db 100644
--- a/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java
+++ b/spring-boot-modules/spring-boot-swagger-keycloak/src/main/java/com/baeldung/swaggerkeycloak/GlobalSecurityConfig.java
@@ -3,10 +3,11 @@ package com.baeldung.swaggerkeycloak;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
+import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
@@ -24,16 +25,19 @@ public class GlobalSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http.csrf()
- .disable()
- .authorizeRequests()
- .requestMatchers(HttpMethod.OPTIONS)
+
+ http.csrf(AbstractHttpConfigurer::disable)
+ .authorizeHttpRequests((requests) -> requests.requestMatchers(HttpMethod.OPTIONS)
.permitAll()
.requestMatchers("/api/**")
.authenticated()
.anyRequest()
- .permitAll();
- http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
+ .permitAll());
+
+ http.oauth2ResourceServer((oauth2) -> oauth2
+ .jwt(Customizer.withDefaults())
+ );
+
return http.build();
}
diff --git a/spring-boot-modules/spring-boot-testing-2/README.md b/spring-boot-modules/spring-boot-testing-2/README.md
index e6bc4c4590..1baf83bf34 100644
--- a/spring-boot-modules/spring-boot-testing-2/README.md
+++ b/spring-boot-modules/spring-boot-testing-2/README.md
@@ -13,4 +13,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Spring Web Service Integration Tests with @WebServiceServerTest](https://www.baeldung.com/spring-webserviceservertest)
- [Spring Boot – Testing Redis With Testcontainers](https://www.baeldung.com/spring-boot-redis-testcontainers)
- [Spring Boot – Keycloak Integration Testing with Testcontainers](https://www.baeldung.com/spring-boot-keycloak-integration-testing)
+- [Difference Between @Spy and @SpyBean](https://www.baeldung.com/spring-spy-vs-spybean)
- More articles: [[<-- prev]](../spring-boot-testing)
diff --git a/spring-cloud-modules/pom.xml b/spring-cloud-modules/pom.xml
index b21b208414..a098bc90a9 100644
--- a/spring-cloud-modules/pom.xml
+++ b/spring-cloud-modules/pom.xml
@@ -19,7 +19,8 @@
spring-cloud-loadbalancer
spring-cloud-config
- spring-cloud-eureka
+
+
spring-cloud-hystrix
spring-cloud-bootstrap
spring-cloud-ribbon-client
diff --git a/spring-cloud-modules/spring-cloud-contract/pom.xml b/spring-cloud-modules/spring-cloud-contract/pom.xml
index 7a9c8c32cd..f2d0d1b5b0 100644
--- a/spring-cloud-modules/spring-cloud-contract/pom.xml
+++ b/spring-cloud-modules/spring-cloud-contract/pom.xml
@@ -41,28 +41,35 @@
org.springframework.cloud
spring-cloud-contract-wiremock
- ${spring-cloud.version}
+ ${spring-cloud-contract.version}
test
org.springframework.cloud
spring-cloud-contract-stub-runner
- ${spring-cloud.version}
+ ${spring-cloud-contract.version}
test
org.springframework.cloud
spring-cloud-starter-contract-verifier
- ${spring-cloud.version}
+ ${spring-cloud-contract.version}
test
+
+ org.codehaus.groovy
+ groovy
+ ${groovy.version}
+
4.0.3
+ 4.0.4
2.1.4.RELEASE
2.17.1
+ 2.5.6
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml b/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml
index 680e2e1795..a8c3337de5 100644
--- a/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml
+++ b/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml
@@ -16,6 +16,15 @@
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-rest
+
+
org.springframework.cloud
spring-cloud-contract-wiremock
@@ -26,20 +35,13 @@
spring-cloud-contract-stub-runner
test
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-data-rest
-
com.baeldung.spring.cloud
spring-cloud-contract-producer
${project.parent.version}
test
+
io.rest-assured
rest-assured
@@ -50,6 +52,12 @@
+
+
+ org.codehaus.groovy
+ groovy
+
+
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-producer/pom.xml b/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-producer/pom.xml
index 35dd9596f7..eb80f8d3dd 100644
--- a/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-producer/pom.xml
+++ b/spring-cloud-modules/spring-cloud-contract/spring-cloud-contract-producer/pom.xml
@@ -16,19 +16,17 @@
-
- org.springframework.cloud
- spring-cloud-starter-contract-verifier
- test
-
+
org.springframework.boot
spring-boot-starter-web
+
org.springframework.boot
spring-boot-starter-data-rest
+
io.rest-assured
rest-assured
@@ -39,6 +37,18 @@
+
+
+ org.springframework.cloud
+ spring-cloud-starter-contract-verifier
+ test
+
+
+
+ org.codehaus.groovy
+ groovy
+
+
@@ -46,7 +56,7 @@
org.springframework.cloud
spring-cloud-contract-maven-plugin
- 2.1.1.RELEASE
+ ${spring-cloud-contract.version}
true
com.baeldung.spring.cloud.springcloudcontractproducer.BaseTestClass
diff --git a/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/com/baeldung/spring/cloud/DataFlowServerApplicationIntegrationTest.java b/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/com/baeldung/spring/cloud/DataFlowServerApplicationIntegrationTest.java
index 68f0db60eb..49eb255303 100644
--- a/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/com/baeldung/spring/cloud/DataFlowServerApplicationIntegrationTest.java
+++ b/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/com/baeldung/spring/cloud/DataFlowServerApplicationIntegrationTest.java
@@ -9,6 +9,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.session.data.redis.config.ConfigureRedisAction;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.test.context.junit4.SpringRunner;
@@ -39,5 +40,10 @@ public class DataFlowServerApplicationIntegrationTest {
return factory;
}
+
+ @Bean
+ public static ConfigureRedisAction configureRedisAction() {
+ return ConfigureRedisAction.NO_OP;
+ }
}
}
diff --git a/spring-cloud-modules/spring-cloud-eureka/pom.xml b/spring-cloud-modules/spring-cloud-eureka/pom.xml
index 23523f2c2f..599853c675 100644
--- a/spring-cloud-modules/spring-cloud-eureka/pom.xml
+++ b/spring-cloud-modules/spring-cloud-eureka/pom.xml
@@ -45,8 +45,6 @@
- 2.1.2.RELEASE
- Greenwich.RELEASE
2.17.1
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml
index 4fdfe2d9c2..08a85d191a 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml
@@ -41,7 +41,7 @@
org.springframework.cloud
- spring-cloud-starter-netflix-ribbon
+ spring-cloud-starter-loadbalancer
org.springframework.cloud
@@ -51,6 +51,20 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ 2.6.8
+
com.github.tomakehurst
wiremock
@@ -75,9 +89,18 @@
+
+
+ repository.spring.milestone
+ Spring Milestone Repository
+ https://repo.spring.io/release
+
+
+
+ org.apache.maven.plugins
maven-surefire-plugin
1
@@ -87,4 +110,9 @@
+
+ 17
+ 17
+
+
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java
index a263624b28..97d8643e19 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java
@@ -1,16 +1,15 @@
package com.baeldung.spring.cloud.client;
-import com.baeldung.spring.cloud.model.Book;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.RequestMapping;
-
import java.util.List;
-@FeignClient("books-service")
-//@FeignClient(value="simple-books-client", url="${book.service.url}")
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import com.baeldung.spring.cloud.model.Book;
+
+@FeignClient(name = "books-service")
public interface BooksClient {
@RequestMapping("/books")
List getBooks();
-
}
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java
index 2842eef435..7f4807e356 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java
@@ -8,6 +8,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -21,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest
@ActiveProfiles("test")
+@EnableFeignClients
@EnableConfigurationProperties
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { WireMockConfig.class })
@@ -29,12 +31,16 @@ class BooksClientIntegrationTest {
@Autowired
private WireMockServer mockBooksService;
+ @Autowired
+ private WireMockServer mockBooksService2;
+
@Autowired
private BooksClient booksClient;
@BeforeEach
void setUp() throws IOException {
setupMockBooksResponse(mockBooksService);
+ setupMockBooksResponse(mockBooksService2);
}
@Test
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java
index 6747d14b88..10ea3ffa34 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java
@@ -31,9 +31,6 @@ public class EurekaContainerConfig {
+ eurekaServer.getFirstMappedPort().toString()
+ "/eureka")
.applyTo(configurableApplicationContext);
-
}
-
}
-
}
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java
index f05df11ba3..5690c24d77 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java
@@ -9,23 +9,39 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.client.DefaultServiceInstance;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.loadbalancer.Response;
+import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
+import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
+import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
+import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
+import org.springframework.cloud.loadbalancer.support.ServiceInstanceListSuppliers;
+import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
import static com.baeldung.spring.cloud.client.BookMocks.setupMockBooksResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.moreThan;
import static java.util.Arrays.asList;
+import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
@SpringBootTest
-@ActiveProfiles("ribbon-test")
+@ActiveProfiles("test")
@EnableConfigurationProperties
+@EnableFeignClients
@ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { RibbonTestConfig.class })
+@ContextConfiguration(classes = { TestConfig.class })
class LoadBalancerBooksClientIntegrationTest {
@Autowired
@@ -37,10 +53,22 @@ class LoadBalancerBooksClientIntegrationTest {
@Autowired
private BooksClient booksClient;
+ @Autowired
+ private LoadBalancerClientFactory clientFactory;
+
@BeforeEach
void setUp() throws IOException {
setupMockBooksResponse(mockBooksService);
setupMockBooksResponse(secondMockBooksService);
+
+ String serviceId = "books-service";
+ RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(ServiceInstanceListSuppliers
+ .toProvider(serviceId, instance(serviceId, "localhost", false), instance(serviceId, "localhost", true)),
+ serviceId, -1);
+ }
+
+ private static DefaultServiceInstance instance(String serviceId, String host, boolean secure) {
+ return new DefaultServiceInstance(serviceId, serviceId, host, 80, secure);
}
@Test
@@ -62,4 +90,53 @@ class LoadBalancerBooksClientIntegrationTest {
new Book("Dune", "Frank Herbert"),
new Book("Foundation", "Isaac Asimov"))));
}
+
+ @Test
+ void loadbalancerWorks() throws IOException {
+
+ setupMockBooksResponse(mockBooksService);
+ setupMockBooksResponse(secondMockBooksService);
+
+ ReactiveLoadBalancer reactiveLoadBalancer = this.clientFactory.getInstance("books-service",
+ ReactiveLoadBalancer.class, ServiceInstance.class);
+
+ then(reactiveLoadBalancer).isInstanceOf(RoundRobinLoadBalancer.class);
+ then(reactiveLoadBalancer).isInstanceOf(ReactorLoadBalancer.class);
+ ReactorLoadBalancer loadBalancer = (ReactorLoadBalancer) reactiveLoadBalancer;
+
+ for (int k = 0; k < 10; k++) {
+ booksClient.getBooks();
+ }
+
+ // order dependent on seedPosition -1 of RoundRobinLoadBalancer
+ List hosts = Arrays.asList("localhost", "localhost");
+
+ assertLoadBalancer(loadBalancer, hosts);
+
+ mockBooksService.verify(
+ moreThan(0), getRequestedFor(WireMock.urlEqualTo("/books")));
+ secondMockBooksService.verify(
+ moreThan(0), getRequestedFor(WireMock.urlEqualTo("/books")));
+ }
+
+ private void assertLoadBalancer(ReactorLoadBalancer loadBalancer, List hosts) {
+ for (String host : hosts) {
+ Mono> source = loadBalancer.choose();
+ StepVerifier.create(source).consumeNextWith(response -> {
+ then(response).isNotNull();
+ then(response.hasServer()).isTrue();
+
+ ServiceInstance instance = response.getServer();
+ then(instance).isNotNull();
+ then(instance.getHost()).as("instance host is incorrect %s", host).isEqualTo(host);
+
+ if (host.contains("secure")) {
+ then(instance.isSecure()).isTrue();
+ }
+ else {
+ then(instance.isSecure()).isFalse();
+ }
+ }).verifyComplete();
+ }
+ }
}
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerIntegrationTest.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerIntegrationTest.java
new file mode 100644
index 0000000000..eee4e7b860
--- /dev/null
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerIntegrationTest.java
@@ -0,0 +1,112 @@
+package com.baeldung.spring.cloud.client;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.client.DefaultServiceInstance;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.loadbalancer.Response;
+import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
+import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
+import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
+import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
+import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
+import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
+import org.springframework.cloud.loadbalancer.support.ServiceInstanceListSuppliers;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+@SpringBootTest
+@EnableFeignClients
+@EnableConfigurationProperties
+@ExtendWith(SpringExtension.class)
+@ActiveProfiles("test")
+@ContextConfiguration(classes = { TestConfig.class })
+class LoadBalancerIntegrationTest {
+
+ @Autowired
+ private LoadBalancerClientFactory clientFactory;
+
+ @Autowired
+ private BooksClient booksClient;
+
+ @Autowired
+ private WireMockServer mockBooksService;
+
+ @Autowired
+ private WireMockServer secondMockBooksService;
+
+ private void assertLoadBalancer(ReactorLoadBalancer loadBalancer, List hosts) {
+ for (String host : hosts) {
+ Mono> source = loadBalancer.choose();
+ StepVerifier.create(source).consumeNextWith(response -> {
+ then(response).isNotNull();
+ then(response.hasServer()).isTrue();
+
+ ServiceInstance instance = response.getServer();
+ then(instance).isNotNull();
+ then(instance.getHost()).as("instance host is incorrect %s", host).isEqualTo(host);
+
+ if (host.contains("secure")) {
+ then(instance.isSecure()).isTrue();
+ }
+ else {
+ then(instance.isSecure()).isFalse();
+ }
+ }).verifyComplete();
+ }
+ }
+
+ @Test
+ void staticConfigurationWorks() {
+ String serviceId = "test-book-service";
+ RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(ServiceInstanceListSuppliers
+ .toProvider(serviceId, instance(serviceId, "bookservice1", false), instance(serviceId, "bookservice2", false)),
+ serviceId, -1);
+ assertLoadBalancer(loadBalancer, Arrays.asList("bookservice1", "bookservice2"));
+ }
+
+ private static DefaultServiceInstance instance(String serviceId, String host, boolean secure) {
+ return new DefaultServiceInstance(serviceId, serviceId, host, 80, secure);
+ }
+
+ @EnableAutoConfiguration
+ @SpringBootConfiguration(proxyBeanMethods = false)
+ @LoadBalancerClients({ @LoadBalancerClient(name = "books-service", configuration = MyBooksServiceConfig.class) })
+ @EnableCaching
+ protected static class Config {
+
+ }
+
+ protected static class MyBooksServiceConfig {
+
+ @Bean
+ public RoundRobinLoadBalancer roundRobinContextLoadBalancer(LoadBalancerClientFactory clientFactory,
+ Environment env) {
+ String serviceId = LoadBalancerClientFactory.getName(env);
+ return new RoundRobinLoadBalancer(
+ clientFactory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class), serviceId, -1);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/RibbonTestConfig.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/RibbonTestConfig.java
deleted file mode 100644
index 273ba182b1..0000000000
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/RibbonTestConfig.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.baeldung.spring.cloud.client;
-
-import com.github.tomakehurst.wiremock.WireMockServer;
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.ServerList;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.cloud.netflix.ribbon.StaticServerList;
-import org.springframework.context.annotation.Bean;
-import org.springframework.test.context.ActiveProfiles;
-
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
-
-@TestConfiguration
-@ActiveProfiles("ribbon-test")
-public class RibbonTestConfig {
-
- @Autowired
- private WireMockServer mockBooksService;
-
- @Autowired
- private WireMockServer secondMockBooksService;
-
- @Bean(initMethod = "start", destroyMethod = "stop")
- public WireMockServer mockBooksService() {
- return new WireMockServer(options().dynamicPort());
- }
-
- @Bean(name="secondMockBooksService", initMethod = "start", destroyMethod = "stop")
- public WireMockServer secondBooksMockService() {
- return new WireMockServer(options().dynamicPort());
- }
-
- @Bean
- public ServerList ribbonServerList() {
- return new StaticServerList<>(
- new Server("localhost", mockBooksService.port()),
- new Server("localhost", secondMockBooksService.port()));
- }
-
-}
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/TestConfig.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/TestConfig.java
new file mode 100644
index 0000000000..b3770721b1
--- /dev/null
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/TestConfig.java
@@ -0,0 +1,24 @@
+package com.baeldung.spring.cloud.client;
+
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.context.ActiveProfiles;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+
+@TestConfiguration
+@ActiveProfiles("test")
+public class TestConfig {
+
+ @Bean(initMethod = "start", destroyMethod = "stop")
+ public WireMockServer mockBooksService() {
+ return new WireMockServer(options().port(80));
+ }
+
+ @Bean(name="secondMockBooksService", initMethod = "start", destroyMethod = "stop")
+ public WireMockServer secondBooksMockService() {
+ return new WireMockServer(options().port(81));
+ }
+}
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java
index 82b7cddede..3d4f2822f4 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java
@@ -11,7 +11,11 @@ public class WireMockConfig {
@Bean(initMethod = "start", destroyMethod = "stop")
public WireMockServer mockBooksService() {
- return new WireMockServer(9561);
+ return new WireMockServer(80);
}
+ @Bean(initMethod = "start", destroyMethod = "stop")
+ public WireMockServer mockBooksService2() {
+ return new WireMockServer(81);
+ }
}
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-ribbon-test.yml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-ribbon-test.yml
deleted file mode 100644
index 84a78d0ec7..0000000000
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-ribbon-test.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-eureka:
- client:
- enabled: false
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-spring-cloud-balancer-test.yml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-spring-cloud-balancer-test.yml
new file mode 100644
index 0000000000..ad11d46ae8
--- /dev/null
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-spring-cloud-balancer-test.yml
@@ -0,0 +1,19 @@
+eureka:
+ client:
+ enabled: false
+
+spring:
+ application:
+ name: books-service
+ cloud:
+ loadbalancer:
+ ribbon:
+ enabled: false
+ discovery:
+ client:
+ simple:
+ instances:
+ books-service[0]:
+ uri: http://localhost:80
+ books-service[1]:
+ uri: http://localhost:81
\ No newline at end of file
diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml
index dce11adf69..231d45004f 100644
--- a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml
+++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml
@@ -1,11 +1,19 @@
-#book:
-# service:
-# url: http://localhost:9561
-
-books-service:
- ribbon:
- listOfServers: http://localhost:9561
-
eureka:
client:
enabled: false
+
+spring:
+ application:
+ name: books-service
+ cloud:
+ loadbalancer:
+ ribbon:
+ enabled: false
+ discovery:
+ client:
+ simple:
+ instances:
+ books-service[0]:
+ uri: http://localhost:80
+ books-service[1]:
+ uri: http://localhost:81
diff --git a/spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java b/spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java
index a3c5445698..aa526b5403 100644
--- a/spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java
+++ b/spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java
@@ -7,7 +7,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.baeldung.scope.prototype.PrototypeBean;
-import com.baeldung.scope.singletone.SingletonFunctionBean;
+import com.baeldung.scope.singleton.SingletonFunctionBean;
@Configuration
public class AppConfigFunctionBean {
diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java
index 33a9c5c21e..2ef775ee4f 100644
--- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java
+++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java
@@ -1,10 +1,10 @@
package com.baeldung.scope;
import com.baeldung.scope.prototype.PrototypeBean;
-import com.baeldung.scope.singletone.SingletonAppContextBean;
-import com.baeldung.scope.singletone.SingletonBean;
-import com.baeldung.scope.singletone.SingletonObjectFactoryBean;
-import com.baeldung.scope.singletone.SingletonProviderBean;
+import com.baeldung.scope.singleton.SingletonAppContextBean;
+import com.baeldung.scope.singleton.SingletonBean;
+import com.baeldung.scope.singleton.SingletonObjectFactoryBean;
+import com.baeldung.scope.singleton.SingletonProviderBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
diff --git a/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java
index 9f1874375e..0564dfb3c0 100644
--- a/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java
+++ b/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java
@@ -1,7 +1,7 @@
package com.baeldung.scope;
import com.baeldung.scope.prototype.PrototypeBean;
-import com.baeldung.scope.singletone.SingletonBean;
+import com.baeldung.scope.singleton.SingletonBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
diff --git a/spring-core/src/main/java/com/baeldung/scope/BeanInjectionStarter.java b/spring-core/src/main/java/com/baeldung/scope/BeanInjectionStarter.java
index 5cf0c9170c..47014aa2d1 100644
--- a/spring-core/src/main/java/com/baeldung/scope/BeanInjectionStarter.java
+++ b/spring-core/src/main/java/com/baeldung/scope/BeanInjectionStarter.java
@@ -1,7 +1,7 @@
package com.baeldung.scope;
import com.baeldung.scope.prototype.PrototypeBean;
-import com.baeldung.scope.singletone.SingletonBean;
+import com.baeldung.scope.singleton.SingletonBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.Assert;
diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonAppContextBean.java b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonAppContextBean.java
similarity index 94%
rename from spring-core/src/main/java/com/baeldung/scope/singletone/SingletonAppContextBean.java
rename to spring-core/src/main/java/com/baeldung/scope/singleton/SingletonAppContextBean.java
index f4d57a0f63..4f5b3274c8 100644
--- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonAppContextBean.java
+++ b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonAppContextBean.java
@@ -1,4 +1,4 @@
-package com.baeldung.scope.singletone;
+package com.baeldung.scope.singleton;
import com.baeldung.scope.prototype.PrototypeBean;
import org.springframework.beans.BeansException;
diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonBean.java b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonBean.java
similarity index 93%
rename from spring-core/src/main/java/com/baeldung/scope/singletone/SingletonBean.java
rename to spring-core/src/main/java/com/baeldung/scope/singleton/SingletonBean.java
index 8d3a09b8fd..9c4cea4439 100644
--- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonBean.java
+++ b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonBean.java
@@ -1,4 +1,4 @@
-package com.baeldung.scope.singletone;
+package com.baeldung.scope.singleton;
import com.baeldung.scope.prototype.PrototypeBean;
import org.apache.log4j.Logger;
diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonFunctionBean.java
similarity index 91%
rename from spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java
rename to spring-core/src/main/java/com/baeldung/scope/singleton/SingletonFunctionBean.java
index 8cdc56a6fa..2788af1701 100644
--- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java
+++ b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonFunctionBean.java
@@ -1,4 +1,4 @@
-package com.baeldung.scope.singletone;
+package com.baeldung.scope.singleton;
import java.util.function.Function;
diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonLookupBean.java b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonLookupBean.java
similarity index 88%
rename from spring-core/src/main/java/com/baeldung/scope/singletone/SingletonLookupBean.java
rename to spring-core/src/main/java/com/baeldung/scope/singleton/SingletonLookupBean.java
index 4c3c9b69da..e5461826ef 100644
--- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonLookupBean.java
+++ b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonLookupBean.java
@@ -1,4 +1,4 @@
-package com.baeldung.scope.singletone;
+package com.baeldung.scope.singleton;
import com.baeldung.scope.prototype.PrototypeBean;
import org.springframework.beans.factory.annotation.Lookup;
diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonObjectFactoryBean.java b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonObjectFactoryBean.java
similarity index 91%
rename from spring-core/src/main/java/com/baeldung/scope/singletone/SingletonObjectFactoryBean.java
rename to spring-core/src/main/java/com/baeldung/scope/singleton/SingletonObjectFactoryBean.java
index 55a91f8202..0e70d12e6e 100644
--- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonObjectFactoryBean.java
+++ b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonObjectFactoryBean.java
@@ -1,4 +1,4 @@
-package com.baeldung.scope.singletone;
+package com.baeldung.scope.singleton;
import com.baeldung.scope.prototype.PrototypeBean;
import org.springframework.beans.factory.ObjectFactory;
diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonProviderBean.java b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonProviderBean.java
similarity index 90%
rename from spring-core/src/main/java/com/baeldung/scope/singletone/SingletonProviderBean.java
rename to spring-core/src/main/java/com/baeldung/scope/singleton/SingletonProviderBean.java
index 37d0ad9404..01a4a0ff11 100644
--- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonProviderBean.java
+++ b/spring-core/src/main/java/com/baeldung/scope/singleton/SingletonProviderBean.java
@@ -1,4 +1,4 @@
-package com.baeldung.scope.singletone;
+package com.baeldung.scope.singleton;
import com.baeldung.scope.prototype.PrototypeBean;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java
index d0c2733765..df04957992 100644
--- a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java
+++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java
@@ -1,10 +1,9 @@
package com.baeldung.scope;
import com.baeldung.scope.prototype.PrototypeBean;
-import com.baeldung.scope.singletone.SingletonFunctionBean;
-import com.baeldung.scope.singletone.SingletonLookupBean;
-import com.baeldung.scope.singletone.SingletonObjectFactoryBean;
-import com.baeldung.scope.singletone.SingletonProviderBean;
+import com.baeldung.scope.singleton.SingletonLookupBean;
+import com.baeldung.scope.singleton.SingletonObjectFactoryBean;
+import com.baeldung.scope.singleton.SingletonProviderBean;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java
index 1e3c652599..dac3461ceb 100644
--- a/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java
+++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java
@@ -11,7 +11,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
import com.baeldung.config.scope.AppConfigFunctionBean;
import com.baeldung.scope.prototype.PrototypeBean;
-import com.baeldung.scope.singletone.SingletonFunctionBean;
+import com.baeldung.scope.singleton.SingletonFunctionBean;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = AppConfigFunctionBean.class)
diff --git a/spring-kafka-2/README.md b/spring-kafka-2/README.md
index d71e75f15c..318312ace6 100644
--- a/spring-kafka-2/README.md
+++ b/spring-kafka-2/README.md
@@ -7,3 +7,4 @@ This module contains articles about Spring with Kafka
- [Implementing Retry in Kafka Consumer](https://www.baeldung.com/spring-retry-kafka-consumer)
- [Spring Kafka: Configure Multiple Listeners on Same Topic](https://www.baeldung.com/spring-kafka-multiple-listeners-same-topic)
- [Understanding Kafka Topics and Partitions](https://www.baeldung.com/kafka-topics-partitions)
+- [How to Subscribe a Kafka Consumer to Multiple Topics](https://www.baeldung.com/kafka-subscribe-consumer-multiple-topics)