AWS Services: AWS SDK on the Scala with Play Framework


playing-aws-scala

The following blog and attached code represent a simple example of Amazon Web Services in the Scala way with Play Framework using AWScala but in this blog I have implemented only Amazon Simple Storage Service (Amazon S3) functionalities.

AWScala: AWS SDK on the Scala REPL

AWScala enables Scala developers to easily work with Amazon Web Services in the Scala way.

Though AWScala objects basically extend AWS SDK for Java APIs, you can use them with less stress on Scala REPL or sbt console.


AWScala Supported Services


  • AWS Identity and Access Management (IAM)
  • AWS Security Token Service (STS)
  • Amazon Elastic Compute Cloud (Amazon EC2)
  • Amazon Simple Storage Service (Amazon S3)
  • Amazon Simple Queue Service(Amazon SQS)
  • Amazon Redshift
  • Amazon DynamoDB
  • Amazon SimpleDB

Amazon Simple Storage Service (Amazon S3)


package utils

import awscala._, s3._

object S3Utility extends S3Utility

trait S3Utility {

  implicit val s3 = S3()

  /**
   * Get all the available buckets
   *
   * @return
   */
  def getBuckets(): Seq[Bucket] = s3.buckets

  /**
   * Get the bucket by given name
   *
   * @param name The Bucket name
   * @return
   */
  def getBucketByName(name: String): Option[Bucket] = s3.bucket(name)

  /**
   * Create new bucket for given name
   *
   * @param name The Bucket name
   * @return
   */
  def createBucket(name: String): Bucket = s3.createBucket(name)

  /**
   * Create an object into given bucket by name
   *
   * @param bucket The Bucket
   * @param name The Object name
   * @param file The Object
   * @return
   */
  def createObject(bucket: Bucket, name: String, file: File): PutObjectResult = bucket.put(name, file)

  /**
   * Get the Object by given name from given bucket
   *
   * @param bucket The Bucket
   * @param name The Object name
   * @return
   */
  def getObject(bucket: Bucket, name: String): Option[S3Object] = bucket.getObject(name)

}
  val uploadService: UploadService

  def upload = Action(parse.multipartFormData) { implicit request =>
    val result = uploadService.uploadFile(request)
    Redirect(routes.Application.index).flashing("message" -> result)
  }
  /**
   * Get file from the request and move it in your location
   *
   * @param request
   * @return
   */
  def uploadFile(request: Request[MultipartFormData[TemporaryFile]]): String = {
    log.error("Called uploadFile function" + request)
    request.body.file("file").map { file =>
      import java.io.File
      val filename = file.filename
      val contentType = file.contentType
      log.error(s"File name : $filename, content type : $contentType")
      val uniqueFile = new File(s"/tmp/${UUID.randomUUID}_$filename")
      file.ref.moveTo(uniqueFile, true)
      if (Play.isProd) {
        try {
          val bucket = s3Utility.getBucketByName("test").getOrElse(s3Utility.createBucket("test"))
          val result = s3Utility.createObject(bucket, filename, uniqueFile)
          s"File uploaded on S3 with Key : ${result.key}"
        } catch {
          case t: Throwable => log.error(t.getMessage, t); t.getMessage
        }
      } else {
        s"File(${filename}) uploaded"
      }
    }.getOrElse {
      "Missing file"
    }
  }

Test Code for Controller and Service


ApplicationSpec.scala

"should be valid" in new WithApplication {
  val request = mock[Request[MultipartFormData[TemporaryFile]]]
  mockedUploadService.uploadFile(request) returns "File Uploaded"
  val result: Future[Result] = TestController.upload().apply(request)
  status(result) must equalTo(SEE_OTHER)
}

UploadServiceSpec.scala

"UploadService" should {
    "uploadFile returns (File uploaded)" in new WithApplication {
      val files = Seq[FilePart[TemporaryFile]](FilePart("file", "UploadServiceSpec.scala", None, TemporaryFile("file", "spec")))
      val multipartBody = MultipartFormData(Map[String, Seq[String]](), files, Seq[BadPart](), Seq[MissingFilePart]())
      val fakeRequest = FakeRequest[MultipartFormData[Files.TemporaryFile]]("POST", "/", FakeHeaders(), multipartBody)
      val success = UploadService.uploadFile(fakeRequest)
      success must beEqualTo("File uploaded")
    }

    "uploadFile returns (Missing file)" in new WithApplication {
      val files = Seq[FilePart[TemporaryFile]]()
      val multipartBody = MultipartFormData(Map[String, Seq[String]](), files, Seq[BadPart](), Seq[MissingFilePart]())
      val fakeRequest = FakeRequest[MultipartFormData[Files.TemporaryFile]]("POST", "/", FakeHeaders(), multipartBody)
      val success = UploadService.uploadFile(fakeRequest)
      success must beEqualTo("Missing file")
    }
}

AWS credentials! Make sure about environment or configuration


export AWS_ACCESS_KEY_ID=<ACCESS_KEY>
export AWS_SECRET_KEY=<SECRET_KEY>

Build and Run the application


  • To run the Play Framework, you need JDK 6 or later
  • Install Typesafe Activator if you do not have it already. You can get it from here
  • Execute ./activator clean compile to build the product
  • Execute ./activator run to execute the product
  • playing-aws-scala should now be accessible at localhost:9000

Test the application with code coverage


  • Execute $ ./activator clean coverage test to test
  • Execute $ ./activator coverageReport to generate coverage report

References :-


This is the start of AWS Services implementation, from next week onwards we would be working on this application to make it grow. We would look at how we can make it more functional, then we would be adding more AWS modules to it together. If you have any changes then feel free to send in pull requests and we would do the merges 🙂 Stay tuned.

Advertisements

About Anand Kumar Singh

Hi, I’m Anand Singh and I specialize in Computer Software. I’m passionate about what I do, and I love to help people. Nothing is more fulfilling than being part of a team with similar interests, and an organization that values its employees. I'm Lead Software Engineer at Sapient. Having 5+ years of experience in Java, Grails/Groovy and Scala language. Anand also knows about Javascript, jQuery, CSS and other UI design technologies. Certified developer in: * Principles of Reactive Programming – Coursera * Functional Programming Principles in Scala – Coursera * Functional Program Design in Scala – Coursera * Introduction to Big Data with Apache Spark – edX * Oracle Certified Associate (OCA) * Sun Certified Java Programmer (SCJP) I'm passionate to work with upcoming technologies and bleeding platforms providing the new way to programming & development. He is actively involved in development & maintenance of several software projects. He has been enjoying Scala for more than a year now. Anand completed his MCA from IGNOU. As a Developer, I'm continuing my journey by actively collaborating with other Developers in my field. I'm actively contributing on the TechMonad & Playing Scala platform. I likes to spend his free time in Cooking, watching Discovery for new Technology and visiting new places with friends.
This entry was posted in Akka, Amazon, Amazon EC2, AWS, AWS Services, Bootstrap, Bootswatch, Future, MultipartFormData, Play Framework, S3 and tagged , , , , , , , , , . Bookmark the permalink.

3 Responses to AWS Services: AWS SDK on the Scala with Play Framework

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s