
Using gRPC and ProtoBuf in Java
This article is part of the series Building a Web Server
Welcome back to the Building a Web Server series. So far we’ve primarily focused on writing web servers in GoLang. However, I’ve received requests to write an article on how the gRPC implementation can be done using Java, and what are the available libraries and options to achieve the same.
Pre-requisite: Basic understanding of Spring, Spring Boot, Dependency Injection, RPC and ProtoBuf.
We will use spring boot to initialise a basic service and then will add an RPC server and client on top of it.
Steps to write a Java gRPC server
Assuming we have generated a code from the spring initlizr website with project name as grpc-server
- We define the service protobuf file and add the required dependencies in
pom.xml
to compile the proto files and generate RPC Java interfaces as part of the build process. - Next we move on to write a basic
HelloWorld
server. - Compile the code and call the RPC server to test the same.
1. Writing Proto definitions
Protobuf definitions are language agnostic and hence don’t change across all the options available to us. For this server example, we will write a very basic HelloWorld service as follows:
syntax = "proto3";
option java_multiple_files = true;
package com.test.grpc;
message HelloRequest {
string firstName = 1;
string lastName = 2;
}
message HelloResponse {
string greeting = 1;
}
service HelloService {
rpc hello(HelloRequest) returns (HelloResponse);
}
Make sure you create this file under the main
directory, else the proto files will not be included in the build process. File Path: <project-root>/src/main/proto/HelloService.proto
Next, add the following dependency, extension, and plugin to pom.xml
// add the following dependency to dependencies section. This dependency helps you to run a basic GRPC server out of the box by using the io.grpc module.
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-autoconfigure</artifactId>
<version>2.12.0.RELEASE</version>
</dependency>//add the following extension to build section. This extension adds OS specific logic during the protobuf compilation step.
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
</extension>
</extensions>// add the following plugin to the build section. This plugin compiles the protobuf files and adds it to the target folder.
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf-maven-plugin.version}</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>// add the following to properties section
<protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
<os-maven-plugin.version>1.6.1</os-maven-plugin.version>
After making changes to the pom.xml
file, run mvn clean install
to compile the code and generate the required boilerplate java code from the protobuf definition.
2. Hello World Server
Setting up the server is relatively an easy task once we have figured out the build and compilation step for protobuf.
Let’s create a basic java gRPC server by implementing the base class of `com.test.grpc.HelloServiceGrpc.HelloServiceImplBase` which was generated as a part of our proto compilation step.
@GrpcService
public class HelloServiceImpl extends HelloServiceImplBase {
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
System.out.println("Received:" + request);
String greeting = new StringBuilder().append("Hello, ")
.append(request.getFirstName())
.append(" ")
.append(request.getLastName())
.toString();
HelloResponse response = HelloResponse.newBuilder()
.setGreeting(greeting)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
Next, We need to initialise the server and register our gRPC service implementation against the same. Modify your GrpcServerApplication.java
file to look like this:
@SpringBootApplication
public class GrpcServerApplication {
public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(8080)
.addService(new HelloServiceImpl()).build();
System.out.println("Starting server...");
server.start();
System.out.println("Server started!");
server.awaitTermination();
}
}
In the above file we create a new gRPC server on port 8080
and register our HelloServiceImpl
with the same.
3. Compilation and testing
Till now we created a basic RPC server implementation in Java using the proto definition and registered the same into our server. The magic of RPC server creation is handled by the net.devh
dependency which we added in the first step.
Now, go ahead, run the server and test it for serving the requests.
Compile and Run: mvn spring-boot:run
The above command starts a gRPC server which can be tested using multiple tools like yab, and grpcurl.
With this, server setup is complete using Java in Spring boot. In the next article, we will consume the data provided by this server by spinning up a client. We will also add a GoLang client for the same to see how RPC based communications are easier and more efficient across multiple services without any language barriers.
Coding Fun Fact: According to many online studies, the most disliked programming languages are Perl, Delphi, and VBA.
Request: Please add your valuable feedback in the comments. It would really help me improve the quality of content and bring it in-line with your expectations.