From c96199e4a52a8769b9b8d7f4352707e9a0de08de Mon Sep 17 00:00:00 2001 From: panos-kakos Date: Wed, 5 Jul 2023 08:38:36 +0300 Subject: [PATCH 01/16] [JAVA-22456] Upgraded aws-s3 module to aws-sdk 2.20.52 --- aws-modules/aws-s3/pom.xml | 12 +- .../com/baeldung/s3/AWSS3ObjectUtils.java | 42 --- .../java/com/baeldung/s3/AWSS3Service.java | 93 ------- .../java/com/baeldung/s3/MultipartUpload.java | 115 ++++++--- .../java/com/baeldung/s3/S3Application.java | 114 +++------ .../main/java/com/baeldung/s3/S3Service.java | 241 ++++++++++++++++++ .../com/baeldung/jets3t/JetS3tLiveTest.java | 49 ++-- .../baeldung/s3/AWSS3ObjectManualTest.java | 49 ---- .../s3/AWSS3ServiceIntegrationTest.java | 113 -------- .../baeldung/s3/MultipartUploadLiveTest.java | 61 ----- .../baeldung/s3/S3ServiceIntegrationTest.java | 137 ++++++++++ .../com/baeldung/s3/S3ServiceManualTest.java | 51 ++++ 12 files changed, 579 insertions(+), 498 deletions(-) delete mode 100644 aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java delete mode 100644 aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java create mode 100644 aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java delete mode 100644 aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java delete mode 100644 aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java delete mode 100644 aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java create mode 100644 aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java create mode 100644 aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java diff --git a/aws-modules/aws-s3/pom.xml b/aws-modules/aws-s3/pom.xml index 0ea99588d8..157aeb671d 100644 --- a/aws-modules/aws-s3/pom.xml +++ b/aws-modules/aws-s3/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 aws-s3 0.1.0-SNAPSHOT @@ -16,10 +16,11 @@ - com.amazonaws - aws-java-sdk - ${aws-java-sdk.version} + software.amazon.awssdk + s3 + ${aws.java.sdk.version} + commons-io commons-io @@ -60,6 +61,7 @@ + 2.20.52 1.10.L001 0.9.4.0006L diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java deleted file mode 100644 index 1c31218ff9..0000000000 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.s3; - -import org.apache.http.HttpStatus; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.s3.AmazonS3; - -public class AWSS3ObjectUtils { - - private AmazonS3 s3Client; - - public AWSS3ObjectUtils(AmazonS3 s3client) { - this.s3Client = s3client; - } - - public boolean doesObjectExistByDefaultMethod(String bucket, String key) { - return s3Client.doesObjectExist(bucket, key); - } - - public boolean doesObjectExistByListObjects(String bucket, String key) { - return s3Client.listObjects(bucket) - .getObjectSummaries() - .stream() - .filter(s3ObjectSummary -> s3ObjectSummary.getKey() - .equals(key)) - .findFirst() - .isPresent(); - } - - public boolean doesObjectExistByMetaData(String bucket, String key) { - try { - s3Client.getObjectMetadata(bucket, key); - return true; - } catch (AmazonServiceException e) { - if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { - return false; - } else { - throw e; - } - } - } -} \ No newline at end of file diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java deleted file mode 100644 index 64ed043f98..0000000000 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.baeldung.s3; - -import java.io.File; -import java.net.URL; -import java.util.List; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.Bucket; -import com.amazonaws.services.s3.model.CopyObjectResult; -import com.amazonaws.services.s3.model.DeleteObjectsRequest; -import com.amazonaws.services.s3.model.DeleteObjectsResult; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.model.S3Object; - -public class AWSS3Service { - private final AmazonS3 s3client; - - public AWSS3Service() { - this(new AmazonS3Client() { - }); - } - - public AWSS3Service(AmazonS3 s3client) { - this.s3client = s3client; - } - - //is bucket exist? - public boolean doesBucketExist(String bucketName) { - return s3client.doesBucketExist(bucketName); - } - - //create a bucket - public Bucket createBucket(String bucketName) { - return s3client.createBucket(bucketName); - } - - //list all buckets - public List listBuckets() { - return s3client.listBuckets(); - } - - //delete a bucket - public void deleteBucket(String bucketName) { - s3client.deleteBucket(bucketName); - } - - //uploading object - public PutObjectResult putObject(String bucketName, String key, File file) { - return s3client.putObject(bucketName, key, file); - } - //uploading object and getting url - public URL getObjectURL(String bucketName, String key, File file) { - s3client.putObject(bucketName, key, file); - return s3client.getUrl(bucketName, key); - } - - //listing objects - public ObjectListing listObjects(String bucketName) { - return s3client.listObjects(bucketName); - } - - //get an object - public S3Object getObject(String bucketName, String objectKey) { - return s3client.getObject(bucketName, objectKey); - } - - //copying an object - public CopyObjectResult copyObject( - String sourceBucketName, - String sourceKey, - String destinationBucketName, - String destinationKey - ) { - return s3client.copyObject( - sourceBucketName, - sourceKey, - destinationBucketName, - destinationKey - ); - } - - //deleting an object - public void deleteObject(String bucketName, String objectKey) { - s3client.deleteObject(bucketName, objectKey); - } - - //deleting multiple Objects - public DeleteObjectsResult deleteObjects(DeleteObjectsRequest delObjReq) { - return s3client.deleteObjects(delObjReq); - } -} diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java index 711046c112..de45238994 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java @@ -1,56 +1,101 @@ package com.baeldung.s3; -import com.amazonaws.AmazonClientException; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; -import com.amazonaws.event.ProgressListener; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.transfer.TransferManager; -import com.amazonaws.services.s3.transfer.TransferManagerBuilder; -import com.amazonaws.services.s3.transfer.Upload; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.model.*; -import java.io.File; -import java.util.concurrent.Executors; public class MultipartUpload { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { String existingBucketName = "baeldung-bucket"; String keyName = "my-picture.jpg"; String filePath = "documents/my-picture.jpg"; - AmazonS3 amazonS3 = AmazonS3ClientBuilder - .standard() - .withCredentials(new DefaultAWSCredentialsProviderChain()) - .withRegion(Regions.DEFAULT_REGION) - .build(); + ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create(); + Region region = Region.US_EAST_1; + S3Client s3 = S3Client.builder() + .region(region) + .credentialsProvider(credentialsProvider) + .build(); - int maxUploadThreads = 5; + // Initiate a multipart upload + CreateMultipartUploadRequest createRequest = CreateMultipartUploadRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .build(); - TransferManager tm = TransferManagerBuilder - .standard() - .withS3Client(amazonS3) - .withMultipartUploadThreshold((long) (5 * 1024 * 1024)) - .withExecutorFactory(() -> Executors.newFixedThreadPool(maxUploadThreads)) - .build(); + CreateMultipartUploadResponse createResponse = s3.createMultipartUpload(createRequest); - ProgressListener progressListener = - progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred()); + String uploadId = createResponse.uploadId(); - PutObjectRequest request = new PutObjectRequest(existingBucketName, keyName, new File(filePath)); + // Prepare the parts to be uploaded + List completedParts = new ArrayList<>(); + int partNumber = 1; + ByteBuffer buffer = ByteBuffer.allocate(5 * 1024 * 1024); // Set your preferred part size (5 MB in this example) - request.setGeneralProgressListener(progressListener); + // Read the file and upload each part + try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) { + long fileSize = file.length(); + long position = 0; - Upload upload = tm.upload(request); + while (position < fileSize) { + file.seek(position); + int bytesRead = file.getChannel().read(buffer); - try { - upload.waitForCompletion(); - System.out.println("Upload complete."); - } catch (AmazonClientException e) { - System.out.println("Error occurred while uploading file"); + buffer.flip(); + UploadPartRequest uploadPartRequest = UploadPartRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .uploadId(uploadId) + .partNumber(partNumber) + .contentLength((long) bytesRead) + .build(); + + UploadPartResponse response = s3.uploadPart(uploadPartRequest, RequestBody.fromByteBuffer(buffer)); + + completedParts.add(CompletedPart.builder() + .partNumber(partNumber) + .eTag(response.eTag()) + .build()); + + buffer.clear(); + position += bytesRead; + partNumber++; + } + } catch (IOException e) { e.printStackTrace(); } + + // Complete the multipart upload + CompletedMultipartUpload completedUpload = CompletedMultipartUpload.builder() + .parts(completedParts) + .build(); + + CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .uploadId(uploadId) + .multipartUpload(completedUpload) + .build(); + + CompleteMultipartUploadResponse completeResponse = s3.completeMultipartUpload(completeRequest); + + // Print the object's URL + String objectUrl = s3.utilities().getUrl(GetUrlRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .build()) + .toExternalForm(); + + System.out.println("Uploaded object URL: " + objectUrl); } } \ No newline at end of file diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java index 39a9b0050f..1ce2f9cbb5 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java @@ -1,104 +1,60 @@ package com.baeldung.s3; import java.io.File; -import java.io.IOException; +import java.util.List; -import org.apache.commons.io.FileUtils; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.Bucket; -import com.amazonaws.services.s3.model.DeleteObjectsRequest; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectInputStream; -import com.amazonaws.services.s3.model.S3ObjectSummary; +import software.amazon.awssdk.regions.Region; public class S3Application { - private static final AWSCredentials credentials; - private static String bucketName; + private static String AWS_BUCKET = "baeldung-tutorial-s3"; + public static Region AWS_REGION = Region.EU_CENTRAL_1; - static { - //put your accesskey and secretkey here - credentials = new BasicAWSCredentials( - "", - "" - ); - } - - public static void main(String[] args) throws IOException { - //set-up the client - AmazonS3 s3client = AmazonS3ClientBuilder - .standard() - .withCredentials(new AWSStaticCredentialsProvider(credentials)) - .withRegion(Regions.US_EAST_2) - .build(); - - AWSS3Service awsService = new AWSS3Service(s3client); - - bucketName = "baeldung-bucket"; + public static void main(String[] args) { + S3Service s3Service = new S3Service(AWS_REGION); //creating a bucket - if(awsService.doesBucketExist(bucketName)) { + s3Service.createBucket(AWS_BUCKET); + + //check if a bucket exists + if(s3Service.doesBucketExist(AWS_BUCKET)) { System.out.println("Bucket name is not available." - + " Try again with a different Bucket name."); + + " Try again with a different Bucket name."); return; } - awsService.createBucket(bucketName); - - //list all the buckets - for(Bucket s : awsService.listBuckets() ) { - System.out.println(s.getName()); - } - - //deleting bucket - awsService.deleteBucket("baeldung-bucket-test2"); - - //uploading object - awsService.putObject( - bucketName, - "Document/hello.txt", - new File("/Users/user/Document/hello.txt") - ); - //uploading object and getting url - awsService.getObjectURL(bucketName, "Document/hello.txt", new File("/Users/user/Document/hello.txt")); + //list all the buckets + s3Service.listBuckets(); + + //deleting bucket + s3Service.deleteBucket("baeldung-bucket-test2"); + + //uploading object + s3Service.putObject( + AWS_BUCKET, + "Document/hello.txt", + new File("/Users/user/Document/hello.txt") + ); //listing objects - ObjectListing objectListing = awsService.listObjects(bucketName); - for(S3ObjectSummary os : objectListing.getObjectSummaries()) { - System.out.println(os.getKey()); - } + s3Service.listObjects(AWS_BUCKET); //downloading an object - S3Object s3object = awsService.getObject(bucketName, "Document/hello.txt"); - S3ObjectInputStream inputStream = s3object.getObjectContent(); - FileUtils.copyInputStreamToFile(inputStream, new File("/Users/user/Desktop/hello.txt")); - + s3Service.getObject(AWS_BUCKET, "Document/hello.txt"); + //copying an object - awsService.copyObject( - "baeldung-bucket", - "picture/pic.png", - "baeldung-bucket2", - "Document/picture.png" + s3Service.copyObject( + "baeldung-bucket", + "picture/pic.png", + "baeldung-bucket2", + "Document/picture.png" ); - + //deleting an object - awsService.deleteObject(bucketName, "Document/hello.txt"); + s3Service.deleteObject(AWS_BUCKET, "Document/hello.txt"); //deleting multiple objects - String objkeyArr[] = { - "Document/hello2.txt", - "Document/picture.png" - }; - - DeleteObjectsRequest delObjReq = new DeleteObjectsRequest("baeldung-bucket") - .withKeys(objkeyArr); - awsService.deleteObjects(delObjReq); + List objKeyList = List.of("Document/hello2.txt", "Document/picture.png"); + s3Service.deleteObjects(AWS_BUCKET, objKeyList); } } diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java new file mode 100644 index 0000000000..361e7e83b0 --- /dev/null +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java @@ -0,0 +1,241 @@ +package com.baeldung.s3; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.Bucket; +import software.amazon.awssdk.services.s3.model.CopyObjectRequest; +import software.amazon.awssdk.services.s3.model.CopyObjectResponse; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; +import software.amazon.awssdk.services.s3.model.Delete; +import software.amazon.awssdk.services.s3.model.DeleteBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.HeadObjectRequest; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; +import software.amazon.awssdk.services.s3.model.NoSuchBucketException; +import software.amazon.awssdk.services.s3.model.ObjectIdentifier; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.model.S3Object; +import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; + +class S3Service { + + private S3Client s3Client; + + public S3Service(Region awsRegion) { + init(awsRegion); + } + + public S3Service(S3Client s3Client) { + this.s3Client = s3Client; + } + + public void init(Region awsRegion) { + this.s3Client = S3Client.builder() + .region(awsRegion) + .credentialsProvider(ProfileCredentialsProvider.create("default")) + .build(); + } + + //is bucket exist? + public boolean doesBucketExist(String bucketName) { + HeadBucketRequest headBucketRequest = HeadBucketRequest.builder() + .bucket(bucketName) + .build(); + + try { + s3Client.headBucket(headBucketRequest); + return true; + } catch (NoSuchBucketException e) { + return false; + } + } + + //create a bucket + public void createBucket(String bucketName) { + CreateBucketRequest bucketRequest = CreateBucketRequest.builder() + .bucket(bucketName) + .build(); + + s3Client.createBucket(bucketRequest); + } + + //delete a bucket + public void deleteBucket(String bucketName) { + try { + DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder() + .bucket(bucketName) + .build(); + + s3Client.deleteBucket(deleteBucketRequest); + System.out.println("Successfully deleted bucket : " + bucketName); + } catch (S3Exception e) { + System.err.println(e.getMessage()); + System.exit(1); + } + } + + //uploading object + public PutObjectResponse putObject(String bucketName, String key, java.io.File file) { + PutObjectRequest request = PutObjectRequest.builder() + .bucket(bucketName) + .key(key) + .build(); + + return s3Client.putObject(request, Path.of(file.toURI()) ); + } + + //listing objects + public void listObjects(String bucketName) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .build(); + ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); + + for(S3Object os : listObjectsV2Response.contents()) { + System.out.println(os.key()); + } + } + + //get an object + public void getObject(String bucketName, String objectKey) { + try { + GetObjectRequest objectRequest = GetObjectRequest.builder() + .bucket(bucketName) + .key(objectKey) + .build(); + + ResponseBytes responseResponseBytes = s3Client.getObjectAsBytes(objectRequest); + + byte[] data = responseResponseBytes.asByteArray(); + + // Write the data to a local file. + java.io.File myFile = new java.io.File("/Users/user/Desktop/hello.txt" ); + OutputStream os = new FileOutputStream(myFile); + os.write(data); + System.out.println("Successfully obtained bytes from an S3 object"); + os.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } catch (S3Exception e) { + System.err.println(e.awsErrorDetails().errorMessage()); + System.exit(1); + } + } + + //copying an object + public CopyObjectResponse copyObject( + String sourceBucketName, + String sourceKey, + String destinationBucketName, + String destinationKey + ) { + CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder() + .sourceBucket(sourceBucketName) + .sourceKey(sourceKey) + .destinationBucket(destinationBucketName) + .destinationKey(destinationKey) + .build(); + + return s3Client.copyObject(copyObjectRequest); + } + + //deleting an object + public void deleteObject(String bucketName, String objectKey) { + DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder() + .bucket(bucketName) + .key(objectKey) + .build(); + + s3Client.deleteObject(deleteObjectRequest); + } + + //deleting multiple Objects + public void deleteObjects(String bucketName, List keys ) { + + ArrayList toDelete = new ArrayList<>(); + for(String objKey : keys) { + toDelete.add(ObjectIdentifier.builder() + .key(objKey) + .build()); + } + + DeleteObjectsRequest deleteObjectRequest = DeleteObjectsRequest.builder() + .bucket(bucketName) + .delete(Delete.builder() + .objects(toDelete).build()) + .build(); + + s3Client.deleteObjects(deleteObjectRequest); + } + + public boolean doesObjectExistByListObjects(String bucketName, String key) { + + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .build(); + ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); + + return listObjectsV2Response.contents() + .stream() + .filter(s3ObjectSummary -> s3ObjectSummary.getValueForField("key", String.class) + .equals(key)) + .findFirst() + .isPresent(); + } + + public boolean doesObjectExistByDefaultMethod(String bucket, String key) { + try { + HeadObjectRequest headObjectRequest = HeadObjectRequest.builder() + .bucket(bucket) + .key(key) + .build(); + + s3Client.headObject(headObjectRequest); + + System.out.println("Object exists"); + return true; + } catch (S3Exception e) { + if (e.statusCode() == 404) { + System.out.println("Object does not exist"); + return false; + } else { + throw e; + } + } + } + + public void listBuckets() { + // List all buckets + ListBucketsResponse listBucketsResponse = s3Client.listBuckets(); + + // Display the bucket names + List buckets = listBucketsResponse.buckets(); + System.out.println("Buckets:"); + for (Bucket bucket : buckets) { + System.out.println(bucket.name()); + } + } + + public void cleanup() { + this.s3Client.close(); + } + +} \ No newline at end of file diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java index cf0b203e10..cad7da6cc9 100644 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java @@ -1,5 +1,13 @@ package com.baeldung.jets3t; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -10,8 +18,8 @@ import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Object; import org.jets3t.service.model.StorageObject; import org.jets3t.service.security.AWSCredentials; -import org.junit.BeforeClass; -import org.junit.Test; + + import java.io.*; import java.nio.file.Files; @@ -19,14 +27,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.stream.Collectors; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static junit.framework.TestCase.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; + + + public class JetS3tLiveTest { - private Log log = LogFactory.getLog(JetS3tLiveTest.class); + private final Log log = LogFactory.getLog(JetS3tLiveTest.class); private static final String BucketName = "baeldung-barfoo"; private static final String TestString = "test string"; @@ -35,7 +42,7 @@ public class JetS3tLiveTest { private static S3Service s3Service; - @BeforeClass + @BeforeAll public static void connectS3() throws Exception { // Replace with your keys @@ -50,7 +57,7 @@ public class JetS3tLiveTest { } @Test - public void givenCreate_AndDeleteBucket_CountGoesUpThenDown() throws Exception { + void givenCreate_AndDeleteBucket_CountGoesUpThenDown() throws Exception { // List buckets, get a count S3Bucket[] myBuckets = s3Service.listAllBuckets(); @@ -89,7 +96,7 @@ public class JetS3tLiveTest { } @Test - public void givenString_Uploaded_StringInfoIsAvailable() throws Exception { + void givenString_Uploaded_StringInfoIsAvailable() throws Exception { // Create a bucket S3Bucket bucket = createBucket(); @@ -120,7 +127,7 @@ public class JetS3tLiveTest { } @Test - public void givenStringUploaded_StringIsDownloaded() throws Exception { + void givenStringUploaded_StringIsDownloaded() throws Exception { // Get a bucket S3Bucket bucket = createBucket(); @@ -135,7 +142,7 @@ public class JetS3tLiveTest { String downloadedString = new BufferedReader(new InputStreamReader(stringObject.getDataInputStream())).lines().collect(Collectors.joining("\n")); // Verify - assertTrue(TestString.equals(downloadedString)); + assertEquals(TestString, downloadedString); // Clean up for next test @@ -144,7 +151,7 @@ public class JetS3tLiveTest { } @Test - public void givenBinaryFileUploaded_FileIsDownloaded() throws Exception { + void givenBinaryFileUploaded_FileIsDownloaded() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -169,7 +176,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/newtest.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteObject("test.jpg"); @@ -186,7 +193,7 @@ public class JetS3tLiveTest { @Test - public void givenStreamDataUploaded_StreamDataIsDownloaded() throws Exception { + void givenStreamDataUploaded_StreamDataIsDownloaded() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -233,7 +240,7 @@ public class JetS3tLiveTest { } @Test - public void whenFileCopied_CopyIsSame() throws Exception { + void whenFileCopied_CopyIsSame() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -260,7 +267,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/testcopy.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteObject("test.jpg"); @@ -271,7 +278,7 @@ public class JetS3tLiveTest { @Test - public void whenFileRenamed_NewNameIsSame() throws Exception { + void whenFileRenamed_NewNameIsSame() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -297,7 +304,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/spidey.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteObject("test.jpg"); @@ -307,7 +314,7 @@ public class JetS3tLiveTest { } @Test - public void whenFileMoved_NewInstanceIsSame() throws Exception { + void whenFileMoved_NewInstanceIsSame() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -338,7 +345,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/spidey.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteBucket(); diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java deleted file mode 100644 index 02cc22367a..0000000000 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.s3; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -import com.amazonaws.auth.EnvironmentVariableCredentialsProvider; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; - -/** - * Required defined environment variables AWS_ACCESS_KEY_ID & AWS_ACCESS_KEY to access S3. - * Required S3 bucket and key that exist. - */ - -public class AWSS3ObjectManualTest { - - private static final String BUCKET = "your-bucket"; - private static final String KEY_THAT_EXIST = "your-key-that-exist"; - private AWSS3ObjectUtils s3ObjectUtils; - - @Before - public void setUp() { - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withRegion(Regions.DEFAULT_REGION) - .withCredentials(new EnvironmentVariableCredentialsProvider()) - .build(); - - s3ObjectUtils = new AWSS3ObjectUtils(client); - } - - @Test - public void whenVerifyIfObjectExistByDefaultMethod_thenCorrect() { - assertTrue(s3ObjectUtils.doesObjectExistByDefaultMethod(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist"); - - } - - @Test - public void whenVerifyIfObjectExistByListObjects_thenCorrect() { - assertTrue(s3ObjectUtils.doesObjectExistByListObjects(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist"); - } - - @Test - public void whenVerifyIfObjectExistByMetaData_thenCorrect() { - assertTrue(s3ObjectUtils.doesObjectExistByMetaData(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist"); - } -} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java deleted file mode 100644 index d386704513..0000000000 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.baeldung.s3; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; - -import org.junit.Before; -import org.junit.Test; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CopyObjectResult; -import com.amazonaws.services.s3.model.DeleteObjectsRequest; -import com.amazonaws.services.s3.model.DeleteObjectsResult; -import com.amazonaws.services.s3.model.PutObjectResult; - -public class AWSS3ServiceIntegrationTest { - - private static final String BUCKET_NAME = "bucket_name"; - private static final String KEY_NAME = "key_name"; - private static final String BUCKET_NAME2 = "bucket_name2"; - private static final String KEY_NAME2 = "key_name2"; - - private AmazonS3 s3; - private AWSS3Service service; - - @Before - public void setUp() { - s3 = mock(AmazonS3.class); - service = new AWSS3Service(s3); - } - - @Test - public void whenInitializingAWSS3Service_thenNotNull() { - assertThat(new AWSS3Service()).isNotNull(); - } - - @Test - public void whenVerifyingIfS3BucketExist_thenCorrect() { - service.doesBucketExist(BUCKET_NAME); - verify(s3).doesBucketExist(BUCKET_NAME); - } - - @Test - public void whenVerifyingCreationOfS3Bucket_thenCorrect() { - service.createBucket(BUCKET_NAME); - verify(s3).createBucket(BUCKET_NAME); - } - - @Test - public void whenVerifyingListBuckets_thenCorrect() { - service.listBuckets(); - verify(s3).listBuckets(); - } - - @Test - public void whenDeletingBucket_thenCorrect() { - service.deleteBucket(BUCKET_NAME); - verify(s3).deleteBucket(BUCKET_NAME); - } - - @Test - public void whenVerifyingPutObject_thenCorrect() { - File file = mock(File.class); - PutObjectResult result = mock(PutObjectResult.class); - when(s3.putObject(anyString(), anyString(), (File) any())).thenReturn(result); - - assertThat(service.putObject(BUCKET_NAME, KEY_NAME, file)).isEqualTo(result); - verify(s3).putObject(BUCKET_NAME, KEY_NAME, file); - } - - @Test - public void whenVerifyingListObjects_thenCorrect() { - service.listObjects(BUCKET_NAME); - verify(s3).listObjects(BUCKET_NAME); - } - - @Test - public void whenVerifyingGetObject_thenCorrect() { - service.getObject(BUCKET_NAME, KEY_NAME); - verify(s3).getObject(BUCKET_NAME, KEY_NAME); - } - - @Test - public void whenVerifyingCopyObject_thenCorrect() { - CopyObjectResult result = mock(CopyObjectResult.class); - when(s3.copyObject(anyString(), anyString(), anyString(), anyString())).thenReturn(result); - - assertThat(service.copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2)).isEqualTo(result); - verify(s3).copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2); - } - - @Test - public void whenVerifyingDeleteObject_thenCorrect() { - service.deleteObject(BUCKET_NAME, KEY_NAME); - verify(s3).deleteObject(BUCKET_NAME, KEY_NAME); - } - - @Test - public void whenVerifyingDeleteObjects_thenCorrect() { - DeleteObjectsRequest request = mock(DeleteObjectsRequest.class); - DeleteObjectsResult result = mock(DeleteObjectsResult.class); - when(s3.deleteObjects((DeleteObjectsRequest)any())).thenReturn(result); - - assertThat(service.deleteObjects(request)).isEqualTo(result); - verify(s3).deleteObjects(request); - } - -} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java deleted file mode 100644 index e2a34b1c39..0000000000 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.baeldung.s3; - -import com.amazonaws.event.ProgressListener; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.transfer.TransferManager; -import com.amazonaws.services.s3.transfer.TransferManagerBuilder; -import com.amazonaws.services.s3.transfer.Upload; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.util.concurrent.Executors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class MultipartUploadLiveTest { - - private static final String BUCKET_NAME = "bucket_name"; - private static final String KEY_NAME = "picture.jpg"; - - private AmazonS3 amazonS3; - private TransferManager tm; - private ProgressListener progressListener; - - @Before - public void setup() { - amazonS3 = mock(AmazonS3.class); - tm = TransferManagerBuilder - .standard() - .withS3Client(amazonS3) - .withMultipartUploadThreshold((long) (5 * 1024 * 1025)) - .withExecutorFactory(() -> Executors.newFixedThreadPool(5)) - .build(); - progressListener = - progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred()); - } - - @Test - public void whenUploadingFileWithTransferManager_thenVerifyUploadRequested() { - File file = mock(File.class); - PutObjectResult s3Result = mock(PutObjectResult.class); - - when(amazonS3.putObject(anyString(), anyString(), (File) any())).thenReturn(s3Result); - when(file.getName()).thenReturn(KEY_NAME); - - PutObjectRequest request = new PutObjectRequest(BUCKET_NAME, KEY_NAME, file); - request.setGeneralProgressListener(progressListener); - - Upload upload = tm.upload(request); - - assertThat(upload).isNotNull(); - verify(amazonS3).putObject(request); - } -} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java new file mode 100644 index 0000000000..bf24bcaa43 --- /dev/null +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java @@ -0,0 +1,137 @@ +package com.baeldung.s3; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.util.Collections; + +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.CopyObjectRequest; +import software.amazon.awssdk.services.s3.model.CopyObjectResponse; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; + +class S3ServiceIntegrationTest { + + private static final String BUCKET_NAME = "bucket_name"; + private static final String KEY_NAME = "key_name"; + private static final String BUCKET_NAME2 = "bucket_name2"; + private static final String KEY_NAME2 = "key_name2"; + + @Mock + private S3Client s3Client; + + private S3Service s3Service; + + private final String AWS_BUCKET = "baeldung-tutorial-s3"; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + s3Service = new S3Service(s3Client); + } + + @AfterEach + public void cleanup() { + s3Service.cleanup(); + Mockito.verify(s3Client).close(); + } + + @Test + void whenInitializingAWSS3Service_thenNotNull() { + assertThat(new S3Service(s3Client)).isNotNull(); + } + + @Test + void whenVerifyingIfS3BucketExist_thenCorrect() { + HeadBucketRequest headBucketRequest = HeadBucketRequest.builder() + .bucket(BUCKET_NAME) + .build(); + + s3Service.doesBucketExist(BUCKET_NAME); + verify(s3Client).headBucket(headBucketRequest); + } + + @Test + void whenVerifyingCreationOfS3Bucket_thenCorrect() { + CreateBucketRequest bucketRequest = CreateBucketRequest.builder() + .bucket(BUCKET_NAME) + .build(); + + s3Service.createBucket(BUCKET_NAME); + verify(s3Client).createBucket(bucketRequest); + } + + @Test + void whenVerifyingListBuckets_thenCorrect() { + when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); + + s3Service.listBuckets(); + Mockito.verify(s3Client).listBuckets(); + } + + @Test + void whenDeletingBucket_thenCorrect() { + DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder() + .bucket(BUCKET_NAME) + .build(); + + s3Service.deleteBucket(BUCKET_NAME); + verify(s3Client).deleteBucket(deleteBucketRequest); + } + + + + @Test + void whenVerifyingListObjects_thenCorrect() { + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); + + when(s3Client.listObjectsV2(request)).thenReturn(response); + + s3Service.listObjects(AWS_BUCKET); + verify(s3Client).listObjectsV2(request); + } + + + @Test + void whenVerifyingCopyObject_thenCorrect() { + CopyObjectRequest request = CopyObjectRequest.builder() + .sourceBucket(BUCKET_NAME) + .sourceKey(KEY_NAME) + .destinationBucket(BUCKET_NAME2) + .destinationKey(KEY_NAME2) + .build(); + + CopyObjectResponse result = CopyObjectResponse.builder().build(); + + when(s3Client.copyObject(request)).thenReturn(result); + + assertThat(s3Service.copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2)).isEqualTo(result); + verify(s3Client).copyObject(request); + } + + @Test + void whenVerifyingDeleteObject_thenCorrect() { + DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder() + .bucket(BUCKET_NAME) + .key(KEY_NAME) + .build(); + + s3Service.deleteObject(BUCKET_NAME, KEY_NAME); + verify(s3Client).deleteObject(deleteObjectRequest); + } +} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java new file mode 100644 index 0000000000..defe75e346 --- /dev/null +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java @@ -0,0 +1,51 @@ +package com.baeldung.s3; + + +import static org.junit.jupiter.api.Assertions.assertTrue; + + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import software.amazon.awssdk.services.s3.S3Client; + +/** + * Required defined environment variables AWS_ACCESS_KEY_ID & AWS_ACCESS_KEY to access S3. + * Required S3 bucket and key that exist. + */ + +class S3ServiceManualTest { + + private static final String BUCKET_NAME = "bucket_name"; + private static final String KEY_NAME = "key_name"; + @Mock + private S3Client s3Client; + + private S3Service s3Service; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + s3Service = new S3Service(s3Client); + } + + @AfterEach + public void cleanup() { + s3Service.cleanup(); + Mockito.verify(s3Client).close(); + } + + @Test + void whenVerifyIfObjectExistByDefaultMethod_thenCorrect() { + assertTrue(s3Service.doesObjectExistByDefaultMethod(BUCKET_NAME, KEY_NAME), "Key: " + KEY_NAME + " doesn't exist"); + } + + @Test + void whenVerifyIfObjectExistByListObjects_thenCorrect() { + assertTrue(s3Service.doesObjectExistByListObjects(BUCKET_NAME, KEY_NAME), "Key: " + KEY_NAME + " doesn't exist"); + } +} From f562c27a0414b3de70e1bf14768f73ffb20374bc Mon Sep 17 00:00:00 2001 From: panos-kakos Date: Wed, 5 Jul 2023 08:50:30 +0300 Subject: [PATCH 02/16] [JAVA-22456] Merge modules aws-s3 & aws-s3-v2 --- aws-modules/aws-s3-v2/README.md | 2 - aws-modules/aws-s3-v2/pom.xml | 50 ---- .../com/baeldung/s3/listobjects/Main.java | 22 -- .../baeldung/s3/listobjects/S3Service.java | 129 ----------- .../aws-s3-v2/src/main/resources/logback.xml | 14 -- .../src/main/java/com/baeldung/s3}/File.java | 42 ++-- .../java/com/baeldung/s3}/FileGenerator.java | 54 ++--- .../java/com/baeldung/s3/S3Application.java | 9 + .../main/java/com/baeldung/s3/S3Service.java | 82 +++++++ .../aws-s3/src/main/resources/logback.xml | 3 + .../com/baeldung/s3}/S3ServiceLiveTest.java | 218 +++++++++--------- aws-modules/pom.xml | 1 - 12 files changed, 251 insertions(+), 375 deletions(-) delete mode 100644 aws-modules/aws-s3-v2/README.md delete mode 100644 aws-modules/aws-s3-v2/pom.xml delete mode 100644 aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java delete mode 100644 aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java delete mode 100644 aws-modules/aws-s3-v2/src/main/resources/logback.xml rename aws-modules/{aws-s3-v2/src/main/java/com/baeldung/s3/listobjects => aws-s3/src/main/java/com/baeldung/s3}/File.java (85%) rename aws-modules/{aws-s3-v2/src/main/java/com/baeldung/s3/listobjects => aws-s3/src/main/java/com/baeldung/s3}/FileGenerator.java (91%) rename aws-modules/{aws-s3-v2/src/test/java/com/baeldung/s3/listobjects => aws-s3/src/test/java/com/baeldung/s3}/S3ServiceLiveTest.java (85%) diff --git a/aws-modules/aws-s3-v2/README.md b/aws-modules/aws-s3-v2/README.md deleted file mode 100644 index 4ec342894e..0000000000 --- a/aws-modules/aws-s3-v2/README.md +++ /dev/null @@ -1,2 +0,0 @@ -## Relevant Articles -- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects) diff --git a/aws-modules/aws-s3-v2/pom.xml b/aws-modules/aws-s3-v2/pom.xml deleted file mode 100644 index 888d98e654..0000000000 --- a/aws-modules/aws-s3-v2/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - 4.0.0 - com.baeldung.s3 - aws-s3-v2 - 1.0-SNAPSHOT - aws-s3-v2 - jar - - - com.baeldung - aws-modules - 1.0.0-SNAPSHOT - - - - UTF-8 - 2.20.52 - 3.6.1 - - - - - software.amazon.awssdk - s3 - ${aws.java.sdk.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - ${maven-shade-plugin.version} - - false - - - - package - - shade - - - - - - - diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java b/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java deleted file mode 100644 index 7b7c95a0d0..0000000000 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.s3.listobjects; - -import software.amazon.awssdk.regions.Region; - -public class Main { - - private static String AWS_BUCKET = "baeldung-tutorial-s3"; - public static Region AWS_REGION = Region.EU_CENTRAL_1; - - public static void main(String[] args) { - S3Service s3Service = new S3Service(AWS_REGION); - - s3Service.putObject(AWS_BUCKET, FileGenerator.generateFiles(1000, 1)); - s3Service.listBuckets(); - s3Service.listObjectsInBucket(AWS_BUCKET); - s3Service.listAllObjectsInBucket(AWS_BUCKET); - s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, 500); - s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, 500, "backup/"); - - s3Service.cleanup(); - } -} diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java b/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java deleted file mode 100644 index 132123f214..0000000000 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.baeldung.s3.listobjects; - -import java.util.List; - -import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.*; -import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; - -class S3Service { - - private S3Client s3Client; - - public S3Service(Region awsRegion) { - init(awsRegion); - } - - public S3Service(S3Client s3Client) { - this.s3Client = s3Client; - } - - public void init(Region awsRegion) { - this.s3Client = S3Client.builder() - .region(awsRegion) - .credentialsProvider(ProfileCredentialsProvider.create("default")) - .build(); - } - - public void listObjectsInBucket(String bucketName) { - ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() - .bucket(bucketName) - .build(); - ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); - - List contents = listObjectsV2Response.contents(); - - System.out.println("Number of objects in the bucket: " + contents.stream().count()); - contents.stream().forEach(System.out::println); - } - - public void listAllObjectsInBucket(String bucketName) { - String nextContinuationToken = null; - long totalObjects = 0; - - do { - ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.builder() - .bucket(bucketName) - .continuationToken(nextContinuationToken); - - ListObjectsV2Response response = s3Client.listObjectsV2(requestBuilder.build()); - nextContinuationToken = response.nextContinuationToken(); - - totalObjects += response.contents().stream() - .peek(System.out::println) - .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); - } while (nextContinuationToken != null); - System.out.println("Number of objects in the bucket: " + totalObjects); - } - - public void listAllObjectsInBucketPaginated(String bucketName, int pageSize) { - ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() - .bucket(bucketName) - .maxKeys(pageSize) // Set the maxKeys parameter to control the page size - .build(); - - ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); - long totalObjects = 0; - - for (ListObjectsV2Response page : listObjectsV2Iterable) { - long retrievedPageSize = page.contents().stream() - .peek(System.out::println) - .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); - totalObjects += retrievedPageSize; - System.out.println("Page size: " + retrievedPageSize); - } - System.out.println("Total objects in the bucket: " + totalObjects); - } - - public void listAllObjectsInBucketPaginatedWithPrefix(String bucketName, int pageSize, String prefix) { - ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() - .bucket(bucketName) - .maxKeys(pageSize) // Set the maxKeys parameter to control the page size - .prefix(prefix) - .build(); - - ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); - long totalObjects = 0; - - for (ListObjectsV2Response page : listObjectsV2Iterable) { - long retrievedPageSize = page.contents().stream() - .peek(System.out::println) - .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); - totalObjects += retrievedPageSize; - System.out.println("Page size: " + retrievedPageSize); - } - System.out.println("Total objects in the bucket: " + totalObjects); - } - - public void listBuckets() { - // List all buckets - ListBucketsResponse listBucketsResponse = s3Client.listBuckets(); - - // Display the bucket names - List buckets = listBucketsResponse.buckets(); - System.out.println("Buckets:"); - for (Bucket bucket : buckets) { - System.out.println(bucket.name()); - } - } - - public void putObject(String bucketName, List files) { - try { - files.stream().forEach(file -> { - s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(), - RequestBody.fromByteBuffer(file.getContent())); - System.out.println("Uploaded file: " + file.getName()); - }); - } catch (S3Exception e) { - System.err.println("Upload failed"); - e.printStackTrace(); - } - } - - public void cleanup() { - this.s3Client.close(); - } -} \ No newline at end of file diff --git a/aws-modules/aws-s3-v2/src/main/resources/logback.xml b/aws-modules/aws-s3-v2/src/main/resources/logback.xml deleted file mode 100644 index 91d3d0cfa6..0000000000 --- a/aws-modules/aws-s3-v2/src/main/resources/logback.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - \ No newline at end of file diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/File.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/File.java similarity index 85% rename from aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/File.java rename to aws-modules/aws-s3/src/main/java/com/baeldung/s3/File.java index f9fe7f6fb3..9ab817f7fb 100644 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/File.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/File.java @@ -1,21 +1,21 @@ -package com.baeldung.s3.listobjects; - -import java.nio.ByteBuffer; - -public class File { - private String name; - private ByteBuffer content; - - public File(String name, ByteBuffer content) { - this.name = name; - this.content = content; - } - - public String getName() { - return name; - } - - public ByteBuffer getContent() { - return content; - } -} +package com.baeldung.s3; + +import java.nio.ByteBuffer; + +public class File { + private String name; + private ByteBuffer content; + + public File(String name, ByteBuffer content) { + this.name = name; + this.content = content; + } + + public String getName() { + return name; + } + + public ByteBuffer getContent() { + return content; + } +} diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/FileGenerator.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/FileGenerator.java similarity index 91% rename from aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/FileGenerator.java rename to aws-modules/aws-s3/src/main/java/com/baeldung/s3/FileGenerator.java index 7c640591d7..7c35192d22 100644 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/FileGenerator.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/FileGenerator.java @@ -1,27 +1,27 @@ -package com.baeldung.s3.listobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class FileGenerator { - - public static List generateFiles(int fileCount, int fileSize) { - List files = new ArrayList<>(); - for (int i = 0; i < fileCount; i++) { - String fileName = "file_" + i + ".txt"; - ByteBuffer fileContent = generateRandomBytes(fileSize); - files.add(new File(fileName, fileContent)); - } - return files; - } - - private static ByteBuffer generateRandomBytes(int size) { - byte[] array = new byte[size]; - new Random().nextBytes(array); - return ByteBuffer.wrap(array); - } - - -} +package com.baeldung.s3; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class FileGenerator { + + public static List generateFiles(int fileCount, int fileSize) { + List files = new ArrayList<>(); + for (int i = 0; i < fileCount; i++) { + String fileName = "file_" + i + ".txt"; + ByteBuffer fileContent = generateRandomBytes(fileSize); + files.add(new File(fileName, fileContent)); + } + return files; + } + + private static ByteBuffer generateRandomBytes(int size) { + byte[] array = new byte[size]; + new Random().nextBytes(array); + return ByteBuffer.wrap(array); + } + + +} diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java index 1ce2f9cbb5..abf570f0d0 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java @@ -23,8 +23,17 @@ public class S3Application { return; } + + s3Service.putObjects(AWS_BUCKET, FileGenerator.generateFiles(1000, 1)); + //list all the buckets s3Service.listBuckets(); + s3Service.listObjectsInBucket(AWS_BUCKET); + s3Service.listAllObjectsInBucket(AWS_BUCKET); + s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, 500); + s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, 500, "backup/"); + + //deleting bucket s3Service.deleteBucket("baeldung-bucket-test2"); diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java index 361e7e83b0..f4f768d1b4 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java @@ -234,6 +234,88 @@ class S3Service { } } + public void listObjectsInBucket(String bucketName) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .build(); + ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); + + List contents = listObjectsV2Response.contents(); + + System.out.println("Number of objects in the bucket: " + contents.stream().count()); + contents.stream().forEach(System.out::println); + } + + public void listAllObjectsInBucket(String bucketName) { + String nextContinuationToken = null; + long totalObjects = 0; + + do { + ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.builder() + .bucket(bucketName) + .continuationToken(nextContinuationToken); + + ListObjectsV2Response response = s3Client.listObjectsV2(requestBuilder.build()); + nextContinuationToken = response.nextContinuationToken(); + + totalObjects += response.contents().stream() + .peek(System.out::println) + .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); + } while (nextContinuationToken != null); + System.out.println("Number of objects in the bucket: " + totalObjects); + } + + public void listAllObjectsInBucketPaginated(String bucketName, int pageSize) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .maxKeys(pageSize) // Set the maxKeys parameter to control the page size + .build(); + + ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); + long totalObjects = 0; + + for (ListObjectsV2Response page : listObjectsV2Iterable) { + long retrievedPageSize = page.contents().stream() + .peek(System.out::println) + .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); + totalObjects += retrievedPageSize; + System.out.println("Page size: " + retrievedPageSize); + } + System.out.println("Total objects in the bucket: " + totalObjects); + } + + public void listAllObjectsInBucketPaginatedWithPrefix(String bucketName, int pageSize, String prefix) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .maxKeys(pageSize) // Set the maxKeys parameter to control the page size + .prefix(prefix) + .build(); + + ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); + long totalObjects = 0; + + for (ListObjectsV2Response page : listObjectsV2Iterable) { + long retrievedPageSize = page.contents().stream() + .peek(System.out::println) + .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); + totalObjects += retrievedPageSize; + System.out.println("Page size: " + retrievedPageSize); + } + System.out.println("Total objects in the bucket: " + totalObjects); + } + + public void putObjects(String bucketName, List files) { + try { + files.stream().forEach(file -> { + s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(), + RequestBody.fromByteBuffer(file.getContent())); + System.out.println("Uploaded file: " + file.getName()); + }); + } catch (S3Exception e) { + System.err.println("Upload failed"); + e.printStackTrace(); + } + } public void cleanup() { this.s3Client.close(); } diff --git a/aws-modules/aws-s3/src/main/resources/logback.xml b/aws-modules/aws-s3/src/main/resources/logback.xml index 7d900d8ea8..88eee7b977 100644 --- a/aws-modules/aws-s3/src/main/resources/logback.xml +++ b/aws-modules/aws-s3/src/main/resources/logback.xml @@ -10,4 +10,7 @@ + + + \ No newline at end of file diff --git a/aws-modules/aws-s3-v2/src/test/java/com/baeldung/s3/listobjects/S3ServiceLiveTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceLiveTest.java similarity index 85% rename from aws-modules/aws-s3-v2/src/test/java/com/baeldung/s3/listobjects/S3ServiceLiveTest.java rename to aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceLiveTest.java index 40b30f8669..c46af81564 100644 --- a/aws-modules/aws-s3-v2/src/test/java/com/baeldung/s3/listobjects/S3ServiceLiveTest.java +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceLiveTest.java @@ -1,109 +1,109 @@ -package com.baeldung.s3.listobjects; - -import com.baeldung.s3.listobjects.S3Service; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.ListBucketsResponse; -import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; -import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; -import software.amazon.awssdk.services.s3.model.S3Object; -import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; - -import java.util.Arrays; -import java.util.Collections; - -import static org.mockito.Mockito.when; - -class S3ServiceLiveTest { - - @Mock - private S3Client s3Client; - - private S3Service s3Service; - - private String AWS_BUCKET = "baeldung-tutorial-s3"; - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - s3Service = new S3Service(s3Client); - } - - @AfterEach - public void cleanup() { - s3Service.cleanup(); - Mockito.verify(s3Client).close(); - } - - @Test - public void givenBucketName_whenListObjectsInBucket_thenReturnList() { - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); - - when(s3Client.listObjectsV2(request)).thenReturn(response); - - s3Service.listObjectsInBucket(AWS_BUCKET); - Mockito.verify(s3Client).listObjectsV2(request); - } - - @Test - public void givenBucketName_whenListAllObjectsInBucket_thenReturnList() { - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); - - when(s3Client.listObjectsV2(request)).thenReturn(response); - - s3Service.listAllObjectsInBucket(AWS_BUCKET); - Mockito.verify(s3Client).listObjectsV2(request); - } - - @Test - public void givenBucketNameAndPageSize_whenListAllObjectsInBucketPaginated_thenReturnPaginatedList() { - int pageSize = 10; - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).build(); - - ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); - - S3Object s3Object1 = S3Object.builder().key("object1").build(); - S3Object s3Object2 = S3Object.builder().key("object2").build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); - - when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); - when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); - - s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, pageSize); - Mockito.verify(s3Client).listObjectsV2Paginator(request); - } - - @Test - public void givenBucketNamePageSizeAndPrefix_whenListAllObjectsInBucketPaginatedWithPrefix_thenReturnPaginatedList() { - int pageSize = 1; - String prefix = "folder/"; - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).prefix(prefix).build(); - - ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); - - S3Object s3Object1 = S3Object.builder().key("folder/object1").build(); - S3Object s3Object2 = S3Object.builder().key("folder/object2").build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); - - when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); - when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); - - s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, pageSize, prefix); - Mockito.verify(s3Client).listObjectsV2Paginator(request); - } - - @Test - public void whenListBuckets_thenReturnBucketList() { - when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); - - s3Service.listBuckets(); - Mockito.verify(s3Client).listBuckets(); - } -} +package com.baeldung.s3; + +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; +import software.amazon.awssdk.services.s3.model.S3Object; +import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; + +import java.util.Arrays; +import java.util.Collections; + +class S3ServiceLiveTest { + + @Mock + private S3Client s3Client; + + private S3Service s3Service; + + private String AWS_BUCKET = "baeldung-tutorial-s3"; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + s3Service = new S3Service(s3Client); + } + + @AfterEach + public void cleanup() { + s3Service.cleanup(); + Mockito.verify(s3Client).close(); + } + + @Test + void givenBucketName_whenListObjectsInBucket_thenReturnList() { + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); + + when(s3Client.listObjectsV2(request)).thenReturn(response); + + s3Service.listObjectsInBucket(AWS_BUCKET); + Mockito.verify(s3Client).listObjectsV2(request); + } + + @Test + void givenBucketName_whenListAllObjectsInBucket_thenReturnList() { + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); + + when(s3Client.listObjectsV2(request)).thenReturn(response); + + s3Service.listAllObjectsInBucket(AWS_BUCKET); + Mockito.verify(s3Client).listObjectsV2(request); + } + + @Test + void givenBucketNameAndPageSize_whenListAllObjectsInBucketPaginated_thenReturnPaginatedList() { + int pageSize = 10; + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).build(); + + ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); + + S3Object s3Object1 = S3Object.builder().key("object1").build(); + S3Object s3Object2 = S3Object.builder().key("object2").build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); + + when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); + when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); + + s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, pageSize); + Mockito.verify(s3Client).listObjectsV2Paginator(request); + } + + @Test + void givenBucketNamePageSizeAndPrefix_whenListAllObjectsInBucketPaginatedWithPrefix_thenReturnPaginatedList() { + int pageSize = 1; + String prefix = "folder/"; + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).prefix(prefix).build(); + + ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); + + S3Object s3Object1 = S3Object.builder().key("folder/object1").build(); + S3Object s3Object2 = S3Object.builder().key("folder/object2").build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); + + when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); + when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); + + s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, pageSize, prefix); + Mockito.verify(s3Client).listObjectsV2Paginator(request); + } + + @Test + void whenListBuckets_thenReturnBucketList() { + when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); + + s3Service.listBuckets(); + Mockito.verify(s3Client).listBuckets(); + } +} diff --git a/aws-modules/pom.xml b/aws-modules/pom.xml index 77872e3f8f..02473815b5 100644 --- a/aws-modules/pom.xml +++ b/aws-modules/pom.xml @@ -19,7 +19,6 @@ aws-miscellaneous aws-reactive aws-s3 - aws-s3-v2 From c966588a954096b2854ce6e4bb31fb9b97a2c202 Mon Sep 17 00:00:00 2001 From: panos-kakos Date: Mon, 31 Jul 2023 12:01:04 +0300 Subject: [PATCH 03/16] [TASK-22456] Added missing article from README.md --- aws-modules/aws-s3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/aws-modules/aws-s3/README.md b/aws-modules/aws-s3/README.md index 109a898405..3389fdf454 100644 --- a/aws-modules/aws-s3/README.md +++ b/aws-modules/aws-s3/README.md @@ -8,3 +8,4 @@ This module contains articles about Simple Storage Service (S3) on AWS - [Multipart Uploads in Amazon S3 with Java](https://www.baeldung.com/aws-s3-multipart-upload) - [Using the JetS3t Java Client With Amazon S3](https://www.baeldung.com/jets3t-amazon-s3) - [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists) +- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects) \ No newline at end of file From 8f27b58aa7dd58be40cbabc6816b98fcbf4b37ba Mon Sep 17 00:00:00 2001 From: tienvn Date: Thu, 3 Aug 2023 17:59:49 +0700 Subject: [PATCH 04/16] BAEL-6541-convert-relative-path --- .../java/com/baeldung/convertpaths/RelativePathConverter.java | 0 .../com/baeldung/convertpaths/RelativePathConverterUnitTest.java | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename core-java-modules/{core-java-20 => core-java-io-apis-2}/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java (100%) rename core-java-modules/{core-java-20 => core-java-io-apis-2}/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java (100%) diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java b/core-java-modules/core-java-io-apis-2/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java similarity index 100% rename from core-java-modules/core-java-20/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java rename to core-java-modules/core-java-io-apis-2/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java diff --git a/core-java-modules/core-java-20/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java similarity index 100% rename from core-java-modules/core-java-20/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java rename to core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java From 76f2e484588878ce837216395fcada3b6951fd5a Mon Sep 17 00:00:00 2001 From: GaetanoPiazzolla Date: Fri, 4 Aug 2023 09:23:30 +0200 Subject: [PATCH 05/16] JAVA-22203 | Forced start and stop + sleep --- ...a => EmbeddedActiveMqIntegrationTest.java} | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) rename messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/{EmbeddedActiveMqManualTest.java => EmbeddedActiveMqIntegrationTest.java} (85%) diff --git a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqManualTest.java b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java similarity index 85% rename from messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqManualTest.java rename to messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java index 676dcb1dd8..0625020a06 100644 --- a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqManualTest.java +++ b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java @@ -8,6 +8,8 @@ import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.junit.EmbeddedActiveMQBroker; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; @@ -23,11 +25,9 @@ import org.springframework.jms.core.JmsTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.spring.jms.testing.EmbeddedActiveMqManualTest.TestConfiguration; - @RunWith(SpringRunner.class) -@ContextConfiguration(classes = { TestConfiguration.class }) -public class EmbeddedActiveMqManualTest { +@ContextConfiguration(classes = { EmbeddedActiveMqIntegrationTest.TestConfiguration.class }) +public class EmbeddedActiveMqIntegrationTest { @ClassRule public static EmbeddedActiveMQBroker embeddedBroker = new EmbeddedActiveMQBroker(); @@ -38,12 +38,23 @@ public class EmbeddedActiveMqManualTest { @SpyBean private MessageSender messageSender; + @BeforeClass + public static void start() { + embeddedBroker.start(); + } + + @AfterClass + public static void stop() { + embeddedBroker.stop(); + } + @Test - public void whenListening_thenReceivingCorrectMessage() throws JMSException { + public void whenListening_thenReceivingCorrectMessage() throws JMSException, InterruptedException { String queueName = "queue-1"; String messageText = "Test message"; embeddedBroker.pushMessage(queueName, messageText); + Thread.sleep(1000L); assertEquals(1, embeddedBroker.getMessageCount(queueName)); ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(TextMessage.class); @@ -56,12 +67,12 @@ public class EmbeddedActiveMqManualTest { } @Test - public void whenSendingMessage_thenCorrectQueueAndMessageText() throws JMSException { + public void whenSendingMessage_thenCorrectQueueAndMessageText() throws JMSException, InterruptedException { String queueName = "queue-2"; String messageText = "Test message"; messageSender.sendTextMessage(queueName, messageText); - + Thread.sleep(1000L); assertEquals(1, embeddedBroker.getMessageCount(queueName)); TextMessage sentMessage = embeddedBroker.peekTextMessage(queueName); assertEquals(messageText, sentMessage.getText()); From 7851382f7749b283b2c09e547987ef94f28f27a8 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 4 Aug 2023 10:42:58 +0300 Subject: [PATCH 06/16] Update CertificatesUnitTest.java --- .../java/com/baeldung/trustedcert/CertificatesUnitTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java index 4f40c3c195..b013ff4ed1 100644 --- a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java @@ -28,6 +28,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import org.junit.jupiter.api.Disabled; + +@Disabled //fixing in https://team.baeldung.com/browse/JAVA-23897 public class CertificatesUnitTest { private static final String GODADDY_CA_ALIAS = "godaddyrootg2ca [jdk]"; From 198dff7bed30660dc7cbec8822de1855fb805c49 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Fri, 4 Aug 2023 05:54:26 -0400 Subject: [PATCH 07/16] Add Example Code (#14521) --- di-modules/avaje/README.md | 7 ++++ di-modules/avaje/pom.xml | 37 +++++++++++++++++++ .../com/baeldung/avaje/intro/ArmsFactory.java | 18 +++++++++ .../java/com/baeldung/avaje/intro/Knight.java | 34 +++++++++++++++++ .../java/com/baeldung/avaje/intro/Ninja.java | 30 +++++++++++++++ .../java/com/baeldung/avaje/intro/Shield.java | 18 +++++++++ .../java/com/baeldung/avaje/intro/Sword.java | 8 ++++ .../baeldung/avaje/intro/AvajeUnitTest.java | 21 +++++++++++ .../avaje/intro/ExampleInjectTest.java | 29 +++++++++++++++ 9 files changed, 202 insertions(+) create mode 100644 di-modules/avaje/README.md create mode 100644 di-modules/avaje/pom.xml create mode 100644 di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java create mode 100644 di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java create mode 100644 di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java create mode 100644 di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java create mode 100644 di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java create mode 100644 di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java create mode 100644 di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java diff --git a/di-modules/avaje/README.md b/di-modules/avaje/README.md new file mode 100644 index 0000000000..ea914e551f --- /dev/null +++ b/di-modules/avaje/README.md @@ -0,0 +1,7 @@ +# Introduction to Avaje Inject + +This module contains articles about Avaje + +### Relevant articles: + +- [Introduction to Avaje Inject](https://www.baeldung.com/avaje-inject/intro) \ No newline at end of file diff --git a/di-modules/avaje/pom.xml b/di-modules/avaje/pom.xml new file mode 100644 index 0000000000..7ffe14bd72 --- /dev/null +++ b/di-modules/avaje/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + com.baeldung + inject-intro + 0.0.1-SNAPSHOT + avaje-inject-intro + + 11 + 11 + 9.5 + + + + io.avaje + avaje-inject + ${avaje.inject.version} + + + + io.avaje + avaje-inject-test + ${avaje.inject.version} + test + + + + + io.avaje + avaje-inject-generator + ${avaje.inject.version} + provided + true + + + \ No newline at end of file diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java new file mode 100644 index 0000000000..381b390ad0 --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java @@ -0,0 +1,18 @@ +package com.baeldung.avaje.intro; + +import io.avaje.inject.Bean; +import io.avaje.inject.Factory; + +@Factory +public class ArmsFactory { + + @Bean + public Sword provideSword() { + return new Sword(); + } + + @Bean + public Shield provideShield() { + return new Shield(25); + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java new file mode 100644 index 0000000000..c78c60b858 --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java @@ -0,0 +1,34 @@ +package com.baeldung.avaje.intro; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +@Singleton +public class Knight { + + private Sword sword; + + private Shield shield; + + @Inject + public Knight(Sword sword, Shield shield) { + this.sword = sword; + this.shield = shield; + } + + public Sword sword() { + return sword; + } + + public void sword(Sword engine) { + this.sword = engine; + } + + public Shield shield() { + return shield; + } + + public void shield(Shield brand) { + this.shield = brand; + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java new file mode 100644 index 0000000000..e4d893ffef --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java @@ -0,0 +1,30 @@ +package com.baeldung.avaje.intro; + +import io.avaje.inject.BeanScope; +import io.avaje.inject.PostConstruct; +import io.avaje.inject.PreDestroy; +import jakarta.inject.Singleton; + +@Singleton +public class Ninja { + + private Sword sword; + + @PostConstruct + void equip(BeanScope scope) { + sword = scope.get(Sword.class); + } + + @PreDestroy + void dequip() { + sword = null; + } + + public Sword sword() { + return sword; + } + + public void sword(Sword engine) { + this.sword = engine; + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java new file mode 100644 index 0000000000..c5d5a3e999 --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java @@ -0,0 +1,18 @@ +package com.baeldung.avaje.intro; + +public class Shield { + + private int defense; + + public Shield(int defense) { + this.defense = defense; + } + + public int defense() { + return defense; + } + + public void defense(int defense) { + this.defense = defense; + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java new file mode 100644 index 0000000000..6eceed082e --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java @@ -0,0 +1,8 @@ +package com.baeldung.avaje.intro; + +public class Sword { + + public void attack() { + System.out.println("swing"); + } +} diff --git a/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java new file mode 100644 index 0000000000..a0b71a228a --- /dev/null +++ b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.avaje.intro; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +import io.avaje.inject.BeanScope; + +class AvajeUnitTest { + + @Test + void givenBeanScope_whenScopeGetsKnight_thenKnightShouldHaveDependencies() { + + final var scope = BeanScope.builder().build(); + final var knight = scope.get(Knight.class); + + assertNotNull(knight); + assertNotNull(knight.sword()); + assertNotNull(knight.shield()); + assertEquals(25, knight.shield().defense()); + } +} diff --git a/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java new file mode 100644 index 0000000000..6eada4cb6d --- /dev/null +++ b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java @@ -0,0 +1,29 @@ +package com.baeldung.avaje.intro; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; + +import io.avaje.inject.test.InjectTest; +import jakarta.inject.Inject; + +@InjectTest +class ExampleInjectTest { + + @Mock Shield shield; + + @Inject Knight knight; + + @Test + void givenMockedShield_whenGetShield_thenShieldShouldHaveMockedValue() { + + Mockito.when(shield.defense()).thenReturn(0); + assertNotNull(knight); + assertNotNull(knight.sword()); + assertNotNull(knight.shield()); + assertEquals(0, knight.shield().defense()); + } +} From 58dcdf8af4db033beae8c3bcab7ba043f5156c5a Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:39:09 +0200 Subject: [PATCH 08/16] BAEL-6651: Embeddable Records in Hibernate 6 (#14516) * BAEL-6651: Bumped Spring Boot version * BAEL-6651: Replaced flaky test * BAEL-6651: Embeddable example with tests --- .../ConstraintsBuilder.java | 15 ++ .../EditReminderFrame.java | 194 ++++++++++++++++++ .../src/reminderapplication/Reminder.java | 33 +++ .../reminderapplication/ReminderFrame.java | 186 +++++++++++++++++ .../ReminderPopupFrame.java | 151 ++++++++++++++ parent-boot-3/pom.xml | 2 +- .../baeldung/recordswithjpa/QueryService.java | 9 +- .../recordswithjpa/embeddable/Author.java | 9 + .../embeddable/AuthorInstallator.java | 23 +++ .../embeddable/EmbeddableBook.java | 65 ++++++ .../repository/EmbeddableBookRepository.java | 14 ++ .../QueryServiceIntegrationTest.java | 9 +- ...RecordsAsJpaEmbeddableIntegrationTest.java | 31 +++ ...beddableBookRepositoryIntegrationTest.java | 16 ++ 14 files changed, 745 insertions(+), 12 deletions(-) create mode 100644 core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java create mode 100644 core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java create mode 100644 core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java create mode 100644 core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java create mode 100644 core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java create mode 100644 spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java new file mode 100644 index 0000000000..ce437fac6d --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java @@ -0,0 +1,15 @@ +package reminderapplication; + +import java.awt.GridBagConstraints; +import java.awt.Insets; + +public class ConstraintsBuilder { + + static GridBagConstraints constraint(int x, int y) { + final GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = x; + gridBagConstraints.gridy = y; + gridBagConstraints.insets = new Insets(5, 5, 5, 5); + return gridBagConstraints; + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java new file mode 100644 index 0000000000..818cea403e --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java @@ -0,0 +1,194 @@ +package reminderapplication; + +import static reminderapplication.ConstraintsBuilder.*; + +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.lang.reflect.InvocationTargetException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +public class EditReminderFrame extends JFrame { + + private static Timer TIMER = new Timer(); + + private final TimeReminderApplication reminderApplication; + private final JLabel reminderTextLabel; + private final JLabel repeatPeriodLabel; + private final JLabel setDelayLabel; + private final JComboBox delay; + private final JComboBox period; + private final JButton cancelButton; + private final JButton okButton; + private final JTextField textField; + private final JLabel delaysLabel; + private final JLabel periodLabel; + + private final int reminderIndex; + + public EditReminderFrame(TimeReminderApplication reminderApp, String reminderText, int delayInSeconds, int periodInSeconds, int index) throws HeadlessException { + this.reminderApplication = reminderApp; + reminderIndex = index; + textField = createTextField(reminderText); + delay = createDelayComboBox(delayInSeconds); + period = createPeriodComboBox(periodInSeconds); + cancelButton = createCancelButton(); + okButton = createOkButton(); + reminderTextLabel = createReminderTextLabel(); + repeatPeriodLabel = createRepeatPeriodLabel(); + setDelayLabel = createSetDelayLabel(); + delaysLabel = createDelaysLabel(); + periodLabel = createPeriodLabel(); + configureVisualRepresentation(); + configureActions(); + } + + private void configureActions() { + updateReminder(); + } + + private void configureVisualRepresentation() { + configureFrame(); + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); + add(reminderTextLabel, constraint(0,0)); + add(repeatPeriodLabel, constraint(1,0)); + add(setDelayLabel, constraint(2,0)); + add(textField, constraint(0, 1)); + add(delay, constraint(1, 1)); + add(period, constraint(2, 1)); + add(delaysLabel, constraint(1,3)); + add(periodLabel, constraint(2,3)); + add(okButton, constraint(1, 4)); + add(cancelButton, constraint(2, 4)); + pack(); + setVisible(true); + } + + private void configureFrame() { + setTitle("Set Reminder"); + setName("Set Reminder"); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + private static JLabel createSetDelayLabel() { + return createLabel("Set Delay", "Set Delay Label"); + } + + private static JLabel createRepeatPeriodLabel() { + return createLabel("Set Period", "Set Repeat Period Label"); + } + + private static JLabel createReminderTextLabel() { + return createLabel("Reminder Text", "Reminder Text Label"); + } + + private JLabel createPeriodLabel() { + return createLabel("0", "Period label"); + } + + private JLabel createDelaysLabel() { + return createLabel("30", "Delays Label"); + } + + private JComboBox createPeriodComboBox(final int periodInSeconds) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20})); + comboBox.setSelectedItem(periodInSeconds); + comboBox.setName("set Period"); + comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JComboBox createDelayComboBox(final int delayInSeconds) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5})); + comboBox.setSelectedItem(delayInSeconds); + comboBox.setName("set Delay"); + comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JTextField createTextField(final String reminderText) { + final JTextField textField = new JTextField(20); + textField.setName("Field"); + textField.setText(reminderText); + return textField; + } + + private JButton createOkButton() { + final JButton button = new JButton("ok"); + button.setName("OK"); + return button; + } + + private void updateReminder() { + okButton.addActionListener(e -> this.dispose()); + okButton.addActionListener(e -> { + final int periodInSeconds = getTimeInSeconds(period); + final int delayInSeconds = getTimeInSeconds(delay); + final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds); + ((DefaultListModel) reminderApplication.getReminders()).set(reminderIndex, reminder); + }); + okButton.addActionListener(e -> scheduleReminder(textField, delay, period)); + } + + private void scheduleReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int periodInSeconds = getTimeInSeconds(period); + if (periodInSeconds == 0) + scheduleNonRepeatedReminder(textField, delay); + else + scheduleRepeatedReminder(textField, delay, period); + } + + private void scheduleRepeatedReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int delayInSeconds = getTimeInSeconds(delay); + final int periodInSeconds = getTimeInSeconds(period); + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds)); + } + + private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox delay) { + final int delayInSeconds = getTimeInSeconds(delay); + final int periodInSeconds = 0; + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds)); + + } + + private int getTimeInSeconds(final JComboBox comboBox) { + if (comboBox != null && comboBox.getSelectedItem() != null) + return ((Integer) comboBox.getSelectedItem()); + else + return 0; + } + + private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) { + return new TimerTask() { + @Override + public void run() { + new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds); + } + }; + } + + private JButton createCancelButton() { + final JButton button = new JButton("cancel"); + button.setName("Cancel"); + button.addActionListener(e -> this.dispose()); + return button; + } + + private static JLabel createLabel(final String text, final String name) { + JLabel label = new JLabel(text); + label.setName(name); + return label; + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java new file mode 100644 index 0000000000..8f6ff336ed --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java @@ -0,0 +1,33 @@ +package reminderapplication; + +public class Reminder { + + private static String REMINDER_FORMAT = "Reminder Text: %s; Delay: %d; Period: %d;"; + + private final String name; + private final int delay; + private final int period; + + public Reminder(final String name, final int delay, final int period) { + this.name = name; + this.delay = delay; + this.period = period; + } + + public String getName() { + return name; + } + + public int getDelay() { + return delay; + } + + public int getPeriod() { + return period; + } + + @Override + public String toString() { + return REMINDER_FORMAT.formatted(name, delay, period); + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java new file mode 100644 index 0000000000..3a1623219c --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java @@ -0,0 +1,186 @@ +package reminderapplication; + +import static reminderapplication.ConstraintsBuilder.*; + +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; + +public class ReminderFrame extends JFrame { + + private static Timer TIMER = new Timer(); + private final TimeReminderApplication reminderApplication; + private final JLabel reminderTextLabel; + private final JLabel repeatPeriodLabel; + private final JLabel setDelayLabel; + private final JComboBox delay; + private final JComboBox period; + private final JButton cancelButton; + private final JButton okButton; + private final JTextField textField; + private final JLabel delaysLabel; + private final JLabel periodLabel; + + public ReminderFrame(TimeReminderApplication reminderApp) throws HeadlessException { + this.reminderApplication = reminderApp; + textField = createTextField(); + delay = createDelayComboBox(); + period = createPeriodComboBox(); + cancelButton = createCancelButton(); + okButton = createOkButton(); + reminderTextLabel = createReminderTextLabel(); + repeatPeriodLabel = createRepeatPeriodLabel(); + setDelayLabel = createSetDelayLabel(); + delaysLabel = createDelaysLabel(); + periodLabel = createPeriodLabel(); + configureVisualRepresentation(); + configureActions(); + } + + private void configureActions() { + createNewReminder(); + } + + private void configureVisualRepresentation() { + configureFrame(); + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); + add(reminderTextLabel, constraint(0,0)); + add(repeatPeriodLabel, constraint(1,0)); + add(setDelayLabel, constraint(2,0)); + add(textField, constraint(0, 1)); + add(delay, constraint(1, 1)); + add(period, constraint(2, 1)); + add(delaysLabel, constraint(1,3)); + add(periodLabel, constraint(2,3)); + add(okButton, constraint(1, 4)); + add(cancelButton, constraint(2, 4)); + pack(); + setVisible(true); + } + + private void configureFrame() { + setTitle("Set Reminder"); + setName("Set Reminder"); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + private static JLabel createSetDelayLabel() { + return createLabel("Set Delay", "Set Delay Label"); + } + + private static JLabel createRepeatPeriodLabel() { + return createLabel("Set Period", "Set Repeat Period Label"); + } + + private static JLabel createReminderTextLabel() { + return createLabel("Reminder Text", "Reminder Text Label"); + } + + private JLabel createPeriodLabel() { + return createLabel("0", "Period label"); + } + + private JLabel createDelaysLabel() { + return createLabel("30", "Delays Label"); + } + + private JComboBox createPeriodComboBox() { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20})); + comboBox.setName("set Period"); + comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JComboBox createDelayComboBox() { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5})); + comboBox.setName("set Delay"); + comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JTextField createTextField() { + final JTextField textField = new JTextField(20); + textField.setName("Field"); + return textField; + } + + private JButton createOkButton() { + final JButton button = new JButton("ok"); + button.setName("OK"); + return button; + } + + private void createNewReminder() { + + okButton.addActionListener(e -> this.dispose()); + okButton.addActionListener(e -> { + final int periodInSeconds = getTimeInSeconds(period); + final int delayInSeconds = getTimeInSeconds(delay); + final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds); + ((DefaultListModel) reminderApplication.getReminders()).addElement(reminder); + }); + okButton.addActionListener(e -> scheduleReminder(textField, delay, period)); + } + + private void scheduleReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int periodInSeconds = getTimeInSeconds(period); + if (periodInSeconds == 0) + scheduleNonRepeatedReminder(textField, delay); + else + scheduleRepeatedReminder(textField, delay, period); + } + + private void scheduleRepeatedReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int delayInSeconds = getTimeInSeconds(delay) + 200; + final int periodInSeconds = getTimeInSeconds(period); + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds)); + } + + private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox delay) { + final int delayInSeconds = getTimeInSeconds(delay); + final int periodInSeconds = 0; + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds)); + + } + + private int getTimeInSeconds(final JComboBox comboBox) { + if (comboBox != null && comboBox.getSelectedItem() != null) + return ((Integer) comboBox.getSelectedItem()); + else + return 0; + } + + private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) { + return new TimerTask() { + @Override + public void run() { + new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds); + } + }; + } + + private JButton createCancelButton() { + final JButton button = new JButton("cancel"); + button.setName("Cancel"); + button.addActionListener(e -> this.dispose()); + return button; + } + + private static JLabel createLabel(final String text, final String name) { + JLabel label = new JLabel(text); + label.setName(name); + return label; + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java new file mode 100644 index 0000000000..d41343cb6d --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java @@ -0,0 +1,151 @@ +package reminderapplication; + +import static reminderapplication.ConstraintsBuilder.*; + +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; + +public class ReminderPopupFrame extends JFrame { + + private static final Timer TIMER = new Timer(); + private final int AUTOMATIC_CLOSE_TIME_IN_SECONDS = 10; + private final TimeReminderApplication reminderApplication; + private final JLabel reminderTextLabel; + private final JLabel repeatPeriodLabel; + private final JLabel setDelayLabel; + private final JComboBox delay; + private final JComboBox period; + private final JButton cancelButton; + private final JButton okButton; + private final JTextField textField; + private final JLabel delaysLabel; + private final JLabel periodLabel; + + public ReminderPopupFrame(TimeReminderApplication reminderApp, final String text, final Integer delayInSeconds, final Integer periodInSeconds) throws HeadlessException { + this.reminderApplication = reminderApp; + textField = createTextField(text); + delay = createDelayComboBox(delayInSeconds); + period = createPeriodComboBox(periodInSeconds); + cancelButton = createCancelButton(); + okButton = createDisabledOkButton(); + reminderTextLabel = createReminderTextLabel(); + repeatPeriodLabel = createRepeatPeriodLabel(); + setDelayLabel = createSetDelayLabel(); + delaysLabel = createDelaysLabel(); + periodLabel = createPeriodLabel(); + configureVisualRepresentation(); + configureActions(); + } + + private void configureActions() { + scheduleClosing(); + } + + private void scheduleClosing() { + final TimerTask timerTask = new TimerTask() { + @Override + public void run() { + ReminderPopupFrame.this.dispose(); + } + }; + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(AUTOMATIC_CLOSE_TIME_IN_SECONDS)); + } + + private void configureVisualRepresentation() { + configureFrame(); + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); + add(reminderTextLabel, constraint(0,0)); + add(repeatPeriodLabel, constraint(1,0)); + add(setDelayLabel, constraint(2,0)); + add(textField, constraint(0, 1)); + add(delay, constraint(1, 1)); + add(period, constraint(2, 1)); + add(delaysLabel, constraint(1,3)); + add(periodLabel, constraint(2,3)); + add(okButton, constraint(1, 4)); + add(cancelButton, constraint(2, 4)); + pack(); + setVisible(true); + } + + private void configureFrame() { + setTitle("Set Reminder"); + setName("Set Reminder"); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + private static JLabel createSetDelayLabel() { + return createLabel("Set Delay", "Set Delay Label"); + } + + private static JLabel createRepeatPeriodLabel() { + return createLabel("Set Period", "Set Repeat Period Label"); + } + + private static JLabel createReminderTextLabel() { + return createLabel("Reminder Text", "Reminder Text Label"); + } + + private JLabel createPeriodLabel() { + return createLabel("0", "Period label"); + } + + private JLabel createDelaysLabel() { + return createLabel("30", "Delays Label"); + } + + private JComboBox createPeriodComboBox(final Integer periodInSeconds) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20})); + comboBox.setName("set Period"); + comboBox.setSelectedItem(periodInSeconds); + comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JComboBox createDelayComboBox(Integer delay) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5})); + comboBox.setSelectedItem(delay); + comboBox.setName("set Delay"); + comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JTextField createTextField(final String text) { + final JTextField textField = new JTextField(20); + textField.setName("Field"); + textField.setText(text); + return textField; + } + + private JButton createDisabledOkButton() { + final JButton button = new JButton("ok"); + button.setName("OK"); + button.setEnabled(false); + return button; + } + + private JButton createCancelButton() { + final JButton button = new JButton("cancel"); + button.setName("Cancel"); + button.addActionListener(e -> this.dispose()); + return button; + } + + private static JLabel createLabel(final String text, final String name) { + JLabel label = new JLabel(text); + label.setName(name); + return label; + } + +} diff --git a/parent-boot-3/pom.xml b/parent-boot-3/pom.xml index dcb5e179bb..dabcd7850b 100644 --- a/parent-boot-3/pom.xml +++ b/parent-boot-3/pom.xml @@ -230,7 +230,7 @@ 3.3.0 2.22.2 - 3.0.0 + 3.1.2 5.8.2 0.9.17 17 diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java index 4c1e73e530..7e2dbd93e9 100644 --- a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java @@ -27,14 +27,15 @@ public class QueryService { return entityManager.createQuery(query).getResultList(); } - public BookRecord findBookById(Long id) { + public BookRecord findBookByTitle(String title) { TypedQuery query = entityManager - .createQuery("SELECT new com.baeldung.recordswithjpa.records.BookRecord(b.id, b.title, b.author, b.isbn) " + - "FROM Book b WHERE b.id = :id", BookRecord.class); - query.setParameter("id", id); + .createQuery("SELECT new com.baeldung.recordswithjpa.records.BookRecord(b.id, b.title, b.author, b.isbn) " + + "FROM Book b WHERE b.title = :title", BookRecord.class); + query.setParameter("title", title); return query.getSingleResult(); } + public List findAllBooksUsingMapping() { Query query = entityManager.createNativeQuery("SELECT * FROM book", "BookRecordMapping"); return query.getResultList(); diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java new file mode 100644 index 0000000000..4f2fa664db --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java @@ -0,0 +1,9 @@ +package com.baeldung.recordswithjpa.embeddable; + +import jakarta.persistence.Embeddable; + +@Embeddable +public record Author( + String firstName, + String lastName +) {} diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java new file mode 100644 index 0000000000..7debfb5071 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java @@ -0,0 +1,23 @@ +package com.baeldung.recordswithjpa.embeddable; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.spi.EmbeddableInstantiator; +import org.hibernate.metamodel.spi.ValueAccess; + +public class AuthorInstallator implements EmbeddableInstantiator { + + public boolean isInstance(Object object, SessionFactoryImplementor sessionFactory) { + return object instanceof Author; + } + + public boolean isSameClass(Object object, SessionFactoryImplementor sessionFactory) { + return object.getClass().equals(Author.class); + } + + @Override + public Object instantiate(final ValueAccess valueAccess, final SessionFactoryImplementor sessionFactoryImplementor) { + final String firstName = valueAccess.getValue(0, String.class); + final String secondName = valueAccess.getValue(1, String.class); + return new Author(firstName, secondName); + } +} diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java new file mode 100644 index 0000000000..74bd7d78ae --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java @@ -0,0 +1,65 @@ +package com.baeldung.recordswithjpa.embeddable; + +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import org.hibernate.annotations.EmbeddableInstantiator; + +@Entity +@Table(name = "embeadable_author_book") +public class EmbeddableBook { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String title; + @Embedded + @EmbeddableInstantiator(AuthorInstallator.class) + private Author author; + private String isbn; + + public EmbeddableBook() { + } + + public EmbeddableBook(Long id, String title, Author author, String isbn) { + this.id = id; + this.title = title; + this.author = author; + this.isbn = isbn; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java new file mode 100644 index 0000000000..3d6e558050 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.recordswithjpa.repository; + +import com.baeldung.recordswithjpa.embeddable.EmbeddableBook; +import com.baeldung.recordswithjpa.embeddable.Author; +import java.util.List; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +public interface EmbeddableBookRepository extends CrudRepository { + @Query("SELECT b FROM EmbeddableBook b WHERE b.author = :author") + List findBookByAuthor(@Param("author") Author author); + +} diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java index 011895e7fa..09c6805544 100644 --- a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java +++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java @@ -1,13 +1,8 @@ package com.baeldung.recordswithjpa; -import com.baeldung.recordswithjpa.entity.Book; import com.baeldung.recordswithjpa.records.BookRecord; -import com.baeldung.recordswithjpa.repository.BookRepository; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @@ -27,8 +22,8 @@ public class QueryServiceIntegrationTest extends RecordsAsJpaIntegrationTest { @Test void findBookById() { - BookRecord bookById = queryService.findBookById(1L); - assertEquals("The Lord of the Rings", bookById.title()); + BookRecord bookByTitle = queryService.findBookByTitle("The Lord of the Rings"); + assertNotNull(bookByTitle); } @Test diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java new file mode 100644 index 0000000000..2d0b834def --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java @@ -0,0 +1,31 @@ +package com.baeldung.recordswithjpa; + +import com.baeldung.recordswithjpa.embeddable.Author; +import com.baeldung.recordswithjpa.embeddable.EmbeddableBook; +import com.baeldung.recordswithjpa.repository.EmbeddableBookRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class RecordsAsJpaEmbeddableIntegrationTest { + @Autowired + protected EmbeddableBookRepository bookRepository; + + @BeforeEach + void setUp() { + + Author author = new Author("J.R.R.", "Tolkien"); + EmbeddableBook book1 = new EmbeddableBook(null, "The Lord of the Rings", author, "978-0544003415"); + EmbeddableBook book2 = new EmbeddableBook(null, "The Hobbit", author, "978-0547928227"); + + bookRepository.save(book1); + bookRepository.save(book2); + } + + @AfterEach + void tearDown() { + bookRepository.deleteAll(); + } +} diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java new file mode 100644 index 0000000000..8f9e9680ba --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java @@ -0,0 +1,16 @@ +package com.baeldung.recordswithjpa.repository; + +import com.baeldung.recordswithjpa.RecordsAsJpaEmbeddableIntegrationTest; +import com.baeldung.recordswithjpa.embeddable.Author; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class EmbeddableBookRepositoryIntegrationTest extends RecordsAsJpaEmbeddableIntegrationTest { + + @Test + void findBookByAuthor() { + assertEquals(2, bookRepository.findBookByAuthor(new Author("J.R.R.", "Tolkien")).size()); + } + +} From 938b6a4ee27c6a8a63a68878570c3125d997e351 Mon Sep 17 00:00:00 2001 From: Tapan Avasthi Date: Sat, 5 Aug 2023 19:14:19 +0530 Subject: [PATCH 09/16] BAEL-6831: Convert an int[] Array to HashSet in Java (#14525) Co-authored-by: Tapan Avasthi --- .../PrimitiveIntArrayToHashSetUnitTest.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java diff --git a/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java new file mode 100644 index 0000000000..ca658d3e97 --- /dev/null +++ b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.array.conversions; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Test; + +import com.google.common.primitives.Ints; + +public class PrimitiveIntArrayToHashSetUnitTest { + int[] arr = { 1, 2, 3, 4, 5 }; + HashSet expected = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5)); + + @Test + public void givenPrimitiveIntArray_whenConvertingByDirectConstructor_thenGiveWrongResult() { + HashSet result = new HashSet<>(Arrays.asList(arr)); + assertEquals(1, result.size()); + assertNotEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByLoop_thenSuccess() { + HashSet result = new HashSet<>(); + for (int num : arr) { + result.add(num); + } + assertEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByStreams_thenSuccess() { + HashSet result = Arrays.stream(arr).boxed().collect(Collectors.toCollection(HashSet::new)); + assertEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByArrayUtils_thenSuccess() { + HashSet result = new HashSet<>(Arrays.asList(ArrayUtils.toObject(arr))); + assertEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByGuava_thenSuccess() { + HashSet result = new HashSet<>(Ints.asList(arr)); + assertEquals(expected, result); + } + +} From 57aa0edf16c3d0770f19aef1c6b731fd1d339737 Mon Sep 17 00:00:00 2001 From: GaetanoPiazzolla Date: Sat, 5 Aug 2023 15:57:27 +0200 Subject: [PATCH 10/16] JAVA-22203 | Fixed race condition. --- .../EmbeddedActiveMqIntegrationTest.java | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java index 0625020a06..e934b66360 100644 --- a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java +++ b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java @@ -8,8 +8,6 @@ import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.junit.EmbeddedActiveMQBroker; -import org.junit.AfterClass; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,41 +36,33 @@ public class EmbeddedActiveMqIntegrationTest { @SpyBean private MessageSender messageSender; - @BeforeClass - public static void start() { - embeddedBroker.start(); - } - - @AfterClass - public static void stop() { - embeddedBroker.stop(); - } - @Test public void whenListening_thenReceivingCorrectMessage() throws JMSException, InterruptedException { String queueName = "queue-1"; String messageText = "Test message"; + assertEquals(0, embeddedBroker.getDestination(queueName).getDestinationStatistics().getDispatched().getCount()); + assertEquals(0, embeddedBroker.getDestination(queueName).getDestinationStatistics().getMessages().getCount()); + embeddedBroker.pushMessage(queueName, messageText); - Thread.sleep(1000L); - assertEquals(1, embeddedBroker.getMessageCount(queueName)); ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(TextMessage.class); - Mockito.verify(messageListener, Mockito.timeout(100)) .sampleJmsListenerMethod(messageCaptor.capture()); - + TextMessage receivedMessage = messageCaptor.getValue(); assertEquals(messageText, receivedMessage.getText()); + + assertEquals(1, embeddedBroker.getDestination(queueName).getDestinationStatistics().getDispatched().getCount()); + assertEquals(0, embeddedBroker.getDestination(queueName).getDestinationStatistics().getMessages().getCount()); } @Test - public void whenSendingMessage_thenCorrectQueueAndMessageText() throws JMSException, InterruptedException { + public void whenSendingMessage_thenCorrectQueueAndMessageText() throws JMSException { String queueName = "queue-2"; String messageText = "Test message"; messageSender.sendTextMessage(queueName, messageText); - Thread.sleep(1000L); assertEquals(1, embeddedBroker.getMessageCount(queueName)); TextMessage sentMessage = embeddedBroker.peekTextMessage(queueName); assertEquals(messageText, sentMessage.getText()); From 2bb0e319fba2f8736774d08904052ba7987d2a69 Mon Sep 17 00:00:00 2001 From: GaetanoPiazzolla Date: Sat, 5 Aug 2023 16:00:34 +0200 Subject: [PATCH 11/16] JAVA-22203 | removed unused throws --- .../spring/jms/testing/EmbeddedActiveMqIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java index e934b66360..f88cf81cf7 100644 --- a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java +++ b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java @@ -37,7 +37,7 @@ public class EmbeddedActiveMqIntegrationTest { private MessageSender messageSender; @Test - public void whenListening_thenReceivingCorrectMessage() throws JMSException, InterruptedException { + public void whenListening_thenReceivingCorrectMessage() throws JMSException { String queueName = "queue-1"; String messageText = "Test message"; From ff42782e3b5f0300be38d13c7c994ee936232a3d Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 5 Aug 2023 21:15:55 +0300 Subject: [PATCH 12/16] comment suanshu library - see JAVA-24004 --- libraries-data-2/pom.xml | 6 +++++- .../src/main/java/com/baeldung/suanshu/SuanShuMath.java | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml index b9b785cebb..e19067daa3 100644 --- a/libraries-data-2/pom.xml +++ b/libraries-data-2/pom.xml @@ -86,11 +86,13 @@ spring-web ${spring.version} + org.derive4j derive4j @@ -160,7 +162,8 @@ - + + 1.16.1 diff --git a/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java b/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java index ce7bc60a3a..fb53d97c32 100644 --- a/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java +++ b/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java @@ -15,7 +15,7 @@ import org.slf4j.LoggerFactory; import java.util.List; class SuanShuMath { - +/** fixing in JAVA-24004 private static final Logger log = LoggerFactory.getLogger(SuanShuMath.class); public static void main(String[] args) throws Exception { @@ -137,5 +137,5 @@ class SuanShuMath { List roots = solver.solve(p); log.info("Finding polynomial roots: {}", roots); } - +*// } From db65a7002bacd1dad37f82f12bf3ec9361f1ffff Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 5 Aug 2023 21:24:21 +0300 Subject: [PATCH 13/16] comment suanshu library - see JAVA-24004 --- .../src/main/java/com/baeldung/suanshu/SuanShuMath.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java b/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java index fb53d97c32..a5365871c6 100644 --- a/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java +++ b/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java @@ -1,5 +1,6 @@ package com.baeldung.suanshu; +/* import com.numericalmethod.suanshu.algebra.linear.matrix.doubles.Matrix; import com.numericalmethod.suanshu.algebra.linear.matrix.doubles.matrixtype.dense.DenseMatrix; import com.numericalmethod.suanshu.algebra.linear.matrix.doubles.operation.Inverse; @@ -9,6 +10,7 @@ import com.numericalmethod.suanshu.analysis.function.polynomial.Polynomial; import com.numericalmethod.suanshu.analysis.function.polynomial.root.PolyRoot; import com.numericalmethod.suanshu.analysis.function.polynomial.root.PolyRootSolver; import com.numericalmethod.suanshu.number.complex.Complex; +*/ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -137,5 +139,5 @@ class SuanShuMath { List roots = solver.solve(p); log.info("Finding polynomial roots: {}", roots); } -*// +*/ } From d06645ee6e392eafb731c7acc85abed7f74886c7 Mon Sep 17 00:00:00 2001 From: Gaetano Piazzolla Date: Sun, 6 Aug 2023 07:10:03 +0200 Subject: [PATCH 14/16] JAVA-23319 | Moving DualPrintStream (#14524) * JAVA-23319 | moving DualPrintStream * JAVA-23319 | adding checkerror --- .../outputtofile/DualPrintStream.java | 49 +++++++++++++++++++ .../ConsoleOutputToFileUnitTest.java | 40 --------------- 2 files changed, 49 insertions(+), 40 deletions(-) create mode 100644 core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java diff --git a/core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java b/core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java new file mode 100644 index 0000000000..17e057aba9 --- /dev/null +++ b/core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java @@ -0,0 +1,49 @@ +package com.baeldung.outputtofile; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + +class DualPrintStream extends PrintStream { + private final PrintStream second; + + public DualPrintStream(OutputStream main, PrintStream second) { + super(main); + this.second = second; + } + + @Override + public void close() { + super.close(); + second.close(); + } + + @Override + public void flush() { + super.flush(); + second.flush(); + } + + @Override + public void write(byte[] buf, int off, int len) { + super.write(buf, off, len); + second.write(buf, off, len); + } + + @Override + public void write(int b) { + super.write(b); + second.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + super.write(b); + second.write(b); + } + + @Override + public boolean checkError() { + return super.checkError() && second.checkError(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java b/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java index c7f643b148..24157d4efa 100644 --- a/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java +++ b/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; -import java.io.OutputStream; import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Path; @@ -15,45 +14,6 @@ import org.junit.jupiter.api.io.TempDir; import com.google.common.collect.Lists; -class DualPrintStream extends PrintStream { - private final PrintStream second; - - public DualPrintStream(OutputStream main, PrintStream second) { - super(main); - this.second = second; - } - - @Override - public void close() { - super.close(); - second.close(); - } - - @Override - public void flush() { - super.flush(); - second.flush(); - } - - @Override - public void write(byte[] buf, int off, int len) { - super.write(buf, off, len); - second.write(buf, off, len); - } - - @Override - public void write(int b) { - super.write(b); - second.write(b); - } - - @Override - public void write(byte[] b) throws IOException { - super.write(b); - second.write(b); - } -} - public class ConsoleOutputToFileUnitTest { // @formatter:off From d6af55c8f73d4b1d3eeb6ae47d43bc6abdffd4ba Mon Sep 17 00:00:00 2001 From: BHARATH GANESH Date: Sun, 6 Aug 2023 18:10:47 +0530 Subject: [PATCH 15/16] BAEL-6504: Convert Json Array to Java list (#14049) --- json-modules/json-conversion/README.md | 5 ++ json-modules/json-conversion/pom.xml | 39 ++++++++++++ .../ConvertJsonArrayToList.java | 31 ++++++++++ .../src/main/java/entities/Product.java | 29 +++++++++ .../src/main/resources/logback.xml | 13 ++++ .../ConvertJsonArrayToListUnitTest.java | 60 +++++++++++++++++++ .../src/test/resources/.gitignore | 13 ++++ .../src/test/resources/logback-test.xml | 19 ++++++ json-modules/pom.xml | 1 + 9 files changed, 210 insertions(+) create mode 100644 json-modules/json-conversion/README.md create mode 100644 json-modules/json-conversion/pom.xml create mode 100644 json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java create mode 100644 json-modules/json-conversion/src/main/java/entities/Product.java create mode 100644 json-modules/json-conversion/src/main/resources/logback.xml create mode 100644 json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java create mode 100644 json-modules/json-conversion/src/test/resources/.gitignore create mode 100644 json-modules/json-conversion/src/test/resources/logback-test.xml diff --git a/json-modules/json-conversion/README.md b/json-modules/json-conversion/README.md new file mode 100644 index 0000000000..7094486afe --- /dev/null +++ b/json-modules/json-conversion/README.md @@ -0,0 +1,5 @@ +## JSON-CONVERSIONS + +This module contains articles about JSON Conversions + +### Relevant Articles: \ No newline at end of file diff --git a/json-modules/json-conversion/pom.xml b/json-modules/json-conversion/pom.xml new file mode 100644 index 0000000000..1af13cbbcb --- /dev/null +++ b/json-modules/json-conversion/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + org.baeldung + json-conversion + json-conversion + + + json-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + + org.json + json + ${json.version} + + + com.google.code.gson + gson + ${gson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + 20211205 + 2.10.1 + + + diff --git a/json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java b/json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java new file mode 100644 index 0000000000..88701e1955 --- /dev/null +++ b/json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java @@ -0,0 +1,31 @@ +package com.baeldung.jsonarraytolist; + +import java.lang.reflect.Type; +import java.util.List; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import entities.Product; + +public class ConvertJsonArrayToList { + + public List convertJsonArrayUsingGsonLibrary(String jsonArray) { + Gson gson = new Gson(); + + Type listType = new TypeToken>() {}.getType(); + + List gsonList = gson.fromJson(jsonArray, listType); + return gsonList; + } + + public List convertJsonArrayUsingJacksonLibrary(String jsonArray) throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + + List typeReferenceList = objectMapper.readValue(jsonArray, new TypeReference>() {}); + return typeReferenceList; + } +} diff --git a/json-modules/json-conversion/src/main/java/entities/Product.java b/json-modules/json-conversion/src/main/java/entities/Product.java new file mode 100644 index 0000000000..64ab5064cc --- /dev/null +++ b/json-modules/json-conversion/src/main/java/entities/Product.java @@ -0,0 +1,29 @@ +package entities; + +public class Product { + + private int id; + private String name; + private String description; + + public Product() {} + + public Product(int id, String name, String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + +} diff --git a/json-modules/json-conversion/src/main/resources/logback.xml b/json-modules/json-conversion/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/json-modules/json-conversion/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/json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java b/json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java new file mode 100644 index 0000000000..d88b75f0ce --- /dev/null +++ b/json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.jsonarraytolist; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; + +import entities.Product; + +public class ConvertJsonArrayToListUnitTest { + + private static ObjectMapper objectMapper; + private static List productList; + private ConvertJsonArrayToList obj; + + @Before + public void setup() { + obj = new ConvertJsonArrayToList(); + productList = getProducts(); + objectMapper = new ObjectMapper(); + } + + private List getProducts() { + List productList = new ArrayList<>(); + Product prod1 = new Product(1, "Icecream", "Sweet and cold"); + Product prod2 = new Product(2, "Apple", "Red and sweet"); + Product prod3 = new Product(3, "Carrot", "Good for eyes"); + productList.add(prod1); + productList.add(prod2); + productList.add(prod3); + return productList; + } + + @Test + public void whenUsingGsonLibrary_thenCompareTwoProducts() { + Gson gson = new Gson(); + String jsonArray = gson.toJson(productList); + List arrList = obj.convertJsonArrayUsingGsonLibrary(jsonArray); + Assert.assertEquals(productList.get(0).getId(), arrList.get(0).getId()); + Assert.assertEquals(productList.get(1).getDescription(), arrList.get(1).getDescription()); + Assert.assertEquals(productList.get(2).getName(), arrList.get(2).getName()); + } + + @Test + public void whenUsingJacksonLibrary_thenCompareTwoProducts() throws JsonProcessingException { + String jsonArray = objectMapper.writeValueAsString(productList); + List arrList = obj.convertJsonArrayUsingJacksonLibrary(jsonArray); + + Assert.assertEquals(productList.get(0).getId(), arrList.get(0).getId()); + Assert.assertEquals(productList.get(1).getDescription(), arrList.get(1).getDescription()); + Assert.assertEquals(productList.get(2).getName(), arrList.get(2).getName()); + } + +} diff --git a/json-modules/json-conversion/src/test/resources/.gitignore b/json-modules/json-conversion/src/test/resources/.gitignore new file mode 100644 index 0000000000..df6ca255ed --- /dev/null +++ b/json-modules/json-conversion/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear diff --git a/json-modules/json-conversion/src/test/resources/logback-test.xml b/json-modules/json-conversion/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..b64f069594 --- /dev/null +++ b/json-modules/json-conversion/src/test/resources/logback-test.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + diff --git a/json-modules/pom.xml b/json-modules/pom.xml index 15a066daa4..82314e0edf 100644 --- a/json-modules/pom.xml +++ b/json-modules/pom.xml @@ -16,6 +16,7 @@ json json-2 + json-conversion json-path gson gson-2 From 1a4d59a3ab450c1c7d381c69346b2bcd396101fb Mon Sep 17 00:00:00 2001 From: Kai Yuan Date: Sun, 6 Aug 2023 19:49:57 +0200 Subject: [PATCH 16/16] Remove Duplicate Values From HashMap in Java (#14519) * Remove Duplicate Values From HashMap in Java * fix the typo in the package name --- .../RemoveDuplicateValuesUnitTest.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java diff --git a/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java new file mode 100644 index 0000000000..080bc46289 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.map.removeuplicate; + +import static java.util.stream.Collectors.toMap; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableMap; + +public class RemoveDuplicateValuesUnitTest { + private Map initDevMap() { + Map devMap = new HashMap<>(); + devMap.put("Tom", "Linux"); + devMap.put("Kent", "Linux"); + + devMap.put("Bob", "MacOS"); + devMap.put("Eric", "MacOS"); + + devMap.put("Peter", "Windows"); + devMap.put("Saajan", "Windows"); + devMap.put("Jan", "Windows"); + + devMap.put("Kevin", "FreeBSD"); + return devMap; + } + + @Test + void whenUsingReverseMap_thenDuplicateValuesAreRemoved() { + Map devMap = initDevMap(); + Map tmpReverseMap = new HashMap<>(); + Map result = new HashMap<>(); + for (String name : devMap.keySet()) { + tmpReverseMap.put(devMap.get(name), name); + } + + for (String os : tmpReverseMap.keySet()) { + result.put(tmpReverseMap.get(os), os); + } + + assertThat(result.values()).hasSize(4) + .containsExactlyInAnyOrder("Windows", "MacOS", "Linux", "FreeBSD"); + } + + @Test + void whenUsingStream_thenDuplicateValuesAreRemoved() { + Map devMap = initDevMap(); + Map result = devMap.entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey, (keyInMap, keyNew) -> keyInMap)) + .entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey)); + + assertThat(result.values()).hasSize(4) + .containsExactlyInAnyOrder("Windows", "MacOS", "Linux", "FreeBSD"); + } + + @Test + void whenUsingStream_thenDuplicateValuesAreRemovedAndOnlyLongestNamesExist() { + Map devMap = initDevMap(); + + //@formatter:off + Map expected = ImmutableMap.of( + "Eric", "MacOS", + "Kent", "Linux", + "Saajan", "Windows", + "Kevin", "FreeBSD"); + //@formatter:on + + Map result = devMap.entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey, (k1, k2) -> k1.length() > k2.length() ? k1 : k2)) + .entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey)); + + assertThat(result).hasSize(4) + .isEqualTo(expected); + } +} \ No newline at end of file