Ballerina + gRPC

Buddhi Kothalawala
Ballerina Swan Lake Tech Blog
6 min readApr 7, 2020

gRPC is now becoming one of the hottest topics in the world of distributed systems. On the other hand, have you ever thought about a programming language that has primitive support for cloud-native features. That is how the Ballerina programming language comes into the picture and plays a major role by providing various cloud-related features for the programmers. This article is devoted to discussing how the Ballerina language enriched with features that help programmers to develop gRPC applications. If you are a newbie to this gRPC+Ballerina world, don’t worry, this blog will provide you the introduction for gRPC and Ballerina. However, if you are a pro-player in this gRPC world, then just skip the following introductory sections.

What is gRPC?

Early days we used API protocols such as SOAP but after that, we moved to the REST API protocol that developed on top of HTTP. gRPC is one of the new players in this API protocol world. gRPC can be defined as a modern RPC (Remote Procedure Calls) framework based on HTTP/2. Usage of protocol buffers makes gRPC communication lighter and faster compared to other communication methods. Protocol buffers make serialization and deserialization much more efficient compared to other data representations such as text, JSON, and XML.

Why Ballerina?

Nowadays, everybody talks about the cloud and tries to move their enterprise application to the cloud to provide a better user experience. Ballerina is a programming language and platform that enriches various cloud features in the language itself. For example, Ballerina provides language-level support for, developing network endpoints and clients, JSON and XML data types, Docker and Kubernetes deployments, and much more. Note that the implementation of the use case in this article uses Ballerina version 1.2.0.

Note that you can install Ballerina easily in your preferred system using the guidelines provided by this article.

Ballerina CLI Support for gRPC

Ballerina CLI (Command Line Interface) has encapsulated several Ballerina language and platform related tasks into a simple set of commands. For example, you can use the following commands to create new Ballerina projects and modules:

// Create a new Ballerina project
$ ballerina new <PROJECT_NAME>
// Add new modules to the project
$ ballerina add <MODULE_NAME>

The Ballerina CLI also has the gRPC support which takes protobuf file as an input and generates relevant Ballerina client, server, and stub files according to the protocol buffer definition.

In this article, I am planning to discuss a very simple health care app that shows how to implement a gRPC client and a server. This health care use case just has microservices to register a patient and fetch the patient information. Note that I did not add any database interactions or any other external things that make this use case much more complicated since I merely want to emphasize the gRPC functionalities.

The following protobuf file has been used during the implementation of the entire use case. This protobuf definition has two Remote Procedure Calls (RPC) and uses the message type called Patient to hold the patient information. The remote procedure calls can be described as follows:

  • registerPatient — this procedure call takes a Patient message as an input and returns a boolean value true if the registration was successful
  • getPatientInfo — this one takes a patient ID as a string value input and returns a Patient message that contains the patient information

Now you can use the Ballerina gRPC command to generate relevant server, client, and stub files. The structure of the Ballerina gRPC command is as follows:

$ ballerina grpc --input <INPUT_PROTOBUF_FILE> --mode <GENERATION_MODE> --output <OUTPUT_DIRECTORY>
  1. INPUT_PROTOBUF_FILE — the path to the protobuf file that you want to use as the definition
  2. GENERATION_MODE — the optional mode of the generation. It has 3 modes: default, service, client. The default mode means when you did not specify any mode at all. At that time the above command will generate the stub file that contains the procedure call definitions, record types, and descriptors. On the other hand, service mode will generate the boilerplate Ballerina code for a gRPC service and the client mode will generate the boilerplate Ballerina gRPC client code according to the given protobuf definition. Note that, the client mode will generate the client boilerplate code along with the stub file. However, the gRPC service mode does not need the procedure call definitions in the stub file because those definitions are only used in the client-side. Therefore, the gRPC command will remove these procedure call definitions from the service mode and only generate service boilerplate code along with the record types.
  3. OUTPUT_DIRECTORY — this is the directory that you need to output the generated Ballerina files

Let’s generate the server and client code for the above protobuf file. The following command will generate the server boilerplate code.

$ ballerina grpc --input health-stub.proto --mode service --output .

The generated server boilerplate code will be as follows:

After that, you can use the following command to generate client boilerplate code. Note that, this command will generate the client and the stub file at the same time.

$ ballerina grpc --input health-stub.proto --mode client --output .

The generated client code will be as follows:

And the generated stub file will be as follows:

The Architecture of the Use Case

The following diagram illustrates the architecture of the use case that we are planning to implement in this article.

As the first step, the Ballerina client initiates the procedure call from the gRPC stub. As the second step, the stub calls the backend Ballerina server passing the request message and finally, the Ballerina server returns the response back to the client. The generated Ballerina code for the server, client, and stub files in the previous section directly maps to the server, client, and the stub depicted in the above diagram.

Server Implementation

This section discusses the actual implementation of the Ballerina gRPC server on top of the generated server code. The implementation of a resource function in the server-side will be as follows:

This resource function simply logs the received Patient data from the client-side and sends the boolean value true to indicate that the registration was successful. If something went wrong in the sending process this will log an error. Thereafter, the caller will complete the call.

Client Implementation

The implementation of the gRPC client will be as follows:

The client initiates with the generated blocking endpoint client object creation. Hereafter creates a Patient record and invokes registerPatient with the patient argument. If something goes wrong the client will log that error, otherwise, it will print out the values received in the response.

Implementation of the Entire Use Case

Note that, you can find out the entire implementation of this use case along with the steps to run it from this GitHub repository.

Conclusion

gRPC is becoming one of the de facto methods in the communication of distributed systems. Therefore, most of the programming languages try to provide gRPC support using external libraries or as a language embedded feature. In this article, we discussed how the Ballerina language supports gRPC functionalities from the language itself. The Ballerina CLI came up with the support of generating boilerplate codes for gRPC server, client, and stub. That makes programmers’ lives easier and programmers only need to worry about the actual implementation of the use case.

References

  1. https://grpc.io/about/
  2. https://ballerina.io/
  3. https://www.mertech.com/blog/know-your-api-protocols
  4. https://github.com/BuddhiWathsala/grpc-healthcare-app/tree/v1.2.0

--

--

Buddhi Kothalawala
Ballerina Swan Lake Tech Blog

Try to discover solutions beyond probabilistic Turing machine :D