3333import software .amazon .awssdk .services .s3 .model .CopyObjectRequest ;
3434import software .amazon .awssdk .services .s3 .model .CreateBucketConfiguration ;
3535import software .amazon .awssdk .services .s3 .model .CreateBucketRequest ;
36+ import software .amazon .awssdk .services .s3 .model .CreateBucketResponse ;
3637import software .amazon .awssdk .services .s3 .model .CreateSessionRequest ;
38+ import software .amazon .awssdk .services .s3 .model .CreateSessionResponse ;
3739import software .amazon .awssdk .services .s3 .model .DataRedundancy ;
3840import software .amazon .awssdk .services .s3 .model .Delete ;
3941import software .amazon .awssdk .services .s3 .model .DeleteBucketRequest ;
@@ -116,7 +118,7 @@ private static Ec2AsyncClient getEc2AsyncClient() {
116118 }
117119
118120 /**
119- * Deletes the specified S3 bucket and all the objects within it in an asynchronous manner .
121+ * Deletes the specified S3 bucket and all the objects within it asynchronously .
120122 *
121123 * @param s3AsyncClient the S3 asynchronous client to use for the operations
122124 * @param bucketName the name of the S3 bucket to be deleted
@@ -175,10 +177,10 @@ public CompletableFuture<WaiterResponse<HeadBucketResponse>> deleteBucketAndObje
175177 }
176178
177179 /**
178- * Lists the objects in an S3 bucket asynchronously using the AWS SDK .
180+ * Lists the objects in an S3 bucket asynchronously.
179181 *
180- * @param s3Client the S3 async client to use for the operation
181- * @param bucketName the name of the S3 bucket to list objects from
182+ * @param s3Client the S3 async client to use for the operation
183+ * @param bucketName the name of the the S3 bucket containing the objects to list
182184 * @return a {@link CompletableFuture} that contains the list of object keys in the specified bucket
183185 */
184186 public CompletableFuture <List <String >> listObjectsAsync (S3AsyncClient s3Client , String bucketName ) {
@@ -197,6 +199,14 @@ public CompletableFuture<List<String>> listObjectsAsync(S3AsyncClient s3Client,
197199 });
198200 }
199201
202+ /**
203+ * Retrieves an object from an Amazon S3 bucket asynchronously.
204+ *
205+ * @param s3Client the S3 async client to use for the operation
206+ * @param bucketName the name of the S3 bucket containing the object
207+ * @param keyName the unique identifier (key) of the object to retrieve
208+ * @return a {@link CompletableFuture} that, when completed, contains the object's content as a {@link ResponseBytes} of {@link GetObjectResponse}
209+ */
200210 public CompletableFuture <ResponseBytes <GetObjectResponse >> getObjectAsync (S3AsyncClient s3Client , String bucketName , String keyName ) {
201211 GetObjectRequest objectRequest = GetObjectRequest .builder ()
202212 .key (keyName )
@@ -206,7 +216,6 @@ public CompletableFuture<ResponseBytes<GetObjectResponse>> getObjectAsync(S3Asyn
206216 // Get the object asynchronously and transform it into a byte array
207217 return s3Client .getObject (objectRequest , AsyncResponseTransformer .toBytes ())
208218 .exceptionally (exception -> {
209- // Handle the exception by checking the cause
210219 Throwable cause = exception .getCause ();
211220 if (cause instanceof S3Exception ) {
212221 throw new CompletionException ("Failed to get the object. Reason: " + ((S3Exception ) cause ).awsErrorDetails ().errorMessage (), cause );
@@ -218,6 +227,7 @@ public CompletableFuture<ResponseBytes<GetObjectResponse>> getObjectAsync(S3Asyn
218227 return response ;
219228 });
220229 }
230+
221231 /**
222232 * Asynchronously copies an object from one S3 bucket to another.
223233 *
@@ -250,40 +260,41 @@ public CompletableFuture<Void> copyObjectAsync(S3AsyncClient s3Client, String so
250260 }
251261
252262 /**
253- * Creates an asynchronous session for the specified S3 bucket.
263+ * Asynchronously creates a session for the specified S3 bucket.
254264 *
255- * @param s3Client the S3 asynchronous client to use for creating the session
265+ * @param s3Client the S3 asynchronous client to use for creating the session
256266 * @param bucketName the name of the S3 bucket for which to create the session
257267 * @return a {@link CompletableFuture} that completes when the session is created, or throws a {@link CompletionException} if an error occurs
258268 */
259- public CompletableFuture <Void > createSessionAsync (S3AsyncClient s3Client , String bucketName ) {
269+ public CompletableFuture <CreateSessionResponse > createSessionAsync (S3AsyncClient s3Client , String bucketName ) {
260270 CreateSessionRequest request = CreateSessionRequest .builder ()
261271 .bucket (bucketName )
262272 .build ();
263273
264274 return s3Client .createSession (request )
265- .thenRun (() -> logger .info ("Created session for bucket: " + bucketName ))
266- .whenComplete ((ignored , exception ) -> {
275+ .whenComplete ((response , exception ) -> {
267276 if (exception != null ) {
268277 Throwable cause = exception .getCause ();
269278 if (cause instanceof S3Exception ) {
270279 throw new CompletionException ("Couldn't create the session. Reason: " + ((S3Exception ) cause ).awsErrorDetails ().errorMessage (), cause );
271280 }
272281 throw new CompletionException ("Unexpected error occurred while creating session" , exception );
273282 }
283+ logger .info ("Created session for bucket: " + bucketName );
274284 });
285+
275286 }
276287
277288 /**
278289 * Creates a new S3 directory bucket in a specified Zone (For example, a
279290 * specified Availability Zone in this code example).
280291 *
281- * @param s3Client The S3 client used to create the bucket
292+ * @param s3Client The asynchronous S3 client used to create the bucket
282293 * @param bucketName The name of the bucket to be created
283- * @param zone The region where the bucket will be created
284- * @throws S3Exception if there's an error creating the bucket
294+ * @param zone The Availability Zone where the bucket will be created
295+ * @throws CompletionException if there's an error creating the bucket
285296 */
286- public CompletableFuture <Void > createDirectoryBucketAsync (S3AsyncClient s3Client , String bucketName , String zone ) {
297+ public CompletableFuture <CreateBucketResponse > createDirectoryBucketAsync (S3AsyncClient s3Client , String bucketName , String zone ) {
287298 logger .info ("Creating bucket: " + bucketName );
288299
289300 CreateBucketConfiguration bucketConfiguration = CreateBucketConfiguration .builder ()
@@ -303,17 +314,18 @@ public CompletableFuture<Void> createDirectoryBucketAsync(S3AsyncClient s3Client
303314 .build ();
304315
305316 return s3Client .createBucket (bucketRequest )
306- .thenAccept (response -> logger .info ("Bucket created successfully with location: " + response .location ()))
307- .whenComplete ((ignored , exception ) -> {
317+ .whenComplete ((response , exception ) -> {
308318 if (exception != null ) {
309319 Throwable cause = exception .getCause ();
310320 if (cause instanceof S3Exception ) {
311321 throw new CompletionException ("Error creating bucket: " + ((S3Exception ) cause ).awsErrorDetails ().errorMessage (), cause );
312322 }
313323 throw new CompletionException ("Unexpected error occurred while creating bucket" , exception );
314324 }
325+ logger .info ("Bucket created successfully with location: " + response .location ());
315326 });
316327 }
328+
317329 /**
318330 * Creates an S3 bucket asynchronously.
319331 *
@@ -348,7 +360,7 @@ public CompletableFuture<WaiterResponse<HeadBucketResponse>> createBucketAsync(S
348360 * Uploads an object to an Amazon S3 bucket asynchronously.
349361 *
350362 * @param s3Client the S3 async client to use for the upload
351- * @param bucketName the name of the S3 bucket to upload the object to
363+ * @param bucketName the destination S3 bucket name
352364 * @param bucketObject the name of the object to be uploaded
353365 * @param text the content to be uploaded as the object
354366 */
@@ -397,12 +409,12 @@ public CompletableFuture<CreateAccessKeyResponse> createAccessKeyAsync(String us
397409 }
398410
399411 /**
400- * Selects an availability zone ID based on the specified AWS region .
412+ * Asynchronously selects an Availability Zone ID from the available EC2 zones .
401413 *
402- * @return A map containing the selected availability zone details, including the zone name, zone ID, region name, and state.
414+ * @return A {@link CompletableFuture} that resolves to the selected Availability Zone ID.
415+ * @throws CompletionException if an error occurs during the request or processing.
403416 */
404417 public CompletableFuture <String > selectAvailabilityZoneIdAsync () {
405- // Request available zones
406418 DescribeAvailabilityZonesRequest zonesRequest = DescribeAvailabilityZonesRequest .builder ()
407419 .build ();
408420
@@ -415,15 +427,13 @@ public CompletableFuture<String> selectAvailabilityZoneIdAsync() {
415427 return CompletableFuture .completedFuture (null ); // Return null if no zones are found
416428 }
417429
418- // Extract zone IDs
419430 List <String > zoneIds = zonesList .stream ()
420431 .map (AvailabilityZone ::zoneId ) // Get the zoneId (e.g., "usw2-az1")
421432 .toList ();
422433
423- // **Prompt user synchronously** and return CompletableFuture
424434 return CompletableFuture .supplyAsync (() -> promptUserForZoneSelection (zonesList , zoneIds ))
425435 .thenApply (selectedZone -> {
426- // Return only the selected Zone ID (e.g., "usw2-az1")
436+ // Return only the selected Zone ID (e.g., "usw2-az1").
427437 return selectedZone .zoneId ();
428438 });
429439 })
@@ -445,7 +455,7 @@ public CompletableFuture<String> selectAvailabilityZoneIdAsync() {
445455 }
446456
447457 /**
448- * Prompts the user to select an availability zone from the given list.
458+ * Prompts the user to select an Availability Zone from the given list.
449459 *
450460 * @param zonesList the list of availability zones
451461 * @param zoneIds the list of zone IDs
@@ -458,21 +468,30 @@ private static AvailabilityZone promptUserForZoneSelection(List<AvailabilityZone
458468 while (index < 0 || index >= zoneIds .size ()) {
459469 logger .info ("Select an availability zone:" );
460470 IntStream .range (0 , zoneIds .size ()).forEach (i ->
461- System . out . println (i + ": " + zoneIds .get (i )) // Display Zone IDs
471+ logger . info (i + ": " + zoneIds .get (i ))
462472 );
463473
464474 logger .info ("Enter the number corresponding to your choice: " );
465475 if (scanner .hasNextInt ()) {
466476 index = scanner .nextInt ();
467477 } else {
468- scanner .next (); // Consume invalid input
478+ scanner .next ();
469479 }
470480 }
471481
472482 AvailabilityZone selectedZone = zonesList .get (index );
473- logger .info ("You selected: " + selectedZone .zoneId ()); // Log Zone ID
483+ logger .info ("You selected: " + selectedZone .zoneId ());
474484 return selectedZone ;
475485 }
486+
487+ /**
488+ * Asynchronously sets up an AWS VPC, including creating a VPC, waiting for it to be available,
489+ * retrieving its associated route table, and creating a VPC endpoint for S3 Express.
490+ *
491+ * @return A {@link CompletableFuture} that completes when the VPC setup is finished.
492+ * If an error occurs, a {@link CompletionException} is thrown.
493+ * @throws CompletionException if an EC2-related error occurs or if required resources are missing.
494+ */
476495 public CompletableFuture <Void > setupVPCAsync () {
477496 String cidr = "10.0.0.0/16" ;
478497 CreateVpcRequest vpcRequest = CreateVpcRequest .builder ()
@@ -483,7 +502,6 @@ public CompletableFuture<Void> setupVPCAsync() {
483502 .thenCompose (vpcResponse -> {
484503 String vpcId = vpcResponse .vpc ().vpcId ();
485504
486- // Wait for VPC to be available
487505 Ec2AsyncWaiter waiter = ec2AsyncClient .waiter ();
488506 DescribeVpcsRequest request = DescribeVpcsRequest .builder ()
489507 .vpcIds (vpcId )
@@ -493,7 +511,6 @@ public CompletableFuture<Void> setupVPCAsync() {
493511 .thenApply (waiterResponse -> vpcId );
494512 })
495513 .thenCompose (vpcId -> {
496- // Fetch route table for VPC
497514 Filter filter = Filter .builder ()
498515 .name ("vpc-id" )
499516 .values (vpcId )
@@ -546,6 +563,6 @@ public CompletableFuture<Void> setupVPCAsync() {
546563 throw new CompletionException ("VPC setup failed: " + exception .getMessage (), exception );
547564 }
548565 })
549- .thenAccept (v -> {}); // Ensure CompletableFuture<Void> return type
566+ .thenAccept (v -> {});
550567 }
551568}
0 commit comments