== gRPC

The `jooby-grpc` module provides first-class, native support for https://grpc.io/[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.

[dependency, artifactId="jooby-grpc"]
.

[source, java, role="primary"]
.Java
----
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>
}
----

[source, kotlin, role="secondary"]
.Kotlin
----
import io.jooby.ServerOptions
import io.jooby.grpc.GrpcModule
import io.jooby.kt.Kooby

{
  serverOptions = ServerOptions().setHttp2(true)          // <1>

  install(GrpcModule(GreeterService()))                   // <2>
}
----

<1> Enable HTTP/2 on your server.
<2> Install the module and explicitly register your services.

=== 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).

[source, java, role="primary"]
.Java
----
import io.jooby.Jooby;
import io.jooby.di.GuiceModule;
import io.jooby.grpc.GrpcModule;

{
  install(new GuiceModule());

  install(new GrpcModule(GreeterService.class));  // <1>
}
----

[source, kotlin, role="secondary"]
.Kotlin
----
import io.jooby.di.GuiceModule
import io.jooby.grpc.GrpcModule
import io.jooby.kt.Kooby

{
  install(GuiceModule())

  install(GrpcModule(GreeterService::class.java)) // <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:

[source, java, role="primary"]
.Java
----
import io.grpc.protobuf.services.ProtoReflectionServiceV1;
import io.jooby.Jooby;
import io.jooby.grpc.GrpcModule;

{
  install(new GrpcModule(
      new GreeterService(),
      ProtoReflectionServiceV1.newInstance() // <1>
  ));
}
----

[source, kotlin, role="secondary"]
.Kotlin
----
import io.grpc.protobuf.services.ProtoReflectionServiceV1
import io.jooby.grpc.GrpcModule
import io.jooby.kt.Kooby

{
  install(GrpcModule(
      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.
