Spring Boot 3 + gRPC Bidirectional Streaming Example
This pattern is commonly used in scenarios where there is a need for ongoing, interactive communication. For example, in a gaming application where multiple gamers may need to continously interact with each other. Other scenario is the autocomplete feature in google search, where the user types some word and is given some possible options which he may select.
We will be implementing the following scenario. Consider a banking service where the client chats with bank customer service. The client can send multiple requests and receive multiple responses. Similarly the bank customer service can receive multiple requests and send multiple responses.

- 1. When the client sends the message "Hi", the server responds with "Hello how can i help you today."
- 2. If the client requests information about their account balance by sending the message "I need to know my account balance", the server acknowledges this request with the message "Ok. Please type the OTP received on your registered phone".
- 3. Upon receiving the OTP "5050" from the client, the server responds with "Ok. The account balance is 300".
- 4. In case the client sends an OTP other than "5050", the server responds with "Invalid OTP".
Video
This tutorial is explained in the below Youtube Video.gRPC - Table of Contents
Spring Boot+ gRPC Hello World Example Spring Boot gRPC Server + C# gRPC Client Example Spring Boot 3 + gRPC - Types of gRPC Spring Boot 3 + gRPC Unary Example Spring Boot 3 + gRPC Server Streaming Example Spring Boot 3 + gRPC Client Streaming Example Spring Boot 3 + gRPC Bidirectional Streaming Example Spring Boot + gRPC Deadline Example Spring Boot + gRPC Error Handling Example Spring Boot + gRPC Error Handling - Using Trailer Metadata Spring Boot + gRPC Error Handling - Global Exception Handler Using GrpcAdvice
Implementation
Spring Boot Bidirectional Streaming gRPC Server
We will be creating a maven project as follows -
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javainuse</groupId> <artifactId>boot-bidirectional-streaming-grpc-server</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.0</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <protobuf.version>3.17.3</protobuf.version> <protobuf-plugin.version>0.6.1</protobuf-plugin.version> <grpc.version>1.59.0</grpc.version> </properties> <dependencies> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> <version>2.15.0.RELEASE</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>${grpc.version}</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>${grpc.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>annotations-api</artifactId> <version>6.0.53</version> <scope>provided</scope> </dependency> </dependencies> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.7.1</version> </extension> </extensions> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact> com.google.protobuf:protoc:3.24.0:exe:${os.detected.classifier} </protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact> io.grpc:protoc-gen-grpc-java:1.59.0:exe:${os.detected.classifier} </pluginArtifact> <protoSourceRoot> ${basedir}/src/main/proto/ </protoSourceRoot> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>Next create the proto file named bank-service.proto in src/main/proto folder. A proto file in gRPC is a special type of file that helps define the structure and communication between different software components. It acts like a blueprint for creating and interacting with these components. The file also defines a service ChatService for bidirectional streaming in a chat system.
syntax = "proto3"; package banking; option java_multiple_files = true; option java_package = "com.javainuse.banking"; // Message representing a client's message in a chat system message ChatMessage { string sender = 1; string message = 2; } // Message representing a server's response in a chat system message ChatResponse { string sender = 1; string message = 2; } // Service for bidirectional streaming for chat support service ChatService { rpc StartChat (stream ChatMessage) returns (stream ChatResponse) {} }