google-site-verification: google61fe8ba583a51912.html
Building a gRPC Server and Client in Java

gRPC is a modern, high-performance RPC (Remote Procedure Call) framework that can run in any environment. It uses HTTP/2 for transport, Protocol Buffers as the interface description language, and provides features such as authentication, bidirectional streaming and flow control.

Overview

In this article, we'll create a simple gRPC service in Java that demonstrates:

  • Defining a service using Protocol Buffers
  • Implementing a gRPC server
  • Creating a gRPC client to call the service
  • Basic unary RPC calls

Prerequisites

  • Java 8 or higher
  • Maven or Gradle build tool
  • Protocol Buffers compiler (protoc)

Step 1: Define the Service with Protocol Buffers

First, create a .proto file that defines your service and messages:

syntax = "proto3"; option java_package = "com.example.grpc"; option java_multiple_files = true; service GreetingService { rpc Greet (GreetingRequest) returns (GreetingResponse); } message GreetingRequest { string name = 1; } message GreetingResponse { string greeting = 1; }

Step 2: Project Setup and Dependencies

Add the following dependencies to your pom.xml if using Maven:

<dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty-shaded</artifactId> <version>1.58.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.58.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.58.0</version> </dependency> <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </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.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.58.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>

Step 3: Implement the gRPC Server

Create the server implementation:

package com.example.grpc.server; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; import com.example.grpc.GreetingRequest; import com.example.grpc.GreetingResponse; import com.example.grpc.GreetingServiceGrpc; import java.io.IOException; import java.util.concurrent.TimeUnit; public class GreetingServer { private Server server; private final int port; public GreetingServer(int port) { this.port = port; } public void start() throws IOException { server = ServerBuilder.forPort(port) .addService(new GreetingServiceImpl()) .build() .start(); System.out.println("Server started, listening on " + port); Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.err.println("*** shutting down gRPC server since JVM is shutting down"); try { GreetingServer.this.stop(); } catch (InterruptedException e) { e.printStackTrace(System.err); } System.err.println("*** server shut down"); })); } public void stop() throws InterruptedException { if (server != null) { server.shutdown().awaitTermination(30, TimeUnit.SECONDS); } } public void blockUntilShutdown() throws InterruptedException { if (server != null) { server.awaitTermination(); } } static class GreetingServiceImpl extends GreetingServiceGrpc.GreetingServiceImplBase { @Override public void greet(GreetingRequest request, StreamObserver<GreetingResponse> responseObserver) { String greeting = "Hello, " + request.getName() + "! Welcome to gRPC."; GreetingResponse response = GreetingResponse.newBuilder() .setGreeting(greeting) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } } public static void main(String[] args) throws IOException, InterruptedException { GreetingServer server = new GreetingServer(50051); server.start(); server.blockUntilShutdown(); } }

Step 4: Implement the gRPC Client

Create the client implementation:

package com.example.grpc.client; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import com.example.grpc.GreetingRequest; import com.example.grpc.GreetingResponse; import com.example.grpc.GreetingServiceGrpc; import java.util.concurrent.TimeUnit; public class GreetingClient { private final ManagedChannel channel; private final GreetingServiceGrpc.GreetingServiceBlockingStub blockingStub; public GreetingClient(String host, int port) { this.channel = ManagedChannelBuilder.forAddress(host, port) .usePlaintext() .build(); this.blockingStub = GreetingServiceGrpc.newBlockingStub(channel); } public void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } public void greet(String name) { System.out.println("Sending greeting request for: " + name); GreetingRequest request = GreetingRequest.newBuilder() .setName(name) .build(); GreetingResponse response = blockingStub.greet(request); System.out.println("Received: " + response.getGreeting()); } public static void main(String[] args) throws InterruptedException { GreetingClient client = new GreetingClient("localhost", 50051); try { // Test with different names client.greet("Alice"); client.greet("Bob"); client.greet("Charlie"); } finally { client.shutdown(); } } }

Step 5: Build and Run

  1. Generate Java classes from .proto file:
 mvn compile
  1. Start the server:
 mvn exec:java -Dexec.mainClass="com.example.grpc.server.GreetingServer"
  1. Run the client (in a separate terminal):
 mvn exec:java -Dexec.mainClass="com.example.grpc.client.GreetingClient"

Expected Output

Server output:

Server started, listening on 50051

Client output:

Sending greeting request for: Alice Received: Hello, Alice! Welcome to gRPC. Sending greeting request for: Bob Received: Hello, Bob! Welcome to gRPC. Sending greeting request for: Charlie Received: Hello, Charlie! Welcome to gRPC.

Key gRPC Concepts Demonstrated

  1. Service Definition: Protocol Buffers define the service contract
  2. Server Implementation: Extend the generated base class and implement service methods
  3. Client Stubs: Use generated client stubs to make RPC calls
  4. Communication: HTTP/2 transport with Protocol Buffers serialization
  5. Lifecycle Management: Proper startup and shutdown of gRPC components

Advanced Features

gRPC supports several advanced features you can explore:

  • Streaming RPCs: Client streaming, server streaming, and bidirectional streaming
  • Error Handling: Status codes and error details
  • Deadlines/Timeouts: Setting timeouts for RPC calls
  • Interceptors: For cross-cutting concerns like logging, authentication
  • Load Balancing: Client-side load balancing

This example provides a solid foundation for building more complex gRPC services in Java. The type-safe API, performance benefits, and cross-language support make gRPC an excellent choice for microservices and distributed systems.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper