== Vert.x gRPC Protoc Plugin

The easiest way to start using vertx-grpc is to utilize its built-in code generator plugin. To do so, one must define
the protocol in the `protobuffer` format as required by gRPC.

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

option java_multiple_files = true;
option java_package = "examples";
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 is a very simple example showing the single request, single response mode.

=== Compile the RPC definition

Using the definition above we need to compile it.

You can compile the proto file using the `protoc` compiler if you https://github.com/google/protobuf/tree/master/java#installation---without-maven[like]
or you can integrate it in your build.


If you’re using Apache Maven you need to add the plugin:

[source,xml]
----
<plugin>
 <groupId>org.xolstice.maven.plugins</groupId>
 <artifactId>protobuf-maven-plugin</artifactId>
 <version>0.6.1</version>
 <configuration>
   <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
   <pluginId>grpc-java</pluginId>
   <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
   <protocPlugins>
     <protocPlugin>
       <id>vertx-grpc-protoc-plugin2</id>
       <groupId>io.vertx</groupId>
       <artifactId>vertx-grpc-protoc-plugin2</artifactId>
       <version>${stack.version}</version>
       <mainClass>io.vertx.grpc.plugin.VertxGrpcGenerator</mainClass>
     </protocPlugin>
   </protocPlugins>
 </configuration>
 <executions>
   <execution>
     <id>compile</id>
     <configuration>
       <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
       <clearOutputDirectory>false</clearOutputDirectory>
     </configuration>
     <goals>
       <goal>compile</goal>
       <goal>compile-custom</goal>
     </goals>
   </execution>
 </executions>
</plugin>
----

The `${os.detected.classifier}` property is used to make the build OS independant, on OSX it is replaced
by _osx-x86_64_ and so on. To use it you need to add the os-maven-plugin[https://github.com/trustin/os-maven-plugin]
in the `build` section of your `pom.xml`:

[source,xml]
----
<build>
 ...
 <extensions>
   <extension>
     <groupId>kr.motd.maven</groupId>
     <artifactId>os-maven-plugin</artifactId>
     <version>1.4.1.Final</version>
   </extension>
 </extensions>
 ...
</build>
----

This plugin will compile your proto files under `src/main/proto` and make them available to your project.

If you're using Gradle you need to add the plugin:

[source,groovy]
----
...
apply plugin: 'com.google.protobuf'
...
buildscript {
 ...
 dependencies {
   // ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier gradle versions
   classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
 }
}
...
protobuf {
 protoc {
   artifact = 'com.google.protobuf:protoc:3.2.0'
 }
 plugins {
   grpc {
     artifact = "io.grpc:protoc-gen-grpc-java:1.25.0"
   }
   vertx {
     artifact = "io.vertx:vertx-grpc-protoc-plugin2:${vertx.grpc.version}"
   }
 }
 generateProtoTasks {
   all()*.plugins {
     grpc
     vertx
   }
 }
}
----

This plugin will compile your proto files under `build/generated/source/proto/main` and make them available to your project.

=== Writing a service

The plugin generates vertx idiomatic Vert.x service stubs.

Each service comes in two flavors, you can override the method you like depending on the style.

Unary services can return a Vert.x `Future`:

```java
VertxGreeterGrpcServer.GreeterApi stub = new VertxGreeterGrpcServer.GreeterApi() {
 @Override
 public Future<HelloReply> sayHello(HelloRequest request) {
   return Future.succeededFuture(HelloReply.newBuilder().setMessage("Hello " + request.getName()).build());
 }
};
```

or process a Vert.x `Promise`

```java
VertxGreeterGrpcServer.GreeterApi stub = new VertxGreeterGrpcServer.GreeterApi() {
 @Override
 public void sayHello(HelloRequest request, Promise<HelloReply> response) {
   response.complete(HelloReply.newBuilder().setMessage("Hello " + request.getName()).build());
 }
};
```

In both case you need to bind the stub to an existing `GrpcServer`:

```java
server.bindAll(stub);
```

==== Streaming requests

Streaming requests are implemented with Vert.x `ReadStream`:

```java
VertxStreamingGrpcServer.StreamingApi stub = new VertxStreamingGrpcServer.StreamingApi() {
 @Override
 public void sink(ReadStream<Item> stream, Promise<Empty> response) {
   stream.handler(item -> {
     System.out.println("Process item " + item.getValue());
   });
   // Send response
   stream.endHandler(v -> response.complete(Empty.getDefaultInstance()));
 }
};
```

==== Streaming responses

Streaming responses are implemented with Vert.x streams and comes in two flavors.

You can return a Vert.x `ReadStream` and let the service send it for you:

```java
VertxStreamingGrpcServer.StreamingApi stub = new VertxStreamingGrpcServer.StreamingApi() {
 @Override
 public ReadStream<Item> source(Empty request) {
   return streamOfItem();
 }
};
```

or you can process a `WriteStream`:

```java
VertxStreamingGrpcServer.StreamingApi stub = new VertxStreamingGrpcServer.StreamingApi() {
 @Override
 public void source(Empty request, WriteStream<Item> response) {
   response.write(Item.newBuilder().setValue("value-1").build());
   response.end(Item.newBuilder().setValue("value-2").build());
 }
};
```

=== Writing a client

The plugin generates Vert.x service clients.

A client wraps a `GrpcClient` and provides Vert.x idiomatic API to interact with the service:

```java
VertxGreeterGrpcClient client = new VertxGreeterGrpcClient(grpcClient, server);
```

Unary services returns a Vert.x `Future`

```java
Future<HelloReply> response = client.sayHello(HelloRequest.newBuilder().setName("John").build());

response.onSuccess(result -> System.out.println("Service responded: " + ar.result().getMessage()));

response.onFailure(err -> System.out.println("Service failure: " + ar.cause().getMessage()));
```

=== Streaming requests

Streaming requests use a lambda passed a Vert.x `WriteStream` of messages sent to the service

```java
Future<Empty> response = client.sink(stream -> {
 stream.write(Item.newBuilder().setValue("Value 1").build());
 stream.write(Item.newBuilder().setValue("Value 2").build());
 stream.end(Item.newBuilder().setValue("Value 3").build());
});
```

=== Streaming responses

Streaming responses get a Vert.x `ReadStream` of messages sent by the service

```java
Future<ReadStream<Item>> response = client.source(Empty.getDefaultInstance());

response.onSuccess(stream -> stream
 .handler(item -> System.out.println("Item " + item.getValue()))
 .exceptionHandler(err -> System.out.println("Stream failed " + err.getMessage()));
 .endHandler(v -> System.out.println("Stream ended")));

response.onFailure(err -> System.out.println("Service failure: " + ar.cause().getMessage()));
```