/akka-grpc-hands-on

Akka gRPC Hands-On

Primary LanguageScalaOtherNOASSERTION

Akka gRPC Hands-on

This repository contains four projects that you can use to play with akka-grpc.

It has three quickstart server projects that you can use to implement and run a akka-grpc service.

  • Akka Http - akka-grpc-quickstart-scala
  • Play - akka-grpc-play-quickstart-scala
  • Lagom - akka-grpc-lagom-quickstart-scala

In additional to the three server projects, you can use the grpc-console-client project to generate a client and interact to any of the server projects.

Configuring the keystore (Lagom)

The Play and Lagom projects have TLS configured and use a selfsigned keystore. The keystore must be shared among the projects including the console client.

akka-grpc-play-quickstart-scala and grpc-console-client have the keystore at src/main/resources, but Lagom needs it under target/dev-mode (issue #1676 ).

To have it working for Lagom we must to copy the keystore to Lagom's target/dev-mode.
You can use script copy-keystore.sh for that:

./copy-keystore.sh

➜  akka-grpc-demo git:(master) ✗ cat copy-keystore.sh
 #!/bin/bash

mkdir -p akka-grpc-lagom-quickstart-scala/target/dev-mode
cp grpc-console-client/src/main/resources/selfsigned.keystore akka-grpc-lagom-quickstart-scala/target/dev-mode

Building

Each project is using the same gRPC service definition for a Hello World service.

message HelloRequest {
    string name = 1;
}
message HelloReply {
    string message = 1;
}

service GreeterService {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
    rpc ItKeepsTalking (stream HelloRequest) returns (HelloReply) {}
    rpc ItKeepsReplying (HelloRequest) returns (stream HelloReply) {}
    rpc StreamHellos (stream HelloRequest) returns (stream HelloReply) {}
}

The projects are already configured to generate the service interface and helper classes. The server projects will generate the gRPC classes for both server and client. The console project will generated only generate the client.

All projects will generate files under package example.myapp.helloworld.grpc.

Akka Http sample

For Akka Http sample, you need to implement example.myapp.helloworld.grpc.GreeterServer and add it to the Akka Http server.

For instance,

// We will need an Akka Streams Materializer for the calls involving Source
class GreeterServiceImpl(implicit materializer: Materializer) extends GreeterService

Check GreeterServer and discover how to attach the gRPC implmentation to the Akka Http server. Look the generated files for a helper class to help you with build a HttpRequest => Future[HttpResponse] wrapping your GreeterService implementation.

Play and Lagom samples

For Play and Lagom, you should implement an specific Play Router that's generated by the plugin. Look for the generated class example.myapp.helloworld.grpc.AbstractGreeterServiceRouter.

The Play implementation will need a javax.inject.Inject annotation as the router will be instantiate by Play itself. In Lagom the router is added programaticaly and it's using macwire as DI.

// for Play
// We will need an Akka Streams Materializer for the calls involving Source
class HelloWorldRouter @Inject() (implicit mat: Materializer) extends AbstractGreeterServiceRouter(mat)
// for Lagom
// We will need an Akka Streams Materializer for the calls involving Source
class HelloWorldRouter (implicit mat: Materializer) extends AbstractGreeterServiceRouter(mat) 

Both Play and Lagom will work with TLS enabled and need ALPN java agent. It should work out-of-the-box when running sbt as the apln jar is committed to the repository and .jvmopts file is configured accordingly.

Add the router to Play's routes file

->  /  routers.HelloWorldRouter

Add the router to Lagom's server

  // in HelloLoader.scala
  override lazy val lagomServer =
    serverFor[HelloService](wire[HelloServiceImpl])
      .additionalRouter(wire[HelloWorldRouter])

Using the client console

cd grpc-console-client
sbt console

You can then load one of the three scripts:

  • :load client-akka.sc
  • :load client-play.sc
  • :load client-lagom.sc

The script will load and create all the necessary classes (eg: ActorySystem, Materializer, gGRPC client, etc).

You can then intereact with one of the servers using the client:

val helloReply = client.sayHello(HelloRequest("John"))

See demo.txt for more examples.

The script defines a stop() method that will close the client and terminate the Actor System.