Play Framework
01 / 02

Routes, Controllers & Twirl Templates

Routes, Controllers & Twirl Templates

Reactive, Non-Blocking by Design

Play is a Scala/Java web framework built for high-throughput, reactive applications on the JVM, historically built on Akka. Unlike a traditional thread-per-request servlet model, a Play request handler doesn't need to hold a dedicated thread blocked for a slow I/O operation — the thread frees up while waiting, improving resource utilization under high concurrency.

The conf/routes File

GET     /users/:id          controllers.UserController.show(id: Long)
POST    /users              controllers.UserController.create()

Routes map HTTP method + URL pattern to a controller action in one concise, declarative file — a centralized view of the app's whole URL structure, rather than scattering route annotations across many controller files.

Controllers & Actions

class UserController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
  def show(id: Long) = Action.async {
    userService.find(id).map {
      case Some(u) => Ok(views.html.user(u))
      case None    => NotFound
    }
  }
}

A controller groups action methods; each handles a request and returns a Result. Actions returning Future[Result] (via Action.async) reflect the non-blocking model directly — the framework frees the thread while an async database/API call completes, rather than blocking on it.

Twirl — Compiled, Type-Safe Templates

Twirl templates (.scala.html) compile to actual JVM functions rather than being interpreted at runtime. A template's expected parameters and types are checked by the compiler — passing the wrong type produces a compile-time error, not a runtime failure discovered only when a user happens to trigger that page.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free