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-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-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-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-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-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-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-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-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 ae9ff59222..5b37db6e1a 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -158,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 @@ -165,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/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-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-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-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)