Uploading a video in S3 Using Future
First, remove import play.api.libs.concurrent.Execution.Implicits._. You don't want the default Play execution context. Instead, you should use one of the ExecutionContexts you've defined and aren't using. Perhaps define one for S3 operations alone, and you don't need the others if you aren't going to use them. Future.apply requires the implicit ExecutionContext, so you can either import the correct one, or explicitly pass it.

Assuming you have a context defined like this in your configuration:

contexts {
    s3-ops {
        fork-join-executor {
            parallelism-factor = 10.0
        }
    }
}


Then in your controller you could add:

implicit val ec: ExecutionContext = Akka.system.dispatchers.lookup("contexts.s3-ops")


Now in the body of the controller function, I'll work my way inward. With the handling of the session, why bother returning data to the user if they don't have a session? It would seem more appropriate to return Forbidden, which can shorten that line to Future.successful(Forbidden). Note that Future.successful creates a Future that has already been completed.

The use of try/catch is not very Scala-like. There are other nicer ways to handle errors in Scala like Try. Future is actually very similar to Try, though, and it should provide all the error handling you need in this case. If an exception occurs within a Future, then it becomes a failed Future. No exceptions will propagate upward. Most of the code inside your try block can go inside the Future apply instead.

var videoName: String = null is something that should be avoided altogether. First, it's best to avoid mutable vars, and second you should never find yourself assigning null to anything.

I'm not sure the body of your current Future where you're mapping request.body.files is doing what you think it's doing. request.body.files is a Seq[FilePart], which means if there are multiple FileParts, you're going to upload them all separately, overwrite videoName and only return the name of the last uploaded FilePart. Or worse, if there are no FileParts, that part will silently fail. If you're only going to have a single FilePart, it'd be better to name it in the upload body and access via request.body.file("filename") which will be an Option[FilePart]. From there you can map the Option[FilePart] to the actual upload.

Since you're not actually doing anything with the PutObjectResult from the S3 response, it'd be better to return the name of the file in the Future, so that you have access to it when you map the Future, and would no longer have a need for a var. Following the suggestions above, it would now be a Future[Option[String]].

This would leave you with three return states for the Future:


A successful Future containing Some[String] (upload success on both ends).
A successful Future containing None (no file was uploaded to the server).
A failed Future (the upload to S3 failed somehow).


You'd then have something that looks roughly like this:

Future {
    request.body.file("filename").map{ file =&gt;
        val videoName = ...
        amazonS3Client.putObject(...)
        videoName
    }
}.map{ upload =&gt;
    upload.map{videoName =&gt; Ok(...)}.getOrElse{BadRequest(...)}
}.recover{ case _ =&gt;  // recover the failed `Future` to a default value, in this case a `Result`
    InternalServerError
}


Much cleaner. Note that recover accepts a PartialFunction[Throwable, ?], similarly to a catch block, so you can be more fine grained in your error handling if you need to.

A couple more notes:

There's no need to use Lift's json API for your responses. Play's implementation works just fine:

import play.api.libs.json.Json
Ok(Json.obj("result" -&gt; "success", "videoName" -&gt; videoName))


Your imports take up a lot of space. Many can be condensed into one liners:

 import play.api.i18n.Lang
 import play.api.i18n.Messages


Can be:

 import play.api.i18n.{Lang, Messages}