////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Getting Started with gRPC

include::./attributes.adoc[]

This page explains how to start using gRPC in your Quarkus application.
While this page describes how to configure it with Maven, it is also possible to use Gradle.

Let's imagine you have a regular Quarkus project, generated from the https://code.quarkus.io[Quarkus project generator].
The default configuration is enough, but you can also select some extensions if you want.

== Configuring your project

Edit the `pom.xml` file to add the Quarkus gRPC extension dependency (just under `<dependencies>`):

[source,xml]
----
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-grpc</artifactId>
</dependency>
----

Make sure you have `generate-code` goal of `quarkus-maven-plugin` enabled in your `pom.xml`.
If you wish to generate code from different `proto` files for tests, also add the `generate-code-tests` goal:

[source,xml]
----
<build>
    <plugins>
        <plugin>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-maven-plugin</artifactId>
            <version>${quarkus-plugin.version}</version>
            <extensions>true</extensions>
            <executions>
                <execution>
                    <goals>
                        <goal>build</goal>
                        <goal>generate-code</goal>
                        <goal>generate-code-tests</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
----

With this configuration, you can put your service and message definitions in the `src/main/proto` directory.
`quarkus-maven-plugin` will generate Java files from your `proto` files.

Alternatively to using the `generate-code` goal of the `quarkus-maven-plugin`, you can use `protobuf-maven-plugin` to generate these files, more in <<Generating Java files from proto with protobuf-maven-plugin>>

Let's start with a simple _Hello_ service.
Create the `src/main/proto/helloworld.proto` file with the following content:

[source]
----
syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.quarkus.example";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
    // Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
    string name = 1;
}

// The response message containing the greetings
message HelloReply {
    string message = 1;
}
----

This `proto` file defines a simple service interface with a single method (`SayHello`), and the exchanged messages (`HelloRequest` containing the name and `HelloReply` containing the greeting message).

Before coding, we need to generate the classes used to implement and consume gRPC services.
In a terminal, run:

[source,shell]
----
$ mvn compile
----

Once generated, you can look at the `target/generated-sources/grpc` directory:

[source,txt]
----
target/generated-sources/grpc
└── io
    └── quarkus
        └── example
            ├── GreeterGrpc.java
            ├── HelloReply.java
            ├── HelloReplyOrBuilder.java
            ├── HelloRequest.java
            ├── HelloRequestOrBuilder.java
            ├── HelloWorldProto.java
            └── MutinyGreeterGrpc.java
----

These are the classes we are going to use.

IMPORTANT: Every time you update the `proto` files, you need to re-generate the classes (using `mvn compile`).

=== `proto` files with imports

Protocol Buffers specification provides a way to import `proto` files.
The Quarkus code generation mechanism lets you control the scope of dependencies to scan for possible imports by setting the `quarkus.generate-code.grpc.scan-for-imports` property to one of the following:

- `all` - scan all the dependencies
- `none` - don't scan the dependencies, use only what is defined in the `src/main/proto` or `src/test/proto`
- `groupId1:artifactId1,groupId2:artifactId2` - scan only the dependencies with group id and artifact id in the list.

If not specified, the property is set to `com.google.protobuf:protobuf-java`.
To override it, set the `quarkus.generate-code.grpc.scan-for-imports` property in your pom.xml (or gradle.properties) to the desired value, e.g.

[source,xml]
----
<properties>
  <quarkus.generate-code.grpc.scan-for-imports>all</quarkus.generate-code.grpc.scan-for-imports>
</properties>
----

== Implementing a gRPC service

Now that we have the generated classes let's implement our _hello_ service.

With Quarkus, implementing a service requires to _extend_ the generated service base implementation and expose it as a `@Singleton` CDI bean.

IMPORTANT: Don't use `@ApplicationScoped` as the gRPC service implementation cannot be proxied.

=== Implementing a service

Create the `src/main/java/org/acme/HelloService.java` file with the following content:

[source,java]
----
package org.acme;

import io.grpc.stub.StreamObserver;
import io.quarkus.example.GreeterGrpc;
import io.quarkus.example.HelloReply;
import io.quarkus.example.HelloRequest;

import javax.inject.Singleton;

@Singleton                                                                                    // <1>
public class HelloService extends GreeterGrpc.GreeterImplBase {                               // <2>

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) { // <3>
        String name = request.getName();
        String message = "Hello " + name;
        responseObserver.onNext(HelloReply.newBuilder().setMessage(message).build());         // <4>
        responseObserver.onCompleted();                                                       // <5>
    }
}

----
1. Expose your implementation as bean.
2. Extends the `ImplBase` class. This is a generated class.
3. Implement the methods defined in the service definition (here we have a single method).
4. Build and send the response.
5. Close the response.

Quarkus also provides an additional model with Mutiny, a Reactive Programming API integrated in Quarkus.
Learn more about Mutiny on the link:getting-started-reactive#mutiny[Getting Started with Reactive guide].
A Mutiny implementation of this service would be:

