Building an end-to-end system in dart using grpc* & flutter(Part 1)

Let’s say you want to build a simple system where people can search for hospitals. Your app needs to request the server for a list of all hospitals and also you want to search for hospitals.

For the hospital object, you would need a name, coordinate(x,y), region its in and let’s say the type of hospital(e.g private or public).

And imagine for once, you want to call your endpoint like hospitalServer.getHospitals() to get a list of hospitals and hospitalServer.searchHospitals(SearchQuery) without having to receive your data as json and then reading it to json and then parsing it back to dart objects to use in your application.

And also despite the backend language you use, e.g python, go, php, java, nodejs, c# and any grpc supported language, you want to call your server like hospitalServer.getHospitals() in dart and get a response that is not in json but in PODO(Plain Dart Objects).

Wouldn’t that be awesome? That’s possible with grpc.

How do we talk?

So for the case of our hospitals, you tell your backend guy that you need two endpoints, one for getting a list of hospitals and one for searching hospitals using a string. Obviously you’ll need to create a contract/ defined format that you’ll use to communicate. This is where protocol buffers come in. It’s a simple file with extension of .proto where you define how you want to send and receive your messages from the server to the client and vice-versa.

In our case, we’ll define our messages as follows

defining grpc server endpoints

rpc is just a shorthand for a method contract that says, when I ask the HospitalServer to GetHospitals, it returns a list of Hospitals. Equivalently, when I ask the HospitalServer to SearchHospitals using a SearchQuery, I want a list of hospitals based on the SearchQuery. Think of GetHospitals and SearchHospitals like functions in an object under HospitalServer class.

In programming, we are always talking using messages. A message in grpc is basically a definition of your objects. Think of them like classes in OOP.

How to define your messages(classes in OOP)

So in our example, to search for Hospitals using SearchHospitals method, you send a SearchQuery message to your server and receive back a Hospitals message which will contain a list of hospitals.

Once the contract has been defined, grpc will generate the respective classes or models or abstract classes which you’ll use in your application.

It generates an abstract server definition which will have abstract methods which you’ll have to implement the logic for and client classes which you’ll use to make calls to the server.

Implementing the server

Dart Implementation

Create a new dart project and under lib, create a directory called src/protos and save the filename above as contract.proto under lib/src/protos.

You can clone this repo here to get a ready generated example.

To generate the server and client libraries(you can call them that), we need protoc. Since we’ve defined our contract in Protocol Buffers, we need to run the protocol buffer compiler protoc on the hospital.proto to generate our server SDK. Check out this link to install protoc. https://developers.google.com/protocol-buffers/docs/darttutorial#compiling-your-protocol-buffers

We also need to install dart’s protoc package globally for the command below to work. More info here.

pub global activate protoc

Create a directory called generated under lib/src/protos where the generated client and server classes will be saved. Then run the command

protoc -I lib/src/protos/ lib/src/protos/hospitals.proto --dart_out=grpc:lib/src/protos/generated/

If you couldn’t generate the dart classes, I got you. Check out the repo on GitHub to get files at this step.

Add the grpc and protobuf packages to your pubspec.yaml in order to get started implementing the server.

Let’s implement the server. In our case, to keep the example short, we will not be reading from a database (although dart has support for postgres, mongo, mysql and many more. Just head to pub.dev and explore.) but rather reading from a csv file containing hospital names and locations from Kenya.

For that, we read the csv columns using the function below

Function to read the elements of the csv

The headers of the csv include many elements but we’re interested in only longitude, latitude,name and type which are at index 0,1,2 and index 5 respectively which we tranform from list of csv rows to a list of HospitalData rows.

Implement server functions and logic

The protoc compiler generates dart files which we’ll need to implement and serve using the grpc server.

To implement the server, we simply extend the generated *ServiceBase. In our case its HospitalServerServiceBase which we implement as below.

Generated classes which we need to implement logic for how we want the server to function.

The flow will be when HospitalServer starts, we supply it with a list of HospitalData which will be converted to Hospital model which exists in our contract as a message like below.

getHospitals Implementation

searchHospitals Implementation

We just put a filter on hospitals with the name requested by client which is stored in request.

Orchestrating the Entire Server in bin\main.dart

We’ll simply read the csv of hospitals and pass it to our HospitalServer which will be used when handling requests. We then run the server using Server from the grpc package binding it to localhost at port 12345.

Creating the client

client.dart

This is the beauty of grpc. It handles serialization and deserialization of the payload in an simple way.

In our instance, we can copy the generated dart files by protoc to a flutter project and call the server like in the client.dart example above and render the UI without creating Models.fromJson(haha) here.

In the next post, we’ll dive into building the UI for our HospitalSearch application using Flutter.

Till then, Happy Darting.

The code for all this is available in the repo below.

https://github.com/bettdouglas/hospitals

Hope you enjoyed this. If you have a question, leave a comment below and I’ll try my best to answer. If you had issues understanding it, head over to https://grpc.io/docs/what-is-grpc/introduction/ to learn more and remember to try it till it sticks.

Software Developer in code wanderlust. Interested in Geospatial Systems and Mobile Development