Integrating Amazon S3 in Grails Application
Recently in my project, we needed to store documents on some cloud based storage. So we choose Amazon S3 as it is secure and has proper backup mechanism and enough data centres so that we have minimum latency to access the server. Amazon has provided a great API available in different languages and we can use their Java API in our Grails application
In this blog we will see how to integrate the Amazon JAR in your Grails application and use different operations like upload/download/delete file to/from S3 in some simple steps.
Step 1 : First you need to have an account on Amazon so that you can consume their services. You will get access_token and secret_key of your owning account which is used for authentication to consume Amazon services through any API call. These credentials should be very secure and should not be exposed to end user. Save credentials into some file let’s say “AWSCredentials.properties” and file content should be something like :
[groovy]
// File: AWSCredentials.properties
accessKey=abcdefghij1234012345678
secretKey=8667f7f66f6fdf+F/jfj987389784
[/groovy]
Step 2 : Add a line in the “dependency” block for fetching the AWS SDK
[groovy]
dependencies {
…
compile ‘com.amazonaws:aws-java-sdk-s3:1.10.8’
…
}
[/groovy]
Step 3 : After you’ve added a dependency, create an “S3Client” and authenticate it with given credentials :
[groovy]
File file = grailsApplication.mainContext.getResource(‘WEB-INF/AWSCredential.properties’).file
FileInputStream fileInputStream = new FileInputStream(file)
AmazonS3 s3Client = new AmazonS3Client(new PropertiesCredentials(fileInputStream))
[/groovy]
… or register a bean named “s3Client” usable throughout the application as follows:
[groovy]
// resources.groovy
File file = grailsApplication.mainContext.getResource(‘WEB-INF/AWSCredentials.properties’).file
FileInputStream fileInputStream = new FileInputStream(file)
s3Client(AmazonS3Client, new PropertiesCredentials(fileInputStream)) {}
[/groovy]
So far so good. Once we’ve created a new “S3Client”, its simply a matter of calling the requisite API methods to perform the respective actions. Let’s try out a few operations.
Create a new bucket:
[groovy]
s3Client.createBucket(new CreateBucketRequest(‘My-Bucket’));
[/groovy]
Upload a new file on a given bucket:
[groovy]
String key = UUID.randomUUID().toString() // Key should be unique for each upload.
File file = new File(‘MyPath’) // You can upload any type of file.
PutObjectRequest putObjectRequest = new PutObjectRequest(‘My-Bucket’, key, file)
putObjectRequest.withCannedAcl(CannedAccessControlList.AuthenticatedRead)) // secure everything
s3Client.putObject(putObjectRequest)
[/groovy]
Fetch a file from a bucket:
[groovy]
GetObjectRequest getObjectRequest = new GetObjectRequest(‘My-Bucket’, key)
s3Client().getObject(getObjectRequest)
[/groovy]
Delete a file from a bucket
[groovy]
DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(‘My-Bucket’, key)
s3Client().deleteObject(deleteObjectRequest);
[/groovy]
Remember “key” is the unique identifier for your every single file upload , so this needs to be stored for future reference.
I hope this blog was helpfull to integrate Amazon S3 within your grails application.
I’m not able to define s3Client bean inside resources.groovy. I always have “mainContext” null and I don’t know why..I’m usign grails 2.5.0.
Another problem: If I don’t declare a bean inside resources.groovy, when I’m instantiating
“AmazonS3 s3Client = new AmazonS3Client(new PropertiesCredentials(fileInputStream))” I get the following cast exception error:
“org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ‘java.io.BufferedOutputStream@48eb346e’ with class ‘java.io.BufferedOutputStream’ to class ‘java.io.File'”
Assuming you are running on AWS (EC2, Beanstalk, etc), please don’t embed credentials. IAM Roles are much safer.