gRPC makes our development easier to communicate with an application that is written in a different language. I tried to use gRPC in Golang before and posted the following two articles.
I implemented the same feature in Dart language. So I share the knowledge in this post with you.
- (this post) Dart How to setup devcontainer for gRPC
- Dart The first gRPC server and client with timestamp
- Dart Server Streaming gRPC function example to download a file
- Dart Client Streaming gRPC function example to Upload a file
- Dart gRPC Bidirectional streaming example
You can clone my GitHub repository if you want to try it yourself.
Set up Dockerfile
We have to set up Dockerfile to make it work in devcontainer. I followed the official page Quick Start. We need to install protocol buffer compiler.
# Install the compiler for protocol buffer
RUN curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v22.3/protoc-22.3-linux-x86_64.zip" && \
unzip protoc-22.3-linux-x86_64.zip -d /usr/local && \
rm protoc-22.3-linux-x86_64.zip
Then, I added the following for Dart.
# Install for Dart
RUN sudo apt update && \
sudo apt install apt-transport-https && \
wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/dart.gpg && \
echo 'deb [signed-by=/usr/share/keyrings/dart.gpg arch=amd64] https://storage.googleapis.com/download.dartlang.org/linux/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list && \
sudo apt update && \
sudo apt install dart && \
# Install proto for Dart
dart pub global activate protoc_plugin && \
# ===== NOT WORK !!! ====
export PATH="$PATH:$HOME/.pub-cache/bin"
The proto files are already created for Golang; thus, I tried to generate gRPC files, but it didn’t work.
$ protoc --dart_out=./internal/proto -Iprotos ../../proto/middle.proto
protos: warning: directory does not exist.
../../proto/middle.proto: File does not reside within any path specified using --proto_path (or -I). You must specify a --proto_path which encompasses this file. Note that the proto_path must be an exact prefix of the .proto file names -- protoc is too dumb to figure out when two paths (e.g. absolute and relative) are equivalent (it's harder than you think).
$ protoc --dart_out=./internal/proto --proto_path=../../proto -Iprotos ./middle.proto
protos: warning: directory does not exist.
Could not make proto path relative: ./middle.proto: No such file or directory
$ protoc --dart_out=./internal/proto --proto_path=../../proto -Iprotos middle.proto
protos: warning: directory does not exist.
protoc-gen-dart: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--dart_out: protoc-gen-dart: Plugin failed with status code 1.
It seems that $HOME
path can’t be used in Dockerfile for the vscode user. I tried echo $HOME
but it shows $HOME
as a string. The following way works neither.
# NOT WORK!!
RUN export PATH="$PATH:/home/vscode/.pub-cache/bin"
Therefore, PATH needs to be set with ENV
.
# Install for Dart
RUN sudo apt update && \
sudo apt install apt-transport-https && \
wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/dart.gpg && \
echo 'deb [signed-by=/usr/share/keyrings/dart.gpg arch=amd64] https://storage.googleapis.com/download.dartlang.org/linux/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list && \
sudo apt update && \
sudo apt install dart && \
# Install proto for Dart
dart pub global activate protoc_plugin
ENV PATH="$PATH:/home/vscode/.pub-cache/bin"
In this way, the path is correctly added to $PATH
.
This is the first part that I took some time to find out.
protoc command for Dart
Once the devcontainer is established, let’s define generate
command in Makefile to make the protoc command simple. We need to set the output path. It must be created in advance. Then, we can set the relative path to the directory where proto files exist with --proto_path
or -I
. At last, give the proto file names.
generate:
@protoc --dart_out=grpc:./lib/proto \
-I../../proto \
middle.proto \
types_def.proto
If you want to make it clearer, use --proto_path
.
generate2:
@protoc --dart_out=grpc:./lib/proto \
--proto_path=../../proto \
middle.proto \
types_def.proto
We can generate code from the defined proto files with the following command.
make generate
We have to regenerate the code whenever we update proto files. This Makefile definition makes our development easier.
Define timestamp in protobuf
Timestamp is often needed but timestamp is not built-in type in protocol buffer. We need to import another proto file as you can see in the following example.
// proto file
syntax = "proto3";
import "google/protobuf/timestamp.proto";
option go_package = "api-test/grpc/apitest";
service Middle {
...
}
However, the following error is shown without modifying our make generate
command.
Target of URI hasn't been generated: 'google/protobuf/timestamp.pbjson.dart'. Try running the generator that will generate the file referenced by the URI.darturi_has_not_been_generated
The necessary file doesn’t exist in our directory. Add the same path to the generate command at the end to solve this problem.
generate2:
@protoc --dart_out=grpc:./lib/proto \
--proto_path=../../proto \
middle.proto \
types_def.proto \
google/protobuf/timestamp.proto
Then, google/protobuf/
directory is newly created in proto directory and the corresponding files are generated there.
Add necessary packages to pubspec.yaml
Let’s add the necessary packages. Execute the following command.
dart pub add grpc protobuf fixnum
grpc and protobuf are of course needed. fixnum
is used in the generated code to define for example Int64. Since a normal Dart int can’t be assigned to it, we need to add the package.
Install VSCode extensions
Let’s add useful vscode extensions.
"customizations": {
"vscode": {
"extensions": [
"zxh404.vscode-proto3",
"ms-vscode.makefile-tools",
"xaver.clang-format",
"dart-code.dart-code"
]
}
}
I installed clang-format in Dockerfile too.
# To format proto file with vscode-proto3 extension
RUN apt update && apt install clang-format --yes
clang-format is used in vscode-proto3 to format the code. Go to my repository if you want to see the complete Dockerfile.
Go to further
The next step is to define the first function in protocol buffer and implement it.
Comments