In a previous post, we discussed gRPC as a framework developed by Google that facilitates connectivity in a polyglot world. So today, let’s explore a practical example with gRPC in Spring Boot.
Let’s get started
Maven Dependencies
After you create the skeleton of your Spring Boot project, which you can do using the initializr page, you need to add the following Maven dependencies to your pom.xml:
<dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> <version>1.16.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.16.1</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.16.1</version> </dependency> <dependency> <groupId>org.lognet</groupId> <artifactId>grpc-spring-boot-starter</artifactId> <version>0.0.6</version> <exclusions> <exclusion> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> </exclusion> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </exclusion> </exclusions> </dependency>
Apart from the native gRPC libraries, we’ll add a Spring Boot starter that will run the embedded gRPC server with @GRpcService. You can check out its code here.
To use the gRPC starter for Spring Boot, we’ll add the following repository:
<repositories> <repository> <snapshots> <enabled>false</enabled> </snapshots> <id>bintray-lognet-maven</id> <name>bintray</name> <url>http://dl.bintray.com/lognet/maven</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <snapshots> <enabled>false</enabled> </snapshots> <id>bintray-lognet-maven</id> <name>bintray-plugins</name> <url>http://dl.bintray.com/lognet/maven</url> </pluginRepository> </pluginRepositories>
Define the service
First, we define a service that specifies the methods that can be called. This involves creating a .proto file that also specifies the message body.
Let’s create a service in our .proto file:
syntax = "proto3"; option java_multiple_files = true; package com.refactorizando.grpc.server.example; enum BookType { BOOK = 0; NEWS_PAPER = 1; COMIC_BOOK = 2; } message Book { string ISBN = 1; string title = 2; string author = 3; int32 page = 4; repeated string keyword = 5; BookType bookType = 6; } message BookList { repeated Book book = 1; } service BookService { rpc createBooks(BookList) returns (BookList); }
We compile this file and converted into Java classes. The above .proto file will generate the classes Book, BookList, and BookType.
Creating the Server-Side
Service
Next, we’ll create a service using the @GRpcService annotation. This class extends BookServiceGrpc.BookServiceImplBase, which is automatically generated along with the classes Book, BookList, and BookType. In this service, we’ll create a list of books and return it as a response:
@GRpcService @Slf4j public class BookGrpcService extends BookServiceGrpc.BookServiceImplBase { @Override public void createBooks(BookList request, StreamObserver<BookList> responseObserver) { log.debug("Request " + request); BookList.Builder responseBuilder = BookList.newBuilder(); BookUtil.assignISBN(request.getBookList()).forEach(responseBuilder::addBook); BookList bookListResponse = responseBuilder.build(); log.debug("Response " + bookListResponse); responseObserver.onNext(bookListResponse); responseObserver.onCompleted(); } }
Controller
The controller will be a basic Spring controller with a POST and a GET method. The POST method is used to add books, and the GET method is used to retrieve them.
Creating the Client-Side
In this section, we’ll create the client service that will make requests to the server-side using the endpoint exposed in the server’s controller. We’ll compile the same .proto file as before and create the following service:
@Service @Slf4j public class BookServiceGrpcClient { public BookList createBooks(List<Book> bookList) { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 6565) .loadBalancerFactory(RoundRobinLoadBalancerFactory.getInstance()) .usePlaintext(true) .build(); BookServiceGrpc.BookServiceBlockingStub bookServiceBlockingStub = BookServiceGrpc.newBlockingStub(channel); BookList.Builder builder = BookList.newBuilder(); bookList.forEach(builder::addBook); BookList request = builder.build(); logger.debug("Request " + request); BookList response = bookServiceBlockingStub.createBooks(request); logger.debug("Response " + response); return response; } }
In this class, we use the ManagedChannel object to communicate with the server.
Conclusion
The best way to understand how gRPC works is through an example with Spring Boot, which you can find here.
If you need more information, you can leave us a comment or send an email to refactorizando.web@gmail.com You can also contact us through our social media channels on Facebook or twitter and we will be happy to assist you!!