LoginSignup
7
1

More than 3 years have passed since last update.

KotlinでgRPCを使ったときのことをまとめてみた

Last updated at Posted at 2020-12-01

この記事は MicroAd Advent Calendar 2020 の1日目の記事です。

(余談ですが、qiita初投稿です。)

はじめに

とある案件で、gRPCを使うことになりました。

「◯◯◯APIを画面から呼び出して情報を取得して画面に表示する」的な話の流れだったので、何も知らなかった僕はHTTP的なものをイメージしていました。

ところが、色々と調べていくうちに、全然違うもので、実装方法もまるで別物ということが分かり、こりゃヤバイ、ということで色々調べつつ実装していた記憶があります。

この記事では、その時に得た知見などを書いて行きたいと思います。

※主にgRPCを呼び出すクライアント側の実装のお話です。

gRPC とは

他の記事によくまとまっていたので引用させていただきます。

gRPCはGoogle謹製のHTTP/2を利用したRPCフレームワークです。
Protocol Buffersを利用し、データをシリアライズして高速なRPCを実現します。

protoファイルと呼ばれるIDL(Interface Definition Language)にAPI仕様を記述します。
また、IDLからサーバーサイドとクライアントサイドの雛形コードを自動生成できます。
自動生成コードは多言語対応で、サーバーサイドとクライアンサイドが異なる言語でも問題ありません。

RPCはRemote Procedure Callの略です。
バラしてみるとこんな感じです。

Remote = リモートサーバの。
Procedure = 手続き(メソッド)を。
Call = 呼び出す(実行する)。

つまり、「ローカルのメソッドを実行するのと同じような感覚でリモートサーバのメソッドを実行」できます。
gRPC以外にもJSON-RPCなどが有名です。
REST-APIのようにパスやメソッドなどを指定する必要がありません。単に関数と引数を指定するだけです。
REST-APIの替わりとして注目を集めています。

引用:https://qiita.com/gold-kou/items/a1cc2be6045723e242eb

gRPCを使うには

大まかにまとめると以下の4点です

  • インターフェースが定義されたprotoファイルを作る
  • protoファイルからコードを自動生成するための設定を追加する
  • コードを自動生成する
    • ビルドすると自動生成される(コードの自動生成だけすることもできる)
    • target/generated-sources/protobuf/ の下に生成されたコードができる
    • コンパイル時に、この場所も見てくれるらしい
  • 自動生成されたコードに記載されているメソッドを呼び出す
    • 他に必要な情報としては、呼び出し先サーバのhost、port
    • プロキシを経由したい場合、若干工夫が必要

インターフェースが定義されたprotoファイルを作る

src/main/proto/xxx_yyy_zzz.proto
syntax = "proto3";
import "google/protobuf/timestamp.proto";

package jp.aaa.bbb.ccc;

message HugaHugaRequest {
  int32 hugaHugaParam = 1;
}

message HugaHugaReply {
  string hugaHugaReturn = 1;
}

service HogeHogeService {
  rpc HugaHugaMethod (HugaHugaRequest) returns (HugaHugaReply) {}
}

protoファイルからコードを自動生成するための設定を追加する

