Windows + Java 7 + Maven 2系
世の中には最新だけじゃダメなこともあるんです。例えばIEとかIEとかIEとか。
そんなわけで、古い環境で頑張って開発しなければならない境遇の方への参考になればと思います。
gRPC自体の説明は他の方が詳しく書いてくれているので探してみて下さい。
ざっと今回の環境。いろいろ古い。
- Windows 10 64bit
- Oracle JDK 1.7.0_75 32bit
- Apache Maven 2.2.1
- Eclipse 4.3.2 Kepler SR2
まずはイマドキのやり方でおさらい
以下を参考にしながら。
https://grpc.io/docs/tutorials/basic/java/
https://github.com/grpc/grpc-java/blob/master/examples/README.md
そんな余裕無いって方はここは読み飛ばしてください。
いつも通りDockerで環境をサクッと作りましょう。
$ docker run --rm -it --name grpc-java -p 50051:50051 ubuntu
root@e7b3b2c13c0b:/# apt-get update
root@e7b3b2c13c0b:/# apt-get install -y git openjdk-8-jdk maven
root@e7b3b2c13c0b:/# git clone -b v1.22.1 https://github.com/grpc/grpc-java
root@e7b3b2c13c0b:/# cd grpc-java/examples
root@e7b3b2c13c0b:/grpc-java/examples# ./gradlew installDist
ちなみにtools.jar
を使うため、jre
じゃダメよ。
jreでやった場合は下記のエラーになります。
> Task :compileJava FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Could not find tools.jar. Please check that /usr/lib/jvm/java-8-openjdk-amd64 contains a valid JDK installation.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 43s
ここまでで環境の準備は出来ています。
HelloWorldのサンプルは以下にあります。
/grpc-java/examples/src/main/proto/helloworld.proto
/grpc-java/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
/grpc-java/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
/grpc-java/examples
配下でビルドして実行してみましょう。
root@e7b3b2c13c0b:~# cd /grpc-java/examples
root@e7b3b2c13c0b:/grpc-java/examples# mvn clean compile
root@e7b3b2c13c0b:/grpc-java/examples# mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldServer &
[1] 5817
root@e7b3b2c13c0b:/grpc-java/examples#
root@e7b3b2c13c0b:/grpc-java/examples# mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldClient
Greeting: Hello world
が表示されれば完了ですね。
今回はサーバーとクライアントを同じ端末で実行しています。
サーバーを終了したいときは下記。(fg
-> Ctrl + C
)
root@e7b3b2c13c0b:/grpc-java/examples# fg
mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldServer
^C*** shutting down gRPC server since JVM is shutting down
*** server shut down
root@e7b3b2c13c0b:/grpc-java/examples#
protoファイルを変更した場合は、./gradlew installDist
を実行すればJavaコードが生成されます。
Javaの実行オプションを変えたい場合は、MAVEN_OPTS
を設定すればOKです。
MAVEN_OPTS="-server -Xmx1024m -Xms1024m -Xloggc:/grpc-java/examples/GC.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xverify:none -Djava.security.egd=file:/dev/./urandom -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:+PrintTenuringDistribution -XX:-Inline"
export MAVEN_OPTS
Windowsの場合
さて、いよいよ本題です。WindowsでDockerもGradleも使用禁止の縛りプレイです。
純粋なgRPCはJava 7以上となっていますが、サンプルではGradleを使うし、Maven3以上が必須(プラグインを使うため)になっています。
まず、Maven プロジェクトを作りましょう。今回必要な依存関係は下記。(ログはお好みで)
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.22.1</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
プロジェクト直下にproto
フォルダを作成し、protoファイルを作成します。
syntax = "proto3";
option java_multiple_files = true;
option java_package = "org.mygrpc.helloworld";
option java_outer_classname = "GrpcProto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
protoファイルからJavaソースを生成します。
protobufのWindows用ファイルをダウンロードします。
https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protoc-3.9.0-win64.zip
解凍し、bin
フォルダ配下にあるprotoc.exe
をパスが通った場所に置きます。新たにどこかに置いてパスを通しても良いです。
今後フルパスで実行するなら、別にパスは通さなくても良いです。
コマンドプロンプトで先ほど作成した、grpc.proto
があるフォルダで下記を実行。
protoc --java_out=..\src\main\java grpc.proto
org.mygrpc.helloworld
配下にソースが生成されました。
.
│ pom.xml
│
├─proto
│ grpc.proto
│
└─src
├─main
│ ├─java
│ │ └─org
│ │ └─mygrpc
│ │ └─helloworld
│ │ GrpcProto.java
│ │ HelloReply.java
│ │ HelloReplyOrBuilder.java
│ │ HelloRequest.java
│ │ HelloRequestOrBuilder.java
│ │
│ └─resources
│ log4j.dtd
│ log4j.xml
│
└─test
├─java
└─resources
実はこれだけでは足りません。もう1つ生成するためにツールをダウンロードします。
https://search.maven.org/search?q=g:io.grpc%20a:protoc-gen-grpc-java
※Downloadのリンクからexeを落とすべし。
ダウンロードしたexeを任意のフォルダに配置し、以下を実行(パスは上記のexeを配置したフォルダに変更してください)
protoc --plugin=protoc-gen-grpc-java=C:\protoc\protoc-gen-grpc-java-1.22.1-windows-x86_64.exe --grpc-java_out=..\src\main\java grpc.proto
GreeterGrpc.java
が作成されたと思います。
サンプルを参考にサーバーとクライアントの処理を作成します。
package org.mygrpc.helloworld;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class HelloWorldServer {
/** Log. */
protected static Log log = LogFactory.getLog(HelloWorldServer.class);
private Server server;
private void start() throws IOException {
int port = 50051;
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
log.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws IOException, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
package org.mygrpc.helloworld;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class HelloWorldClient {
/** Log. */
protected static Log log = LogFactory.getLog(HelloWorldClient.class);
public static void main(String[] args) throws Exception {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 50051).usePlaintext().build();
GreeterGrpc.GreeterBlockingStub blockingStub = GreeterGrpc
.newBlockingStub(channel);
try {
HelloRequest request = HelloRequest.newBuilder().setName("World").build();
try {
HelloReply resp = blockingStub.sayHello(request);
log.info(resp.getMessage());
} catch (StatusRuntimeException e) {
log.warn("RPC failed: " + e.getStatus());
return;
}
} finally {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
}
}
サーバーとクライアントをそれぞれ実行してHello World
と出力されればOK。
これでやっと開発できるようになりました。
ちなみに、protoファイル編集用のプラグインとして以下があるようですが、バージョン2.3.0以上はEclipse 4.6 Neon以上が必要とのことで諦めました。
https://github.com/google/protobuf-dt