Documentation

§Embedding an Pekko Http server in your application

While Play apps are most commonly used as their own container, you can also embed a Play server into your own existing application. This can be used in conjunction with the Twirl template compiler and Play routes compiler, but these are of course not necessary. A common use case is an application with only a few simple routes. To use Pekko HTTP Server embedded, you will need the following dependency:

libraryDependencies ++= Seq(
  pekkoHttpServer
)

One way to start a Play Pekko HTTP Server is to use the PekkoHttpServer factory methods. If all you need to do is provide some straightforward routes, you may decide to use the String Interpolating Routing DSL in combination with the fromRouterWithComponents method:

import play.api.mvc._
import play.api.routing.sird._
import play.core.server.PekkoHttpServer

val server = PekkoHttpServer.fromRouterWithComponents() { components =>
  import Results._
  import components.{ defaultActionBuilder => Action }
  {
    case GET(p"/hello/$to") =>
      Action {
        Ok(s"Hello $to")
      }
  }
}

By default, this will start a server on port 9000 in prod mode. You can configure the server by passing in a ServerConfig:

import play.api.mvc._
import play.api.routing.sird._
import play.core.server.PekkoHttpServer
import play.core.server._

val server = PekkoHttpServer.fromRouterWithComponents(
  ServerConfig(
    port = Some(19000),
    address = "127.0.0.1"
  )
) { components =>
  import Results._
  import components.{ defaultActionBuilder => Action }
  {
    case GET(p"/hello/$to") =>
      Action {
        Ok(s"Hello $to")
      }
  }
}

Play also provides components traits that make it easy to customize other components besides the router. The PekkoHttpServerComponents trait is provided for this purpose, and can be conveniently combined with BuiltInComponents to build the application that it requires. In this example we use DefaultPekkoHttpServerComponents, which is equivalent to PekkoHttpServerComponents with BuiltInComponents with NoHttpFiltersComponents:

import play.api.http.DefaultHttpErrorHandler
import play.api.mvc._
import play.api.routing.Router
import play.api.routing.sird._
import play.core.server.DefaultPekkoHttpServerComponents

import scala.concurrent.Future

val components = new DefaultPekkoHttpServerComponents {
  override lazy val router: Router = Router.from {
    case GET(p"/hello/$to") =>
      Action {
        Results.Ok(s"Hello $to")
      }
  }

  override lazy val httpErrorHandler: DefaultHttpErrorHandler = new DefaultHttpErrorHandler(
    environment,
    configuration,
    devContext.map(_.sourceMapper),
    Some(router)
  ) {
    protected override def onNotFound(request: RequestHeader, message: String): Future[Result] = {
      Future.successful(Results.NotFound("Nothing was found!"))
    }
  }
}
val server = components.server

Here the only method you need to implement is router. Everything else has a default implementation that can be customized by overriding methods, such as in the case of httpErrorHandler above. The server configuration can be overridden by overriding the serverConfig property.

To stop the server once you’ve started it, simply call the stop method:

server.stop()

Note: Play requires an application secret to be configured in order to start. This can be configured by providing an application.conf file in your application, or using the play.http.secret.key system property.

Another way is to create a Play Application via GuiceApplicationBuilder in combination with the fromApplication method:

import play.api.mvc._
import play.api.routing.sird._
import play.core.server.PekkoHttpServer
import play.core.server.ServerConfig
import play.filters.HttpFiltersComponents
import play.api.Environment
import play.api.ApplicationLoader
import play.api.BuiltInComponentsFromContext

val context = ApplicationLoader.Context.create(Environment.simple())
val components = new BuiltInComponentsFromContext(context) with HttpFiltersComponents {
  override def router: Router = Router.from {
    case GET(p"/hello/$to") =>
      Action {
        Results.Ok(s"Hello $to")
      }
  }
}

val server = PekkoHttpServer.fromApplication(
  components.application,
  ServerConfig(
    port = Some(19000),
    address = "127.0.0.1"
  )
)

§Logging configuration

When using Pekko HTTP as an embedded server, no logging dependencies are included by default. If you want to also add logging to the embedded application, you can add the Play logback module:

libraryDependencies ++= Seq(
  logback
)

And later call the LoggerConfigurator API:

import play.api.mvc._
import play.api.routing.sird._
import play.filters.HttpFiltersComponents
import play.core.server.PekkoHttpServer
import play.core.server.ServerConfig
import play.api.Environment
import play.api.ApplicationLoader
import play.api.LoggerConfigurator
import play.api.BuiltInComponentsFromContext

val context = ApplicationLoader.Context.create(Environment.simple())
// Do the logging configuration
LoggerConfigurator(context.environment.classLoader).foreach {
  _.configure(context.environment, context.initialConfiguration, Map.empty)
}

val components = new BuiltInComponentsFromContext(context) with HttpFiltersComponents {
  override def router: Router = Router.from {
    case GET(p"/hello/$to") =>
      Action {
        Results.Ok(s"Hello $to")
      }
  }
}

val server = PekkoHttpServer.fromApplication(
  components.application,
  ServerConfig(
    port = Some(19000),
    address = "127.0.0.1"
  )
)

Next: Embedding Play with Netty Server


Found an error in this documentation? The source code for this page can be found here. After reading the documentation guidelines, please feel free to contribute a pull request. Have questions or advice to share? Go to our community forums to start a conversation with the community.