Spring Boot with gRPC[EN]

Alexander Uryadov
4 min readDec 5, 2022

--

After a long search for an elegant and concise implementation of gRPC with Spring Boot and Gradle, reading the documentation, and also resorting to the help of Stack Overflow, I decided to write an article(russian). Here I would like to describe only the process of creating a server and a client, without resorting to theory and explaining what gRPC is.

To go directly to the task at hand, you must have minimal knowledge of working with Spring Boot. If you are reading this article, you are probably already familiar with the above technologies.

1. Server

1.1. Adding dependencies.

First, let’s create a Spring Boot project and add a plugin and one dependency to the build.gradle file.

Plugin:

id 'com.google.protobuf' version '0.8.19'

Dependency:

implementation 'net.devh:grpc-server-spring-boot-starter:2.13.1.RELEASE'

This is what the final file will look like build.gradle:

plugins {
id 'org.springframework.boot' version '2.7.4'
id 'io.spring.dependency-management' version '1.0.14.RELEASE'
id 'java'
id 'idea'
// protobuf plugin
id 'com.google.protobuf' version '0.8.19'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '8'

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter'

// grpc server
implementation 'net.devh:grpc-server-spring-boot-starter:2.13.1.RELEASE'
}

Let’s create a helper file grpc.gradle for gRPC configuration. This configuration could be written in the original build.gradle file, but it’s better not to litter it, and to keep everything related to gRPC separately.

File grpc.gradle:

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.7.1"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.19.0"
}
}
generateProtoTasks {
ofSourceSet('main').each { task ->
task.builtins {
java {
outputSubDir = 'proto_gen'
}
}
task.plugins {
grpc {
outputSubDir = 'proto_gen'
}
}
}
}
generatedFilesBaseDir = "$projectDir/src/"
}
task cleanProtoGen {
doFirst {
delete("$projectDir/src/main/proto_gen")
}
}

clean.dependsOn cleanProtoGen

That’s all about dependencies.

1.2. Implementation.

Let’s create a test.proto file along the path src/main/proto/test.proto:

The next step is to implement the test method defined in the proto.test file. To do this, let’s create the MyServiceImpl class:

This completes the creation of the server, but another configuration that can be skipped is changing the server port. The server port is 9090 by default, you can set it in the application.properties:

grpc.port=9090

1.3. Testing.

To check the performance of our server, you can use Postman.

Let’s create a new gRPC Request type:

Import the test.proto file from the project Choose a File => Next:

Let’s write the address of our server localhost:9090 and from the drop-down list select the remote method (procedure) test. In the message tab, let’s pass our request:

In the Response tab, we get a response from our server.

2. Client

2.1.Adding dependencies.

The process of adding dependencies to the client is identical to the server but differs in only one dependency. Let’s create another Spring Boot project and add a plugin and one dependency to the build.gradle file.

Plugin:

id 'com.google.protobuf' version '0.8.19'

Dependency:

implementation 'net.devh:grpc-client-spring-boot-starter:2.13.1.RELEASE'

This is how the final build.gradle file will look like:

plugins {
id 'org.springframework.boot' version '2.7.4'
id 'io.spring.dependency-management' version '1.0.14.RELEASE'
id 'java'
id 'idea'
// protobuf plugin
id 'com.google.protobuf' version '0.8.19'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
// grpc client
implementation 'net.devh:grpc-client-spring-boot-starter:2.13.1.RELEASE'
}

Let’s create a helper file grpc.gradle for the gRPC configuration.

File grpc.gradle:

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.7.1"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.19.0"
}
}
generateProtoTasks {
ofSourceSet('main').each { task ->
task.builtins {
java {
outputSubDir = 'proto_gen'
}
}
task.plugins {
grpc {
outputSubDir = 'proto_gen'
}
}
}
}
generatedFilesBaseDir = "$projectDir/src/"
}
task cleanProtoGen {
doFirst {
delete("$projectDir/src/main/proto_gen")
}
}

clean.dependsOn cleanProtoGen

That’s all about dependencies.

2.2. Implementation.

Let’s create a test.proto file along the path src/main/proto/test.proto:

The next step is to create a class that uses the test method of our GrpcTestService service:

The last step is to add our server address to the application.yaml file:

3. Testing

To test the client’s interaction with the server, let’s add a call to the printResponse method after the client starts. For this purpose, we will use the ApplicationRunner:

Let’s run both applications and in the client logs we can observe the result of the printResponse method execution:

Conclusion

In this article, I tried to briefly describe the process of creating a server and client with a minimum amount of code and configuration. I hope the article was useful and you can use it in your projects.
Repository links:

Server: https://github.com/UryadovAlex/grpc-server.git

Client: https://github.com/UryadovAlex/grpc-client.git

--

--

Alexander Uryadov

Experienced Software Engineer with a demonstrated history of working in the computer software industry.