pom.xmlに追加した設定を記載します。(ほぼ公式サンプルのとおりです)
※gradleはやっていませんのでご了承ください。

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <properties>
        <grpc.version>1.31.0</grpc.version>
        <protobuf.version>3.12.4</protobuf.version>
        <protoc.version>3.12.4</protoc.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- https://github.com/grpc/grpc-java -->
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-bom</artifactId>
                <version>${grpc.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- https://github.com/grpc/grpc-java -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java-util</artifactId>
            <version>${protobuf.version}</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
        </dependency>
    </dependencies>

    <build>
        <!-- protocコマンドのダウンロードに必要 -->
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>

        <plugins>
            <!-- protoファイルからコードを自動生成するための設定 -->
            <!-- target/generated-sources/protobuf/ 以下にコードが生成される -->
            <!-- https://github.com/grpc/grpc-java -->
            <!-- https://www.xolstice.org/protobuf-maven-plugin/ -->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

コードを自動生成する

プロジェクト全体をビルドすればコードが自動生成されます。
下記の2つのコマンドを実行することでも、コードを自動生成できます。

自動生成コマンド.txt
mvn protobuf:compile
mvn protobuf:compile-custom

自動生成コード① jp/aaa/bbb/ccc/HogeHogeServiceGrpc.java(289行)
target/generated-sources/protobuf/grpc-java/jp/aaa/bbb/ccc/HogeHogeServiceGrpc.java
package jp.aaa.bbb.ccc;

import static io.grpc.MethodDescriptor.generateFullMethodName;
import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall;
import static io.grpc.stub.ClientCalls.asyncClientStreamingCall;
import static io.grpc.stub.ClientCalls.asyncServerStreamingCall;
import static io.grpc.stub.ClientCalls.asyncUnaryCall;
import static io.grpc.stub.ClientCalls.blockingServerStreamingCall;
import static io.grpc.stub.ClientCalls.blockingUnaryCall;
import static io.grpc.stub.ClientCalls.futureUnaryCall;
import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
import static io.grpc.stub.ServerCalls.asyncUnaryCall;
import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;

/**
 */
@javax.annotation.Generated(
    value = "by gRPC proto compiler (version 1.31.0)",
    comments = "Source: xxx_yyy_zzz.proto")
public final class HogeHogeServiceGrpc {

  private HogeHogeServiceGrpc() {}

  public static final String SERVICE_NAME = "jp.aaa.bbb.ccc.HogeHogeService";

  // Static method descriptors that strictly reflect the proto.
  private static volatile io.grpc.MethodDescriptor<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest,
      jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply> getHugaHugaMethodMethod;

  @io.grpc.stub.annotations.RpcMethod(
      fullMethodName = SERVICE_NAME + '/' + "HugaHugaMethod",
      requestType = jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.class,
      responseType = jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.class,
      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
  public static io.grpc.MethodDescriptor<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest,
      jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply> getHugaHugaMethodMethod() {
    io.grpc.MethodDescriptor<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest, jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply> getHugaHugaMethodMethod;
    if ((getHugaHugaMethodMethod = HogeHogeServiceGrpc.getHugaHugaMethodMethod) == null) {
      synchronized (HogeHogeServiceGrpc.class) {
        if ((getHugaHugaMethodMethod = HogeHogeServiceGrpc.getHugaHugaMethodMethod) == null) {
          HogeHogeServiceGrpc.getHugaHugaMethodMethod = getHugaHugaMethodMethod =
              io.grpc.MethodDescriptor.<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest, jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply>newBuilder()
              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "HugaHugaMethod"))
              .setSampledToLocalTracing(true)
              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                  jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.getDefaultInstance()))
              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
                  jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.getDefaultInstance()))
              .setSchemaDescriptor(new HogeHogeServiceMethodDescriptorSupplier("HugaHugaMethod"))
              .build();
        }
      }
    }
    return getHugaHugaMethodMethod;
  }

  /**
   * Creates a new async stub that supports all call types for the service
   */
  public static HogeHogeServiceStub newStub(io.grpc.Channel channel) {
    io.grpc.stub.AbstractStub.StubFactory<HogeHogeServiceStub> factory =
      new io.grpc.stub.AbstractStub.StubFactory<HogeHogeServiceStub>() {
        @java.lang.Override
        public HogeHogeServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
          return new HogeHogeServiceStub(channel, callOptions);
        }
      };
    return HogeHogeServiceStub.newStub(factory, channel);
  }

  /**
   * Creates a new blocking-style stub that supports unary and streaming output calls on the service
   */
  public static HogeHogeServiceBlockingStub newBlockingStub(
      io.grpc.Channel channel) {
    io.grpc.stub.AbstractStub.StubFactory<HogeHogeServiceBlockingStub> factory =
      new io.grpc.stub.AbstractStub.StubFactory<HogeHogeServiceBlockingStub>() {
        @java.lang.Override
        public HogeHogeServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
          return new HogeHogeServiceBlockingStub(channel, callOptions);
        }
      };
    return HogeHogeServiceBlockingStub.newStub(factory, channel);
  }

  /**
   * Creates a new ListenableFuture-style stub that supports unary calls on the service
   */
  public static HogeHogeServiceFutureStub newFutureStub(
      io.grpc.Channel channel) {
    io.grpc.stub.AbstractStub.StubFactory<HogeHogeServiceFutureStub> factory =
      new io.grpc.stub.AbstractStub.StubFactory<HogeHogeServiceFutureStub>() {
        @java.lang.Override
        public HogeHogeServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
          return new HogeHogeServiceFutureStub(channel, callOptions);
        }
      };
    return HogeHogeServiceFutureStub.newStub(factory, channel);
  }

  /**
   */
  public static abstract class HogeHogeServiceImplBase implements io.grpc.BindableService {

    /**
     */
    public void hugaHugaMethod(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest request,
        io.grpc.stub.StreamObserver<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply> responseObserver) {
      asyncUnimplementedUnaryCall(getHugaHugaMethodMethod(), responseObserver);
    }

    @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
      return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
          .addMethod(
            getHugaHugaMethodMethod(),
            asyncUnaryCall(
              new MethodHandlers<
                jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest,
                jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply>(
                  this, METHODID_HUGA_HUGA_METHOD)))
          .build();
    }
  }

  /**
   */
  public static final class HogeHogeServiceStub extends io.grpc.stub.AbstractAsyncStub<HogeHogeServiceStub> {
    private HogeHogeServiceStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected HogeHogeServiceStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new HogeHogeServiceStub(channel, callOptions);
    }

    /**
     */
    public void hugaHugaMethod(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest request,
        io.grpc.stub.StreamObserver<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply> responseObserver) {
      asyncUnaryCall(
          getChannel().newCall(getHugaHugaMethodMethod(), getCallOptions()), request, responseObserver);
    }
  }

  /**
   */
  public static final class HogeHogeServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub<HogeHogeServiceBlockingStub> {
    private HogeHogeServiceBlockingStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected HogeHogeServiceBlockingStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new HogeHogeServiceBlockingStub(channel, callOptions);
    }

    /**
     */
    public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply hugaHugaMethod(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest request) {
      return blockingUnaryCall(
          getChannel(), getHugaHugaMethodMethod(), getCallOptions(), request);
    }
  }

  /**
   */
  public static final class HogeHogeServiceFutureStub extends io.grpc.stub.AbstractFutureStub<HogeHogeServiceFutureStub> {
    private HogeHogeServiceFutureStub(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      super(channel, callOptions);
    }

    @java.lang.Override
    protected HogeHogeServiceFutureStub build(
        io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
      return new HogeHogeServiceFutureStub(channel, callOptions);
    }

    /**
     */
    public com.google.common.util.concurrent.ListenableFuture<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply> hugaHugaMethod(
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest request) {
      return futureUnaryCall(
          getChannel().newCall(getHugaHugaMethodMethod(), getCallOptions()), request);
    }
  }

  private static final int METHODID_HUGA_HUGA_METHOD = 0;

  private static final class MethodHandlers<Req, Resp> implements
      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
    private final HogeHogeServiceImplBase serviceImpl;
    private final int methodId;

    MethodHandlers(HogeHogeServiceImplBase serviceImpl, int methodId) {
      this.serviceImpl = serviceImpl;
      this.methodId = methodId;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("unchecked")
    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
      switch (methodId) {
        case METHODID_HUGA_HUGA_METHOD:
          serviceImpl.hugaHugaMethod((jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest) request,
              (io.grpc.stub.StreamObserver<jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply>) responseObserver);
          break;
        default:
          throw new AssertionError();
      }
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("unchecked")
    public io.grpc.stub.StreamObserver<Req> invoke(
        io.grpc.stub.StreamObserver<Resp> responseObserver) {
      switch (methodId) {
        default:
          throw new AssertionError();
      }
    }
  }

  private static abstract class HogeHogeServiceBaseDescriptorSupplier
      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
    HogeHogeServiceBaseDescriptorSupplier() {}

    @java.lang.Override
    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
      return jp.aaa.bbb.ccc.XxxYyyZzz.getDescriptor();
    }

    @java.lang.Override
    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
      return getFileDescriptor().findServiceByName("HogeHogeService");
    }
  }

  private static final class HogeHogeServiceFileDescriptorSupplier
      extends HogeHogeServiceBaseDescriptorSupplier {
    HogeHogeServiceFileDescriptorSupplier() {}
  }

  private static final class HogeHogeServiceMethodDescriptorSupplier
      extends HogeHogeServiceBaseDescriptorSupplier
      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
    private final String methodName;

    HogeHogeServiceMethodDescriptorSupplier(String methodName) {
      this.methodName = methodName;
    }

    @java.lang.Override
    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
      return getServiceDescriptor().findMethodByName(methodName);
    }
  }

  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;

  public static io.grpc.ServiceDescriptor getServiceDescriptor() {
    io.grpc.ServiceDescriptor result = serviceDescriptor;
    if (result == null) {
      synchronized (HogeHogeServiceGrpc.class) {
        result = serviceDescriptor;
        if (result == null) {
          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
              .setSchemaDescriptor(new HogeHogeServiceFileDescriptorSupplier())
              .addMethod(getHugaHugaMethodMethod())
              .build();
        }
      }
    }
    return result;
  }
}

