2

While I was trying to upload objects to a specific bucket in Amazon S3 storage via Amazon Web Services API, I obviously needed a reference to that existing bucket. I was using AmazonS3Client to perform that, however I couldn't see any method such as getBucket(String bucketID).

Please check here: AmazonS3Client

I applied a brute-force search to get a reference to the desired bucket:

AmazonS3Client connection = new AmazonS3Client(credentials);
Bucket targetBucket = null;

List<Bucket> buckets = connection.listBuckets();
for (Bucket bucket : buckets)
{
  if (bucket.getName().equals(bucketId))
  {
    targetBucket = bucket;
    break;
  }
}

Obviously, this works fine. But I wonder why the API doesn't provide such a trivial method or might I be missing something or do you know any other method(s) from the same API which will replace the lines above with one-line code?

EDIT:

For a simple task like uploading a file, the bucket name seems to be sufficient:

if (connection.doesBucketExist(bucketId))
{
  connection.putObject(bucketId, ... );
}

However, my question is as the title implies, why isn't there a method returning a reference to a specific Bucket instance?

Juvanis
  • 25,802
  • 5
  • 69
  • 87
  • If you know the name of the bucket you want to use, why do you need to list them? putObject to the bucket directly. – Guy Feb 16 '14 at 11:43
  • putObject can get bucketName as String: (http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3Client.html#putObject(java.lang.String, java.lang.String, java.io.File) – Guy Feb 16 '14 at 11:47
  • @Guy what if I'm using Bucket reference for some other purposes? So please learn the difference between a text and object reference. – Juvanis Feb 16 '14 at 11:52
  • Some concepts are probably too hard for me to understand... I like simple life with API calls that are using text... but this is only me. – Guy Feb 16 '14 at 11:58

4 Answers4

1

Your brute force method gets a Bucket object if the bucket exists and you own it, and otherwise results in null. To get the same result without listing the buckets:

  1. Call AmazonS3Client.doesBucketExist(bucketId); if false, your result is null.
  2. Call AmazonS3Client.getBucketAcl(bucketId).getOwner() to get the owner of the bucket.
  3. If the owner of the bucket is not yourself - available from AmazonS3Client.getS3AccountOwner() - your result is null.
  4. If the owner of the bucket is yourself, then the result is new Bucket(bucketId).

If you already know you own a bucket with the relevant name, you can skip all but the last step.

Not exactly a one line result, but it does avoiding listing the buckets, which could be good if you have a large number of buckets, and I think it's the API's intended way to do what you want.

Warren Dew
  • 8,790
  • 3
  • 30
  • 44
  • Can you tell me how can I check with `AmazonS3Client.getS3AccountOwner()` whether I'm the owner? – Juvanis Feb 24 '14 at 09:22
  • 1
    AmazonS3Client.getS3AccountOwner() gets the owner of the current account the code is using - that is, yourself. AmazonS3Client.getBucketAcl(bucketId).getOwner() gets the owner of the bucket. Comparing the two should show whether you are the owner of the bucket. – Warren Dew Feb 24 '14 at 16:18
0

Quoting my own article:

The createBucket call is idempotent: It if exists, no exception is thrown.

Hope it helps

aldrinleal
  • 3,559
  • 26
  • 33
  • You are referring to the method createBucket() of AmazonS3 interface, and I'm using an implementation of that method and I get an exception when I use that method. Firstly, I was thinking that the method should return the bucket if it already exists, but it does not. Exception message: `com.amazonaws.services.s3.model.AmazonS3Exception: Status Code: 409, AWS Service: Amazon S3, AWS Request ID: ****, AWS Error Code: BucketAlreadyOwnedByYou, AWS Error Message: Your previous request to create the named bucket succeeded and you already own it., S3 Extended Request ID: ****` – Juvanis Feb 14 '14 at 14:45
  • So basically, your answer doesn't help. Thanks, anyway. – Juvanis Feb 14 '14 at 14:45
  • Note to others: Just because this is an idempotent operation doesn't mean you can call it as often as you want. You want to keep bucket creation [off of highly trafficked code paths](http://stackoverflow.com/a/13899997/344286) – Wayne Werner Nov 19 '15 at 14:14
0

I don't think you're missing anything. There are no APIs in that list that return a single bucket. The Ruby SDK seems to do what you want. http://docs.aws.amazon.com/AWSRubySDK/latest/frames.html

Before you can upload files to S3, you need to create a bucket.

s3 = AWS::S3.new bucket = s3.buckets.create('my-bucket')

If a bucket already exists, you can get a reference to the bucket.

bucket = s3.buckets['my-bucket'] # no request made

sallie
  • 349
  • 1
  • 5
  • Thank you for the answer, but I'm using Java as specified above. – Juvanis Feb 14 '14 at 20:53
  • Also, the "no request made" suggests that you'll get a valid bucket object even if the bucket does not actually exist, which is not quite what the question's code does. – Warren Dew Feb 17 '14 at 06:41
0

I'll give it a stab.

According to the Java Doc and the REST API doc (v 1.7.1), there is simply nothing that you can pass in to get anything less than a full list of buckets. If I had to guess, I would say that its probably because Amazon cautions in their docs to create/delete buckets sparingly and thus pushes the burden onto the dev of caching that response or of searching through it themselves. Theres also a limit on the number of buckets per account, so the number of buckets in the response is reasonably small.

One of the comments on the question mentioned that most of the calls use a String and not a Bucket, which caused me to take a look at the Bucket class. The only fields that it contains other than its name are the owner and creation date. If that's what you're trying to get at, then its probably in your best interest keep the full response somewhere. The bucket owner and dates aren't going to change very often, if at all.

Perhaps I'm assuming too much here, but it might be best if you just poll the service at app startup or on a regular basis to see if anything changed, updating your cache when needed and to use this cache instead of hitting S3 every time you need this info.

Its also worth mentioning that if you don't need an owner and creation date, there's nothing stopping you from instantiating a Bucket yourself and setting the name on it.

bstempi
  • 2,023
  • 1
  • 15
  • 27