Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS S3 Java SDK: detect time/clock skew programmatically?

My Android app uses the AWS Java SDK for uploading user photos to S3.

Whenever a user's phone's clock is 'skewed', this causes all transfers to fail. This is a well documented aspect of S3:

http://aws.amazon.com/articles/1109?_encoding=UTF8&jiveRedirect=1#04

It appears that the upstream S3 service reports this error quite clearly:

HTTP Status Code: 403 Forbidden

Error Code: RequestTimeToo-Skewed

Description: The difference between the request time and the server's time is too large.

However when using the Java SDK, it seems as if the informative 403 code is lost ... and I have only an opaque "TransferState.Failed" to go by (which incidentally is the same error if internet connectivity is lost, if it times out, etc...).

As far as I can tell from the docs:

http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferProgress.html http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.TransferState.html http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Upload.html

There is no way to get the additional "RequestTimeToo-Skewed" metadata about a transfer failure.

Am I missing it? Is there any way to get additional error information when an S3 transfer fails using Amazon's Java SDK?

UPDATE #1: A commenter kindly highlighted that I should clarity two points:

  • I am actually using the AWS SDK for Android (which seems very similar to the Java SDK, but is nonetheless distinct)
  • I am using the TransferManager class to perform my upload. Apparently, this is a high-level class that wraps the lower-level AmazonS3Client ... and this lower-level class should expose the error reporting I need, but I am still investigating the exact tradeoffs involved between TransferManager and AmazonS3Client. As far as I can tell, there is no way to get progress information via the (synchronous) AmazonS3Client.putObjectRequest which would be a blocker for me...

UPDATE #2: My sincere thanks to Jason (of the AWS SDK team) for stopping by and helping me out here. The important information is, indeed, available as properties on an AmazonS3Exception if you use certain methods. The docs had originally confused me and I thought that a manual Thread.sleep() loop was required to poll status (and thus I could not leverage waitForCompletion or waitForException), but if you use ProgressListener on PutObjectRequest you can get full progress callbacks and the error-fidelity of AmazonS3Exception.

like image 424
Mike Repass Avatar asked Sep 02 '26 00:09

Mike Repass


1 Answers

these two methods should help you out:

  • Transfer.waitForCompletion()
  • Transfer.waitForException()

If you detect that your transfer has failed based on a transfer progress event, you can simply call Transfer.waitForException() to be returned the exception that occurred. That exception will be an AmazonServiceException in this case, with all of the info that you need to see that the real problem was a clock skew issue.

Alternatively, the Transfer.waitForCompletion() method will unwrap the original exception from an ExecutionException and directly throw the original exception, just as if it'd all been happening on one thread. This might be a more convenient approach if you want to use a catch blocks to catch different types of errors cleanly and elegantly.

I disagree that the "catch Exception" block is "brutally broad". The point of that code is to catch any error that happens, mark the transfer as failed and rethrow the error so that the application code can know about it. If it were less broad, then that's exactly the case where exceptions could sneak through and transfer progress wouldn't be updated correctly and would be out of sync with reality.

Give those two methods and shot and let us know if that helps!

like image 120
Jason Fulghum Avatar answered Sep 03 '26 13:09

Jason Fulghum



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!