[source, java]
----
package org.acme;

import io.quarkus.example.HelloReply;
import io.quarkus.example.HelloRequest;
import io.quarkus.example.MutinyGreeterGrpc;
import io.smallrye.mutiny.Uni;

import javax.inject.Singleton;

@Singleton
public class ReactiveHelloService extends MutinyGreeterGrpc.GreeterImplBase {

    @Override
    public Uni<HelloReply> sayHello(HelloRequest request) {
        return Uni.createFrom().item(() ->
                HelloReply.newBuilder().setMessage("Hello " + request.getName()).build()
        );
    }
}
----

The main differences are the following:

* it extends the `ImplBase` from `MutinyGreeterGrpc` instead of `GreeterGrpc`
* the signature of the method is using Mutiny types

NOTE: If your service implementation logic is blocking (use blocking I/O for example), annotate your method with
`@Blocking`.
The `io.smallrye.common.annotation.Blocking` annotation instructs the framework to invoke the
annotated method on a worker thread instead of the I/O thread (event-loop).

=== The gRPC server

The services are _served_ by a _server_.
Available services (_CDI beans_) are automatically registered and exposed.

By default, the server is exposed on `localhost:9000`, and uses _plain-text_ (so no TLS).

Run the application using: `mvn quarkus:dev`.

== Consuming a gRPC service

In this section, we are going to consume the service we expose.
To simplify, we are going to consume the service from the same application, which in the real world, does not make sense.

Open the existing `org.acme.ExampleResource` class, and edit the content to become:

[source, java]
----
package org.acme;

import io.quarkus.example.GreeterGrpc;
import io.quarkus.example.HelloRequest;
import io.quarkus.grpc.runtime.annotations.GrpcService;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class ExampleResource {

    @Inject
    @GrpcService("hello")                     // <1>
    GreeterGrpc.GreeterBlockingStub client;   // <2>

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }

    @GET
    @Path("/{name}")
    public String hello(@PathParam("name") String name) {
        return client.sayHello(HelloRequest.newBuilder().setName(name).build()).getMessage();  // <3>
    }
}
----

1. Inject the service and configure its name. This name is used in the application configuration.
2. Use the _blocking_ stub (also a generated class).
3. Invoke the service.

We need to configure the application to indicate where the `hello` service is found.
In the `src/main/resources/application.properties` file, add the following property:

[source,text]
----
quarkus.grpc.clients.hello.host=localhost
----

- `hello` is the name of the service used in the `@GrpcService` annotation.
- `host` configures the service host (here it's localhost).

Then, open http://localhost:8080/hello/quarkus in a browser, and you should get `Hello quarkus`!

== Packaging the application

Like any other Quarkus applications, you can package it with: `mvn package`.
You can also package the application into a native executable with: `mvn package -Pnative`.

== Generating Java files from proto with protobuf-maven-plugin

Alternatively to using Quarkus code generation to generate stubs for `proto` files, you can also use
`protobuf-maven-plugin`.

To do it, first define the 2 following properties in the `<properties>` section:

[source,xml,subs="verbatim,attributes"]
----
<grpc.version>{grpc-version}</grpc.version>
<protoc.version>{protoc-version}</protoc.version>
----

They configure the gRPC version and the `protoc` version.

Then, add to the `build` section the `os-maven-plugin` extension and the `protobuf-maven-plugin` configuration.

[source,xml,subs="verbatim,attributes"]
----
<build>
    <extensions>
        <extension>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>${os-maven-plugin-version}</version>
        </extension>
    </extensions>

    <plugins>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>      // <1>
            <version>${protobuf-maven-plugin-version}</version>
            <configuration>
                <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact> // <2>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                <protocPlugins>
                    <protocPlugin>
                        <id>quarkus-grpc-protoc-plugin</id>
                        <groupId>io.quarkus</groupId>
                        <artifactId>quarkus-grpc-protoc-plugin</artifactId>
                        <version>{quarkus-version}</version>
                        <mainClass>io.quarkus.grpc.protoc.plugin.MutinyGrpcGenerator</mainClass>
                    </protocPlugin>
                </protocPlugins>
            </configuration>
            <executions>
                <execution>
                    <id>compile</id>
                    <goals>
                        <goal>compile</goal>
                        <goal>compile-custom</goal>
                    </goals>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <goals>
                        <goal>test-compile</goal>
                        <goal>test-compile-custom</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <!-- ... -->
    </plugins>
</build>
----

1. The `protobuf-maven-plugin` that generates stub classes from your gRPC service definition (`proto` files).
2. The class generation uses a tool named `protoc`, which is OS-specific.
That's why we use the `os-maven-plugin` to target the executable compatible with the operating system.

NOTE: This configuration instructs the `protobuf-maven-plugin` to generate the default gRPC classes and classes using Mutiny to fit with the Quarkus development experience.
