Understanding the code

Adding gRPC support to a vanilla Play application requires a few steps:

1. sbt-akka-grpc

Add the Akka gRPC plugin on project/plugins.sbt

// project/plugins.sbt
addSbtPlugin("com.lightbend.akka.grpc" %% "sbt-akka-grpc" % "0.6.2")

and enable it on your project (in build.sbt):

// build.sbt
lazy val `play-scala-grpc-example` = (project in file("."))
  .enablePlugins(PlayScala)
  .enablePlugins(AkkaGrpcPlugin) // enables source generation for gRPC
  .enablePlugins(PlayAkkaHttp2Support) // enables serving HTTP/2 and gRPC

The AkkaGrpcPlugin locates the gRPC .proto files and generates source code from it. Remember to enable the plugin in all the projects of your build that want to use it.

Note how the PlayAkkaHttp2Support is also enabled. gRPC requires HTTP/2 transport and Play supports it only as an opt-in plugin.

2.a Serving (Akka) gRPC Services

Have a look at the conf/routes file where you’ll notice how to embed a gRPC router within a normal play application. You can in fact mix normal Play routes with gRPC routers like this to offer a mixed service. You’ll notice that we bind the / path to the controllers.HomeController like usual route, and then we use the -> router binding syntax to bind the routers.HelloWorldRouter. This is because gRPC services have paths correspond to their “methods”, yet this is handled by its internal infrastructure and end-users need not concern themselves about the exact names – clients too are generated from the appropriate app/protobuf/helloworld.proto file after all.

You will need to enable the Akka-gRPC generators for server-side code:

// build.sbt
akkaGrpcExtraGenerators += PlayScalaServerCodeGenerator,

You can read more about Service gRPC from a Play App in the docs.

2.b Injecting Akka-gRPC Clients

Similarily to the server side, the sources are generated by the Akka gRPC plugin by having it configured to emit the client as well:

// build.sbt
akkaGrpcExtraGenerators += PlayScalaClientCodeGenerator,

In order to make the gRPC clients easily injectable, we need to enable the following module in Play as well (in this example app this has been done already though):

# conf/application.conf
## Modules - https://www.playframework.com/documentation/latest/Modules
play.modules {
  # To enable Akka gRPC clients to be @Injected
  # This Module is generated by the Akka gRPC sbt plugin. See your `target/scala-2.12/src_managed` folder.
  enabled += example.myapp.helloworld.grpc.AkkaGrpcClientModule
}

Which in turn allows us to inject clients to any of the services defined in our app/proto directory, just like so:

//app/controllers/HomeController.scala
import com.typesafe.config.Config
import example.myapp.helloworld.grpc.{ GreeterServiceClient, HelloReply, HelloRequest }
import javax.inject.Inject
import play.api.mvc._

import scala.concurrent.{ ExecutionContext, Future }

class HomeController @Inject()(greeterServiceClient: GreeterServiceClient,
                               config: Config
                              )(implicit ec: ExecutionContext
                              ) extends InjectedController {

Since you may want to configure what service discovery or hardcoded location to use for each client, you may do so as well in conf/application.conf, though we will not dive into this here. Refer to the documentation on using Akka Discovery for endpoint discovery for more details.