自動生成コード② jp/aaa/bbb/ccc/XxxYyyZzz.java(1122行)
target/generated-sources/protobuf/java/jp/aaa/bbb/ccc/XxxYyyZzz.java
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: xxx_yyy_zzz.proto

package jp.aaa.bbb.ccc;

public final class XxxYyyZzz {
  private XxxYyyZzz() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  public interface HugaHugaRequestOrBuilder extends
      // @@protoc_insertion_point(interface_extends:jp.aaa.bbb.ccc.HugaHugaRequest)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>int32 hugaHugaParam = 1;</code>
     * @return The hugaHugaParam.
     */
    int getHugaHugaParam();
  }
  /**
   * Protobuf type {@code jp.aaa.bbb.ccc.HugaHugaRequest}
   */
  public static final class HugaHugaRequest extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:jp.aaa.bbb.ccc.HugaHugaRequest)
      HugaHugaRequestOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use HugaHugaRequest.newBuilder() to construct.
    private HugaHugaRequest(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private HugaHugaRequest() {
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new HugaHugaRequest();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    private HugaHugaRequest(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      this();
      if (extensionRegistry == null) {
        throw new java.lang.NullPointerException();
      }
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            case 8: {

              hugaHugaParam_ = input.readInt32();
              break;
            }
            default: {
              if (!parseUnknownField(
                  input, unknownFields, extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.class, jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.Builder.class);
    }

    public static final int HUGAHUGAPARAM_FIELD_NUMBER = 1;
    private int hugaHugaParam_;
    /**
     * <code>int32 hugaHugaParam = 1;</code>
     * @return The hugaHugaParam.
     */
    @java.lang.Override
    public int getHugaHugaParam() {
      return hugaHugaParam_;
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (hugaHugaParam_ != 0) {
        output.writeInt32(1, hugaHugaParam_);
      }
      unknownFields.writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (hugaHugaParam_ != 0) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(1, hugaHugaParam_);
      }
      size += unknownFields.getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest)) {
        return super.equals(obj);
      }
      jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest other = (jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest) obj;

      if (getHugaHugaParam()
          != other.getHugaHugaParam()) return false;
      if (!unknownFields.equals(other.unknownFields)) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      hash = (37 * hash) + HUGAHUGAPARAM_FIELD_NUMBER;
      hash = (53 * hash) + getHugaHugaParam();
      hash = (29 * hash) + unknownFields.hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code jp.aaa.bbb.ccc.HugaHugaRequest}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:jp.aaa.bbb.ccc.HugaHugaRequest)
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequestOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.class, jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.Builder.class);
      }

      // Construct using jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        hugaHugaParam_ = 0;

        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_descriptor;
      }

      @java.lang.Override
      public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest getDefaultInstanceForType() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.getDefaultInstance();
      }

      @java.lang.Override
      public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest build() {
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest buildPartial() {
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest result = new jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest(this);
        result.hugaHugaParam_ = hugaHugaParam_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest) {
          return mergeFrom((jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest other) {
        if (other == jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest.getDefaultInstance()) return this;
        if (other.getHugaHugaParam() != 0) {
          setHugaHugaParam(other.getHugaHugaParam());
        }
        this.mergeUnknownFields(other.unknownFields);
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest) e.getUnfinishedMessage();
          throw e.unwrapIOException();
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }

      private int hugaHugaParam_ ;
      /**
       * <code>int32 hugaHugaParam = 1;</code>
       * @return The hugaHugaParam.
       */
      @java.lang.Override
      public int getHugaHugaParam() {
        return hugaHugaParam_;
      }
      /**
       * <code>int32 hugaHugaParam = 1;</code>
       * @param value The hugaHugaParam to set.
       * @return This builder for chaining.
       */
      public Builder setHugaHugaParam(int value) {

        hugaHugaParam_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>int32 hugaHugaParam = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearHugaHugaParam() {

        hugaHugaParam_ = 0;
        onChanged();
        return this;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:jp.aaa.bbb.ccc.HugaHugaRequest)
    }

    // @@protoc_insertion_point(class_scope:jp.aaa.bbb.ccc.HugaHugaRequest)
    private static final jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest();
    }

    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    private static final com.google.protobuf.Parser<HugaHugaRequest>
        PARSER = new com.google.protobuf.AbstractParser<HugaHugaRequest>() {
      @java.lang.Override
      public HugaHugaRequest parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new HugaHugaRequest(input, extensionRegistry);
      }
    };

    public static com.google.protobuf.Parser<HugaHugaRequest> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<HugaHugaRequest> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaRequest getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  public interface HugaHugaReplyOrBuilder extends
      // @@protoc_insertion_point(interface_extends:jp.aaa.bbb.ccc.HugaHugaReply)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>string hugaHugaReturn = 1;</code>
     * @return The hugaHugaReturn.
     */
    java.lang.String getHugaHugaReturn();
    /**
     * <code>string hugaHugaReturn = 1;</code>
     * @return The bytes for hugaHugaReturn.
     */
    com.google.protobuf.ByteString
        getHugaHugaReturnBytes();
  }
  /**
   * Protobuf type {@code jp.aaa.bbb.ccc.HugaHugaReply}
   */
  public static final class HugaHugaReply extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:jp.aaa.bbb.ccc.HugaHugaReply)
      HugaHugaReplyOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use HugaHugaReply.newBuilder() to construct.
    private HugaHugaReply(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private HugaHugaReply() {
      hugaHugaReturn_ = "";
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new HugaHugaReply();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    private HugaHugaReply(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      this();
      if (extensionRegistry == null) {
        throw new java.lang.NullPointerException();
      }
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            case 10: {
              java.lang.String s = input.readStringRequireUtf8();

              hugaHugaReturn_ = s;
              break;
            }
            default: {
              if (!parseUnknownField(
                  input, unknownFields, extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaReply_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaReply_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.class, jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.Builder.class);
    }

    public static final int HUGAHUGARETURN_FIELD_NUMBER = 1;
    private volatile java.lang.Object hugaHugaReturn_;
    /**
     * <code>string hugaHugaReturn = 1;</code>
     * @return The hugaHugaReturn.
     */
    @java.lang.Override
    public java.lang.String getHugaHugaReturn() {
      java.lang.Object ref = hugaHugaReturn_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        hugaHugaReturn_ = s;
        return s;
      }
    }
    /**
     * <code>string hugaHugaReturn = 1;</code>
     * @return The bytes for hugaHugaReturn.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString
        getHugaHugaReturnBytes() {
      java.lang.Object ref = hugaHugaReturn_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        hugaHugaReturn_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (!getHugaHugaReturnBytes().isEmpty()) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, hugaHugaReturn_);
      }
      unknownFields.writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (!getHugaHugaReturnBytes().isEmpty()) {
        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, hugaHugaReturn_);
      }
      size += unknownFields.getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply)) {
        return super.equals(obj);
      }
      jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply other = (jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply) obj;

      if (!getHugaHugaReturn()
          .equals(other.getHugaHugaReturn())) return false;
      if (!unknownFields.equals(other.unknownFields)) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      hash = (37 * hash) + HUGAHUGARETURN_FIELD_NUMBER;
      hash = (53 * hash) + getHugaHugaReturn().hashCode();
      hash = (29 * hash) + unknownFields.hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code jp.aaa.bbb.ccc.HugaHugaReply}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:jp.aaa.bbb.ccc.HugaHugaReply)
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReplyOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaReply_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaReply_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.class, jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.Builder.class);
      }

      // Construct using jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        hugaHugaReturn_ = "";

        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.internal_static_jp_aaa_bbb_ccc_HugaHugaReply_descriptor;
      }

      @java.lang.Override
      public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply getDefaultInstanceForType() {
        return jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.getDefaultInstance();
      }

      @java.lang.Override
      public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply build() {
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply buildPartial() {
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply result = new jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply(this);
        result.hugaHugaReturn_ = hugaHugaReturn_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply) {
          return mergeFrom((jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply other) {
        if (other == jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply.getDefaultInstance()) return this;
        if (!other.getHugaHugaReturn().isEmpty()) {
          hugaHugaReturn_ = other.hugaHugaReturn_;
          onChanged();
        }
        this.mergeUnknownFields(other.unknownFields);
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply) e.getUnfinishedMessage();
          throw e.unwrapIOException();
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }

      private java.lang.Object hugaHugaReturn_ = "";
      /**
       * <code>string hugaHugaReturn = 1;</code>
       * @return The hugaHugaReturn.
       */
      public java.lang.String getHugaHugaReturn() {
        java.lang.Object ref = hugaHugaReturn_;
        if (!(ref instanceof java.lang.String)) {
          com.google.protobuf.ByteString bs =
              (com.google.protobuf.ByteString) ref;
          java.lang.String s = bs.toStringUtf8();
          hugaHugaReturn_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>string hugaHugaReturn = 1;</code>
       * @return The bytes for hugaHugaReturn.
       */
      public com.google.protobuf.ByteString
          getHugaHugaReturnBytes() {
        java.lang.Object ref = hugaHugaReturn_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          hugaHugaReturn_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>string hugaHugaReturn = 1;</code>
       * @param value The hugaHugaReturn to set.
       * @return This builder for chaining.
       */
      public Builder setHugaHugaReturn(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }

        hugaHugaReturn_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>string hugaHugaReturn = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearHugaHugaReturn() {

        hugaHugaReturn_ = getDefaultInstance().getHugaHugaReturn();
        onChanged();
        return this;
      }
      /**
       * <code>string hugaHugaReturn = 1;</code>
       * @param value The bytes for hugaHugaReturn to set.
       * @return This builder for chaining.
       */
      public Builder setHugaHugaReturnBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  checkByteStringIsUtf8(value);

        hugaHugaReturn_ = value;
        onChanged();
        return this;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:jp.aaa.bbb.ccc.HugaHugaReply)
    }

    // @@protoc_insertion_point(class_scope:jp.aaa.bbb.ccc.HugaHugaReply)
    private static final jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply();
    }

    public static jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    private static final com.google.protobuf.Parser<HugaHugaReply>
        PARSER = new com.google.protobuf.AbstractParser<HugaHugaReply>() {
      @java.lang.Override
      public HugaHugaReply parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new HugaHugaReply(input, extensionRegistry);
      }
    };

    public static com.google.protobuf.Parser<HugaHugaReply> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<HugaHugaReply> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public jp.aaa.bbb.ccc.XxxYyyZzz.HugaHugaReply getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_jp_aaa_bbb_ccc_HugaHugaReply_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_jp_aaa_bbb_ccc_HugaHugaReply_fieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor
      getDescriptor() {
    return descriptor;
  }
  private static  com.google.protobuf.Descriptors.FileDescriptor
      descriptor;
  static {
    java.lang.String[] descriptorData = {
      "\n\021xxx_yyy_zzz.proto\022\016jp.aaa.bbb.ccc\032\037goo" +
      "gle/protobuf/timestamp.proto\"(\n\017HugaHuga" +
      "Request\022\025\n\rhugaHugaParam\030\001 \001(\005\"\'\n\rHugaHu" +
      "gaReply\022\026\n\016hugaHugaReturn\030\001 \001(\t2e\n\017HogeH" +
      "ogeService\022R\n\016HugaHugaMethod\022\037.jp.aaa.bb" +
      "b.ccc.HugaHugaRequest\032\035.jp.aaa.bbb.ccc.H" +
      "ugaHugaReply\"\000b\006proto3"
    };
    descriptor = com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
          com.google.protobuf.TimestampProto.getDescriptor(),
        });
    internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_descriptor =
      getDescriptor().getMessageTypes().get(0);
    internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_jp_aaa_bbb_ccc_HugaHugaRequest_descriptor,
        new java.lang.String[] { "HugaHugaParam", });
    internal_static_jp_aaa_bbb_ccc_HugaHugaReply_descriptor =
      getDescriptor().getMessageTypes().get(1);
    internal_static_jp_aaa_bbb_ccc_HugaHugaReply_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_jp_aaa_bbb_ccc_HugaHugaReply_descriptor,
        new java.lang.String[] { "HugaHugaReturn", });
    com.google.protobuf.TimestampProto.getDescriptor();
  }

  // @@protoc_insertion_point(outer_class_scope)
}

