Goal of this project is to demonstrate gRPC based communication between Angular application and java backend.
Main benefits of this approach:
- server and client stubs are generated automatically out of formal API description in proto format
- proto messages are backward compatible so it's easy to add new fields without breaking code
- streaming support
Example definition of proto gRPC service:
service ChatService {
rpc ReceiveMessages (ReceiveMessagesRequests) returns (stream ChatMessage) {}
rpc SendMessage (ChatMessage) returns (google.protobuf.Empty) {}
rpc Ping (ChatMessage) returns (ChatMessage) {}
}
message ChatMessage {
string message = 1;
string user = 2;
google.protobuf.Timestamp timestamp = 3;
}
There's no direct way to call gRPC from browser so additional proxy is required to translate http calls into gRPC calls. Envoy solves this problem.
Disclaimer this is just a PoC/demo. It's rather quick and dirty. Focused mostly on getting it all running togheter. Further improvemetns/cleanup to come in future :)
Disclaimer: setup is tested on ubuntu. Might need some adjustments on Windows machines.
- maven
- npm
- protoc
- docker
cd ${PROJECT_ROOT}
mvn install
cd ${PROJECT_ROOT}/chat-backend-grpc/
mvn spring-boot:run
cd ${PROJECT_ROOT}/chat-webapp/
npm install
npm run compile
npm run start
${PROJECT_ROOT}/chat-proxy/start-local.sh
Open your favourite browser and navigate to http://localhost:8080/
cd ${PROJECT_ROOT}/chat-webapp/
npm run compile
cd ${PROJECT_ROOT}
mvn install
docker-compose build
docker-compose up
Open in browser http://locahost:28080/
Current setup requires java app build and proto->typescript compilation outside of docker. Next step is to do it inside docker so then maven/npm/protoc would not be prerequiste to build.
- chat-proto/src/main/proto/chat.proto - gRPC / proto messages definitions
- chat-backend-grpc/src/main/java/pl/jcw/demo/chat/backend/grpc/ChatServiceImpl.java - java service implementation
- chat-webapp/src/app/api.service.ts - typescript service client implementation
- chat-proxy/envoy(-local).yaml - envoy proxy configuration
To add new service:
- Add definition in chat.proto
- Maven build of chat-proto project (this will generate java stub)
- Implement new service in chat-backend-grpc
- Compile typescript client code: npm run compile
- Implement clinent consumer in app
One disadvantage of gRPC is that it's binary format - not that easy to play with it as with JSON. Fortounately there's great GUI client (like POSTMAN) for gRPC -> BloomRPC. I find it even more convinient that POSTMAN/JSON. It has access to formal API definition so it's able to generate nice requests with all the parameters out of the box.
ng new chat-webapp
npm install --save-dev @angular/cli @angular-devkit/build-angular @angular/compiler @angular/compiler-cli grpc_tools_node_protoc_ts @types/node grpc-tools
npm install --save grpc tls stream os fs ts-protoc-gen protoc path grpc-web-client google-protobuf @types/google-protobuf @improbable-eng/grpc-web
Add node types to chat-webapp/src/tsconfig.app.json
"compilerOptions": {
"types": ["node"]
},
- https://github.com/kmturley/angular-nest-grpc - helped me to get initial setup of envoy proxy and understand how to call gRPC from typescript