Serving gRPC from Lagom

To be able to serve gRPC from a Lagom application you must enable Play HTTP/2 Support with HTTPS and the ALPN agent. This is still somewhat involved and we hope to simplify it.

After adding Akka gRPC sbt plugin you need to enable the Play server side code generator in build.sbt:

Scala
akkaGrpcExtraGenerators += akka.grpc.gen.scaladsl.play.PlayScalaServerCodeGenerator
Java
akkaGrpcExtraGenerators += akka.grpc.gen.javadsl.play.PlayJavaServerCodeGenerator

The plugin will look for .proto service descriptors in src/main/protobuf and output an abstract class per service that you then implement, so for example for the following protobuf descriptor:

Scala
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.lightbend.lagom.scaladsl.grpc.interop";
option java_outer_classname = "HelloWorldProto";

package helloworld;

service GreeterService {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}
Full source at GitHub
Java
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.lightbend.lagom.javadsl.grpc.interop";
option java_outer_classname = "HelloWorldProto";

package helloworld;

service GreeterService {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}
Full source at GitHub

You will get an abstract class named com.lightbend.lagom.scaladsl.grpc.interop.AbstractGreeterServiceRouter com.lightbend.lagom.javadsl.grpc.interop.AbstractGreeterServiceRouter. Create a concrete subclass implementing this wherever you see fit in your project, let’s say com.lightbend.lagom.scaladsl.grpc.interop.test.HelloGrpcServiceImplcom.lightbend.lagom.javadsl.grpc.interop.test.api.HelloGrpcServiceImpl like so:

Scala
package com.lightbend.lagom.scaladsl.grpc.interop.test

import akka.actor.ActorSystem
import akka.stream.Materializer
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.AbstractGreeterServiceRouter
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.HelloReply
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.HelloRequest

import scala.concurrent.Future

class HelloGrpcServiceImpl(mat: Materializer, sys: ActorSystem) extends AbstractGreeterServiceRouter(mat, sys) {
  override def sayHello(in: HelloRequest): Future[HelloReply] =
    Future.successful(HelloReply(s"Hi ${in.name}! (gRPC)"))
}
Full source at GitHub
Java
package com.lightbend.lagom.javadsl.grpc.interop.test.api;

import akka.actor.ActorSystem;
import akka.stream.Materializer;
import com.lightbend.lagom.javadsl.grpc.interop.AbstractGreeterServiceRouter;
import com.lightbend.lagom.javadsl.grpc.interop.HelloReply;
import com.lightbend.lagom.javadsl.grpc.interop.HelloRequest;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

@Singleton
public class HelloGrpcServiceImpl extends AbstractGreeterServiceRouter {

  @Inject
  public HelloGrpcServiceImpl(Materializer mat, ActorSystem sys) {
    super(mat, sys);
  }

  @Override
  public CompletionStage<HelloReply> sayHello(HelloRequest in) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hi " + in.getName() + " (gRPC)").build();
    return CompletableFuture.completedFuture(reply);
  }
}
Full source at GitHub

And then, you need to bind the new additional router in your project.

In Scala, you use additionalRouter method when creating your lagomServer instance:

Scala
// Bind the service that this server provides
override lazy val lagomServer =
  serverFor[HelloService](wire[HelloServiceImpl])
    .additionalRouter(wire[HelloGrpcServiceImpl])
Full source at GitHub

In Java, you need to bind the service with the additional router:

Java
import com.google.inject.AbstractModule;
import com.lightbend.lagom.javadsl.server.ServiceGuiceSupport;
import com.lightbend.lagom.javadsl.grpc.interop.test.api.HelloGrpcServiceImpl;
import com.lightbend.lagom.javadsl.grpc.interop.test.HelloServiceImpl;
import com.lightbend.lagom.javadsl.grpc.interop.test.api.api.HelloService;

public class HelloModule extends AbstractModule implements ServiceGuiceSupport {
  @Override
  protected void configure() {
    bindService(
        // bind the lagom service
        HelloService.class, HelloServiceImpl.class,
        // include additional routers (in this case a gRPC router)
        additionalRouter(HelloGrpcServiceImpl.class)
    );
  }
}
Full source at GitHub

And finally enable this module in your application.conf file:

Java
play.modules.enabled += HelloModule
Full source at GitHub

A gRPC client can now connect to the server and call the provided services.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.