During the last couple of weeks I’ve been identifying and documenting what it takes to get Eclipse Vert.x applications to work as GraalVM native images. Until now tweaks and fixes are in place to allow developers to use many common components (bellow you’ll see a small subset of this list), So today I’ll be describing gRPC.

gRPC

The best description of gRPC can be seen at wikipedia:

gRPC is an open source remote procedure call (RPC) system initially developed at Google. It uses HTTP/2 for transport, Protocol Buffers as the interface description language, and provides features such as authentication, bidirectional streaming and flow control, blocking or nonblocking bindings, and cancellation and timeouts. It generates cross-platform client and server bindings for many languages.

When investigating the code and dependencies of gRPC I was concerned that this could be a complex beast to handle, but I was wrong! Actually everything works.

Bootstrap a gRPC project

In order to simplify your work I’ve a small static website that generates projects for you, don’t worry, it’s a static html app, it all runs on your browser, nothing is sent to servers, all your secrets stay with you.

If you get the same options I have you can go ahead and generate your skeleton project. Once you’ve done this and open the MainVerticle.java file you can start coding your own server. However before we get there we need a proto file. The proto file will contain the description of your API, since this is a lazy example let’s just use the hello world example that you can get with gRPC and add it to src/main/proto/helloworld.proto :

syntax = "proto3" ; option java_multiple_files = true ; option java_package = "io.grpc.examples.helloworld" ; option java_outer_classname = "HelloWorldProto" ; option objc_class_prefix = "HLW" ; 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 ; }

As you can see it’s a very simple protocol, there’s a Greeter service that you can use to send HelloRequest s and there’s a HelloReply that will contain a message back. Knowing this we can write our own server as:

Vertx vertx = Vertx . vertx (); VertxServer server = VertxServerBuilder . forAddress ( vertx , "127.0.0.1" , 50051 ) . addService ( new GreeterGrpc . GreeterVertxImplBase () { @Override public void sayHello ( HelloRequest req , Future < HelloReply > fut ) { System . out . println ( "Hello " + req . getName ()); fut . complete ( HelloReply . newBuilder () . setMessage ( "Hi there, " + req . getName ()) . build ()); } }). build (); server . start ( ar -> { if ( ar . succeeded ()) { System . out . println ( "gRPC service started" ); } else { ar . cause (). printStackTrace (); System . exit ( 1 ); } });

As usual one needs to build it:

./mvn -Pnative-image

And you will end up with a 18MB binary.

Writing a client

Of course we’ll need a client too, so here’s what you need:

ManagedChannel channel = VertxChannelBuilder . forAddress ( vertx , "localhost" , 50051 ) . usePlaintext ( true ) . build (); GreeterGrpc . GreeterVertxStub stub = GreeterGrpc . newVertxStub ( channel ); HelloRequest request = HelloRequest . newBuilder (). setName ( "Paulo" ). build (); stub . sayHello ( request , asyncResponse -> { if ( asyncResponse . succeeded ()) { System . out . println ( "Succeeded " + asyncResponse . result (). getMessage ()); } else { asyncResponse . cause (). printStackTrace (); } });

Testing

From this moment on, all you need to do is run both application and see the output:

server: gRPC service started server: Hello Paulo client: Succeeded Hi there, Paulo

Conclusion

I am really impressed with the work the GraalVM and SubstrateVM team has done, in order to support such complex things as the ones I’ve got to work:

vertx

netty

postgres

redis

gRPC

protocol buffers

websockets

HTTP2

etc…