gRPC reflection and Evans CLI
Tags: grpc, tutorial, microservices, beginners
Published: 2020-05-22 08:56:01

Hello everyone!

Welcome back to the gRPC courses. In this lecture, we will learn about gRPC reflection and how to use Evans CLI to play with it.

gRPC reflection is an optional extension for the server to assist clients to construct requests without having to generate stubs beforehand. This is very useful for the clients to explore the gRPC API  before actually going into implementation.

{% youtube ag9Z8jFuY9A %}

Here's the link to the [full gRPC course playlist on Youtube](https://www.youtube.com/playlist?list=PLy_6D98if3UJd5hxWNfAqKMr15HZqFnqf)
Github repository: [pcbook-go](https://github.com/techschool/pcbook-go) and [pcbook-java](https://github.com/techschool/pcbook-java)
Gitlab repository: [pcbook-go](https://gitlab.com/techschool/pcbook) and [pcbook-java](https://gitlab.com/techschool/pcbook-java)

## Enable gRPC reflection on the server

### Golang

Let’s start by adding gRPC reflection to the **Golang** server.

As you can see in [this tutorial](https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md#enable-server-reflection), it’s super simple, we just need to import the `reflection` package and call `reflection.Register`.

So let’s do it!

```go
func main() {
    ...

	grpcServer := grpc.NewServer()
	pb.RegisterLaptopServiceServer(grpcServer, laptopServer)
	reflection.Register(grpcServer)

	...
}
```

In our `server/main.go` file, after register the laptop service, we call `reflection.Register` and pass in the gRPC server. 

That’s it!

### Java

How about **Java**?

It’s also [pretty straightforward](https://github.com/grpc/grpc-java/blob/master/documentation/server-reflection-tutorial.md). We have to add the gRPC service dependency to our project. And then add the `ProtoReflectionService` to the server.

Let’s go to maven repository and search for [gRPC service](https://mvnrepository.com/artifact/io.grpc/grpc-services).

![Maven gRPC service](https://dev-to-uploads.s3.amazonaws.com/i/ot4ert2fw76slimzixys.png)

Let’s copy the Gradle setting and paste it to the `build.gradle` file, then wait a bit for IntelliJ IDEA to update. 

```gradle
...

dependencies {
    ...

    // https://mvnrepository.com/artifact/io.grpc/grpc-services
    compile group: 'io.grpc', name: 'grpc-services', version: '1.28.0'
}

...
```

Then we go to `LaptopServer.java` file. In this constructor, after adding the laptop service to the server, we just add a new instance of the `ProtoReflectionService`. 

```java
...

import io.grpc.protobuf.services.ProtoReflectionService;

public LaptopServer(
    ServerBuilder serverBuilder, 
    int port, 
    LaptopStore laptopStore, 
    ImageStore imageStore, 
    RatingStore ratingStore
) {
    this.port = port;
    LaptopService laptopService = new LaptopService(laptopStore, imageStore, ratingStore);
    server = serverBuilder.addService(laptopService)
            .addService(ProtoReflectionService.newInstance())
            .build();
}

...
```

And voila, the gRPC reflection is enabled on the server.

## Install Evans client

Next step, we will install the [Evans CLI](https://github.com/ktr0731/evans) to play around with the server reflection.

Evans is a super cool gRPC client that allows you to construct and send requests to gRPC server in an interactive shell.

There are several ways to install it as described in its [Github page](https://github.com/ktr0731/evans).

I’m on a mac, so I will install it by Homebrew. First use `brew tap` to add this repository to Homebrew, then `brew install`:

```bash
brew tap ktr0731/evans
brew install evans
```

## Use Evans CLI with gRPC reflection

OK Evans is ready. Now let’s start the Golang gRPC server.

![Start golang server](https://dev-to-uploads.s3.amazonaws.com/i/89ad4kcwyes4o56x2344.png)

Since gRPC reflection is enabled on our server, we will run Evans with `--reflection` option.

So we run this command in the terminal and pass in the port 8080 of the server:

```bash
evans -r repl -p 8080
```

Then here we are, inside the Evans interactive shell. 

### Show and describe commands

We can call `show package` to see all packages available on the server. Then use the `package` command to choose a specific package.

![Start evans and show](https://dev-to-uploads.s3.amazonaws.com/i/1lc6ii2cjp29velrfeyc.png)

We can show all services of that package with `show service` command. Or show all messages as well with `show message` command. We can use the `desc` command to get the message format.

![Desc command](https://dev-to-uploads.s3.amazonaws.com/i/bnuruxsmbpivttwtjcif.png)

### Test the create laptop RPC

Now let’s choose the `LaptopService` and call the `CreateLaptop` API.

Evans will ask us to provide the data to construct a request.

- The first field is ID, which we can leave empty
- Then the laptop brand, let’s say Apple
- The laptop name: Macbook Pro
- The CPU brand: Intel
- The CPU name: let’s use Core i9
- The number of cores is 8
- The number of threads is 16
- Min frequency is 2.5 ghz
- Max frequency is 4.5 ghz

![Create input 1](https://dev-to-uploads.s3.amazonaws.com/i/a2j1y77m4re4h595site.png)

- Next will be the RAM, let’s say 32 GB. Evans allows us to select the enum value from the list. So it’s very comfortable to use.

![Create input 2](https://dev-to-uploads.s3.amazonaws.com/i/dc6i5fs27us9ggux4s2i.png)

- Now the GPU, Let’s say it’s a NVIDIA GTX 2020, with frequency from 2.0 to 2.5 Ghz, and 16 GIGABYTE of memory. Since GPU is a repeated field, Evans asks us for more values. If we want to stop, just press `Control D`

![Create input 3](https://dev-to-uploads.s3.amazonaws.com/i/ycr1mkeb079kasmpco31.png)

- The next field is storage, which is also a repeated field. Let’s say we have a SSD of 512 gigabytes and a HDD of 1 terabytes. Then control D to stop.

![Create input 4](https://dev-to-uploads.s3.amazonaws.com/i/9dfnxknrbpaadta8zvm6.png)

- The screen size will be 16 inches, and the screen resolution is 3072 x 1920. It’s not a multitouch screen, so I’ll put false here.
- The keyboard layout is QWERTY, and it is a backlit keyboard, so let’s put `true` here.
- Next, the weight of the laptop will be in kilograms, and the value is 2.2
- The price is 3000 USD
- The release year is 2019
- And finally the updated_at field we can leave empty

![Create output](https://dev-to-uploads.s3.amazonaws.com/i/b2k6lvyiq9nmuozp53ie.png)

Now as you can see the request is sent to the server, and we get back a response with the ID of the created laptop.

### Test the search laptop RPC

Let’s try the Search Laptop API to see if we can find that laptop on the server or not.

![Call search laptop](https://dev-to-uploads.s3.amazonaws.com/i/ap1yiolpsbb64va70znn.png)

- The max price is 4000
- The min CPU cores is 4
- The min CPU frequency is 2.0
- And the minimum RAM is 8 gigabytes.

![Search result](https://dev-to-uploads.s3.amazonaws.com/i/wm17ncwd88ttfszvwpiq.png)

Cool, the laptop is found!

So the gRPC reflection is working well on our Golang server. The gRPC reflection on the Java server will be the same. You can try it on your own if you like.

Thanks for reading and see you soon in the next article!

---

If you like the article, please [subscribe to our Youtube channel](http://bit.ly/techschoolguru) and [follow us on Twitter](https://twitter.com/techschoolguru) for more tutorials in the future.

---
If you want to join me on my current amazing team at Voodoo, check out [our job openings here](https://bit.ly/voodoojobs). Remote or onsite in Paris/Amsterdam/London/Berlin/Barcelona with visa sponsorship.