Update your Java knowledge by writing a gRPC server in Java (1)

I decided to do Java again, so I decided to write a gRPC server to update my knowledge of Java.

This article is wonderful, so I'm just streaming it, but since a lot of yak hair is being cut, I would like to include it.

Template when writing a console application with maven

The first thing I got stuck in was to create a very simple Hello World level console application with maven. Simply use maven-archetype-quickstart.

mvn archetype:generate 
  -DgroupId=com.simplearchitect \
  -DartifactId=helloGRPC \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DinteractiveMode=false

proto file

Exactly Hello World level protobuf. Syntax must be set to proto3 or the old version will be used. java_package determines the package of the automatically generated class, so it might have been better to give it a more serious name. ʻOuter_classname` is the name of the auto-generated class that represents the concept of the protocol.

The protocol buffer below has a method called SayHello and defines a simple service that returns HelloReply when you send a HelloRequest.

main/proto/helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

Read this to get a better understanding of the proto file.

Automatic class generation

It is necessary to automatically generate a class based on the proto file. This requires maven to be set to dependency and plugin. Look at the top page of gRPC-Java --An RPC library and framework and set maven.

You need to add ʻio.grpcfamily libraries and includeprotobuf-maven-plugin and ʻos-maven-plugin. By the way, ʻos-maven-plugin` is

os-maven-plugin is a Maven extension/plugin that generates various useful platform-dependent project properties normalized from ${os.name} and ${os.arch}.

And that. os-maven-plugin.

<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-netty-shaded</artifactId>
  <version>1.31.1</version>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-protobuf</artifactId>
  <version>1.31.1</version>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-stub</artifactId>
  <version>1.31.1</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
  <groupId>org.apache.tomcat</groupId>
  <artifactId>annotations-api</artifactId>
  <version>6.0.53</version>
  <scope>provided</scope>
</dependency>
  :
<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.6.2</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.12.0:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.31.1:exe:${os.detected.classifier}</pluginArtifact>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>compile-custom</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

With this setting, mvn clean package will automatically generate a class. image.png

By the way, when creating a project in IntelliJ, it seems better to generate target once and then execute it. If you leave the default, the target directory will disappear. After creating target, load the project into intelliJ and it will be set automatically. If not, you need to set the following settings File> Project Structure Module.

image.png

When loading into IntelliJ, if you do not right-click the project and select an additional Maven project, even if there is no error in maven, the dependency on the screen cannot be resolved and an error occurs. It ends up.

Write a gRPC server

Write a server with reference to the generated class. Allows this to be done from the Main program. All you have to do is start the server, configure it, and set the inherited classes.

package com.simplearchitect;

import java.io.IOException;
import java.util.logging.Logger;

import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.GreeterGrpc.GreeterImplBase;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.CallStreamObserver;

import static io.grpc.ServerBuilder.*;

public class SimpleServer {
    Logger logger = Logger.getLogger(getClass().getName());

    Server server;

    public void start() throws IOException {
        server = ServerBuilder
                .forPort(8080)
                .addService((BindableService) new SimpleHelloServiceImpl())
                .build()
                .start();
        logger.info("start gRPC server.");
    }

    public void stop() {
        if (server != null) {
            server.shutdown();
            logger.info("Shutting down gRPC server.");
        }
    }

    public void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

    public static class SimpleHelloServiceImpl extends GreeterImplBase {
        Logger logger = Logger.getLogger(getClass().getName());

        public void sayHello(HelloRequest request, CallStreamObserver<HelloReply> responseObserver) {
            logger.info(String.format("request: name = %s", request.getName()));
            HelloReply reply = HelloReply.newBuilder().setMessage("Hello, " + request.getName()).build();
            responseObserver.onNext(reply);
            responseObserver.onCompleted();
        }
    }
}

abstract static class Curiously, I have a new static class. What does this mean? The following class is the inheritance source class, but it is static abstract class. This is actually not a static class, but this class is an inner class and is marked with static to indicate that it can be instantiated without instantiating the parent class of the inner class. So, in reality, it is a class that can be instantiated.

public static abstract class GreeterImplBase implements io.grpc.BindableService {

    /**
     * <pre>
     * Sends a greeting
     * </pre>
     */
    public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
        io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver) {
      asyncUnimplementedUnaryCall(getSayHelloMethod(), responseObserver);
    }

    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
      return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
          .addMethod(
            getSayHelloMethod(),
            asyncUnaryCall(
              new MethodHandlers<
                io.grpc.examples.helloworld.HelloRequest,
                io.grpc.examples.helloworld.HelloReply>(
                  this, METHODID_SAY_HELLO)))
          .build();
    }
  }

Adding Dependency to Java

Creating a jar file with mvn clean package and executing it will result in an error. This is because Jar does not include the library. Let's add maven-assembly-plugin. Now you can also specify mainClass and it will create a library with the dependent jars. `

      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.1.0</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.simplearchitect.App</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>sample</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

The Assembly Plugin for Maven enables developers to combine project output into a single distributable archive that also contains dependencies, modules, site documentation, and other files.

Umm. Exactly what you were looking for.

Run

PS > > java -jar .\target\helloGRPC-1.0-SNAPSHOT-jar-with-dependencies.jar
Aug 16, 2020 11:17:33 PM com.simplearchitect.SimpleServer start
INFO: start gRPC server.
> Enter stop.

I wonder if it works, but first of all, it was compiled, a jar with a library was created, and it worked. Next time, I will try to make a client and move it. I want to clearly understand the behavior of CallStreamObserver.

Recommended Posts

Update your Java knowledge by writing a gRPC server in Java (2)
Update your Java knowledge by writing a gRPC server in Java (1)
What I learned when building a server in Java
Implementing a large-scale GraphQL server in Java with Netflix DGS
Find a subset in Java
Make your own simple server in Java and understand HTTP
Try implementing GraphQL server in Java
3 Implement a simple interpreter in Java
I created a PDF in Java.
A person writing C ++ tried writing Java
Handle your own annotations in Java
Implement a gRPC client in Ruby
A simple sample callback in Java
Get stuck in a Java primer
[Java] Divide a character string by a specified character
When seeking multiple in a Java array
Duplicate Map sorted by key in Java
Differences in writing in Ruby, PHP, Java, JS
Key points for introducing gRPC in Java
Understand java interface in your own way
[Creating] A memorandum about coding in Java
Java creates a table in a Word document
Java creates a pie chart in Excel
What is a class in Java language (1 /?)
What is a class in Java language (2 /?)
Basic knowledge of Java development Note writing
Create a TODO app in Java 7 Create Header
Try making a calculator app in Java
Continued Talk about writing Java in Emacs @ 2018
Get history from Zabbix server in Java
Implement something like a stack in Java
Split a string with ". (Dot)" in Java
Creating a matrix class in Java Part 1
The story of writing Java in Emacs
Reading and writing gzip files in Java
Create a Docker container for your development web server in Ansible on MacOS
Let's create a versatile file storage (?) Operation library by abstracting file storage / acquisition in Java
Organize your own differences in writing comfort between Java lambda expressions and Kotlin lambda expressions.