API Design

When designing a gRPC API, you could take into consideration some of the Google Cloud API Design Patterns.

Methods without request or response

If you want to create an endpoint that takes no parameters or produces no response, it might be tempting to use the Empty type as defined by Google in their empty.proto.

It is recommended to introduce your own (empty) message types, however, as functionality may grow and this prepares you for adding additional (optional) fields over time.

Declare and enforce constraints for your request and response payloads with protoc-gen-validate

protoc-gen-validate (PGV) defines a set of Protobuf options allowing to add additional rules on messages and fields in a declarative fashion. A set of validators for different languages is also provided, to enforce these rules at runtime.

Java support

Validators for Java stubs are provided by the project itself.

Follow the instructions there for Maven and Gradle. If your are using sbt, you can get validate.proto into the include path and run the protoc plugin generating the validators through sbt-protoc (used by Pekko gRPC) by adding to your build.sbt:

val pgvVersion = "0.4.1" // latest at the time of writing

libraryDependencies ++= Seq(
  "io.envoyproxy.protoc-gen-validate" % "pgv-java-stub" % pgvVersion % "protobuf,compile",
   ("io.envoyproxy.protoc-gen-validate" % "protoc-gen-validate" % pgvVersion).asProtocPlugin,
)

Compile / PB.targets +=
  Target(PB.gens.plugin("validate"), (Compile / pekkoGrpcCodeGeneratorSettings / target).value, Seq("lang=java"))

// PGV Java validators use lambda expressions
Compile / compile / javacOptions ++= Seq("-source", "8", "-target", "8"),

Scala support

Validators for ScalaPB stubs are provided by scalapb-validate.

Follow the documentation to update project/build.sbt in order to generate the validators using sbt-protoc (used by Pekko gRPC).

With the default parameters and target set by Pekko gRPC, additions to your build.sbt should be:

sourceimport scalapb.GeneratorOption._

enablePlugins(PekkoGrpcPlugin)

libraryDependencies +=
  "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf"
Compile / PB.targets +=
  scalapb.validate.gen(FlatPackage) -> (Compile / pekkoGrpcCodeGeneratorSettings / target).value

The validate_at_construction option can be particularly interesting in a server-side context since method implementations will automatically receive pre-validated requests and will not be able to return invalid responses. Rule-based type customization goes one step further by encoding the rules as types, when applicable.