自動生成されたコードは、ボリュームが大きいので、どのようにコード管理するかは要検討かと思います。

  • git管理する
  • git管理せず、protoファイルからコード生成する形でやっていく
  • 自動生成されたコードをjarファイルにまとめて、そのjarファイルを依存に加える

など。

この記事用に、限りなくシンプルな定義ファイルにしたつもりなのですが、それでも1000行超えました。
実際の案件では10000行を超えてきます。

ちなみに自動生成コードのファイル名とパッケージですが、下記のようになっているようです。

  • 自動生成コードのパッケージ:protoファイルに記載されているpackage
  • 自動生成コード①のファイル名:protoファイルに記載されているservice + Grpc
  • 自動生成コード②のファイル名:protoファイルのファイル名をキャメルケースにしたもの(xxx_yyy_zzz.proto)

自動生成されたコードに記載されているメソッドを呼び出す

  • Stubインスタンスを生成(下記の例では、シングルトンオブジェクトにしています。)
  • 生成したStubから、メソッドを呼び出す

※パッケージやimportはだいぶ省略させて頂いております。

Stubインスタンスを生成
HogeHogeApiConfiguration.kt
import jp.aaa.bbb.ccc.HogeHogeServiceGrpc

/*
 * APIの接続設定
 * VPNプロキシ設定はリモート環境で社内のサーバーと通信する場合のみ必要
 */
