Jooby

gRPC

The jooby-grpc module provides first-class, native support for gRPC.

Unlike traditional setups that require spinning up a separate gRPC server on a different port (often forcing a specific transport like Netty), this module embeds the grpc-java engine directly into Jooby.

By using a custom native bridge, it allows you to run strictly-typed gRPC services alongside your standard REST API routes on the exact same port. It bypasses the standard HTTP/1.1 pipeline in favor of a highly optimized, native interceptor tailored for HTTP/2 multiplexing, reactive backpressure, and zero-copy byte framing. It works natively across Undertow, Netty, and Jetty.

Usage

gRPC strictly requires HTTP/2. Before installing the module, ensure your application is configured to use a supported server with HTTP/2 enabled.

Maven
Gradle
<dependency>
  <groupId>io.jooby</groupId>
  <artifactId>jooby-grpc</artifactId>
  <version>4.5.1</version>
</dependency>
Java
Kotlin
import io.jooby.Jooby;
import io.jooby.ServerOptions;
import io.jooby.grpc.GrpcModule;

{
  setServerOptions(new ServerOptions().setHttp2(true)); // (1)

  install(new GrpcModule(new GreeterService()));        // (2)
}
  1. Enable HTTP/2 on your server.

  2. Install the module and explicitly register your services.

Configuration

You can customize the underlying InProcessServerBuilder and InProcessChannelBuilder used by the module to apply advanced gRPC configurations. This is particularly useful for registering global interceptors (like OpenTelemetry traces), adjusting payload limits, or tweaking executor settings.

Use the withServer and withChannel callbacks to hook directly into the builders before the server starts:

Java
Kotlin
import io.jooby.Jooby;
import io.jooby.grpc.GrpcModule;

{
  install(new GrpcModule(new GreeterService())
      .withServer(server -> {                 // (1)
        server.maxInboundMessageSize(1024 * 1024 * 20); // 20MB limit
      })
      .withChannel(channel -> {               // (2)
        channel.intercept(new MyCustomClientInterceptor());
      })
  );
}
  1. Customize the internal gRPC server (e.g., adjust max message sizes, add server-side interceptors).

  2. Customize the internal loopback channel (e.g., add client-side interceptors for context propagation).

Note
Size Limits: By default, Jooby automatically sets the gRPC server’s maxInboundMessageSize and maxInboundMetadataSize to match your web server’s server.maxRequestSize property (which defaults to 10mb). If you manually increase these limits on the gRPC server builder, you must also increase server.maxRequestSize. If an incoming gRPC payload or metadata exceeds the configured web server limit, the request will be rejected before it ever reaches the gRPC layer.

Dependency Injection

If your gRPC services require external dependencies (like database repositories), you can register the service classes instead of pre-instantiated objects. The module will automatically provision them using your active Dependency Injection framework (e.g., Guice, Spring).

Java
Kotlin
import io.jooby.Jooby;
import io.jooby.di.GuiceModule;
import io.jooby.grpc.GrpcModule;

{
  install(new GuiceModule());

  install(new GrpcModule(GreeterService.class));  // (1)
}
  1. Pass the class references. The DI framework will instantiate them.

Warning
gRPC services are registered as Singletons. Ensure your service implementations are thread-safe and do not hold request-scoped state in instance variables. Heavy blocking operations will safely run on background workers, protecting the native server’s I/O event loops.

Server Reflection

If you want to use tools like grpcurl or Postman to interact with your services without providing the .proto files, you can easily enable gRPC Server Reflection.

Include the grpc-services dependency in your build, and register the v1 reflection service alongside your own:

Java
Kotlin
import io.grpc.protobuf.services.ProtoReflectionServiceV1;
import io.jooby.Jooby;
import io.jooby.grpc.GrpcModule;

{
  install(new GrpcModule(
      new GreeterService(),
      ProtoReflectionServiceV1.newInstance() // (1)
  ));
}
  1. Enables the modern v1 reflection protocol for maximum compatibility with gRPC clients.

Routing & Fallbacks

The gRPC module intercepts requests natively before they reach Jooby’s standard router.

If a client attempts to call a gRPC method that does not exist, the request gracefully falls through to the standard Jooby router, returning a native 404 Not Found (which gRPC clients will automatically translate to a Status 12 UNIMPLEMENTED).

If you misconfigure your server (e.g., attempting to run gRPC over HTTP/1.1), the fallback route will catch the request and throw an IllegalStateException to help you identify the missing configuration immediately.