@Component
class HogeHogeApiConfiguration(
        private val proxyHost: String = "proxyhost",
        private val proxyPort: Int = 8888,
        private val timeout: Int = 5000,
        private val hogeHogeApiHost: String = "hogehogehost",
        private val hogeHogeApiPort: Int = 9999
) {
    @Bean(name = ["HogeHogeApiStub"])
    fun createHogeHogeApiStub(): HogeHogeServiceGrpc.HogeHogeServiceBlockingStub {
        val isReachable = InetAddress.getByName(hogeHogeApiHost).isReachable(timeout)
        val channel = ManagedChannelBuilder
                .forAddress(hogeHogeApiHost, hogeHogeApiPort)
                .usePlaintext()
                .apply { if (!isReachable) proxyDetector(createProxyDetector()) }
                .build()
        return HogeHogeServiceGrpc.newBlockingStub(channel)
    }

    private fun createProxyDetector(): ProxyDetector {
        return ProxyDetector { targetServerAddress ->
            HttpConnectProxiedSocketAddress.newBuilder()
                    .setTargetAddress(targetServerAddress as InetSocketAddress)
                    .setProxyAddress(InetSocketAddress(proxyHost, proxyPort))
                    .build()
        }
    }
}
生成したStubから、メソッドを呼び出す
HogeHogeDaoImpl.kt
import jp.aaa.bbb.ccc.HogeHogeServiceGrpc
import jp.aaa.bbb.ccc.XxxYyyZzz

@Component
internal class HogeHogeDaoImpl(
        @Qualifier("HogeHogeApiStub")
        private val apiStub: HogeHogeServiceGrpc.HogeHogeServiceBlockingStub
) : HogeHogeDao {
    override fun callHugaHugaMethod(): String {
        // Request
        val request: XxxYyyZzz.HugaHugaRequest =
                XxxYyyZzz.HugaHugaRequest.newBuilder().setHugaHugaParam(99).build()

        // call hugaHugaMethod()
        val reply: XxxYyyZzz.HugaHugaReply = apiStub.hugaHugaMethod(request)

        return reply.hugaHugaReturn
    }
}

終わりに

昨今のコロナ事情で、リモートワーク環境でgRPCを使えるようにする件がほぼ必須となり、createProxyDetector の部分を頑張って実装していたのが良い思い出です。

全体的に、Kotlinの師匠であるM氏にはレビューなどで大変お世話になりました。

この記事が様々な人の役に立てば幸いです。

7
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1