これは、なにをしたくて書いたもの?
RESTEasyを組み込みサーバー上で動かす方法はいくつかあるのですが、以前にもUndertow、Netty、JDK HTTP Severなどで
やったことがあります。
RESTEasyをJDK付属のHTTPサーバ、Undertowで動かす - CLOVER🍀
UndertowでJAX-RS(RESTEasy)とCDIを使う - CLOVER🍀
RESTEasy+Netty(Netty 3/Netty 4/Netty 4 with CDI)で遊ぶ - CLOVER🍀
今回は、Vert.xを試してみようかなと。Quarkusで使われているJAX-RSのデフォルトのエンジンも、UndertowからVert.xに
なりましたしね。
RESTEasy Vert.x Embedded Container
RESTEasyでの、Vert.xをEmbedded Containerとして組み込む方法は、こちら。
Undertowなど、他のEmbedded Containerを使ったことがあれば、そう難しくはありません。
JAX-RSクライアント側の実装もあるのですが、こちらは今回のお題では問題が出たのでパスしました…。
とりあえず、使っていってみましょう。
環境
今回の環境は、こちらです。
$ java --version openjdk 11.0.7 2020-04-14 OpenJDK Runtime Environment (build 11.0.7+10-post-Ubuntu-2ubuntu218.04) OpenJDK 64-Bit Server VM (build 11.0.7+10-post-Ubuntu-2ubuntu218.04, mixed mode, sharing) $ mvn --version Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 11.0.7, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "4.15.0-101-generic", arch: "amd64", family: "unix"
準備
pom.xmlは、以下のように設定。
<dependencies> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-vertx</artifactId> <version>4.5.3.Final</version> </dependency> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-core</artifactId> <version>3.9.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.6.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.6.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.16.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </build>
resteasy-vertxではVert.xへの依存関係はprovidedとして定義されているため、Vert.xに関しては自分で依存関係に加えてあげないと
いけません。
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-vertx</artifactId> <version>4.5.3.Final</version> </dependency> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-core</artifactId> <version>3.9.1</version> </dependency>
なお、providedに設定されているVert.xのバージョンは、こちらですね。
https://github.com/resteasy/Resteasy/blob/4.5.3.Final/resteasy-dependencies-bom/pom.xml#L34
その他の依存関係(JUnit、AssertJ)は、テストコード用として使います。
では、プログラムを書いていってみましょう。
JAX-RSリソースクラス
まずは、JAX-RSリソースクラスを用意します。簡単な、足し算を行うだけのクラスです。
src/main/java/org/littlewings/resteasy/vertx/CalcResource.java
package org.littlewings.resteasy.vertx; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; @Path("calc") public class CalcResource { @GET @Path("add") @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) public int add(@QueryParam("a") int a, @QueryParam("b") int b) { return a + b; } }
テストコードの雛形
Vert.xを使ったサーバーの起動および、動作確認はテストコードで行います。
テストコードの雛形は、こちらです。
src/test/java/org/littlewings/reteasy/vertx/ResteasyVertxTest.java
package org.littlewings.reteasy.vertx; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.UriBuilder; import io.vertx.core.VertxOptions; import io.vertx.core.http.HttpServerOptions; import org.jboss.resteasy.plugins.server.vertx.VertxJaxrsServer; import org.jboss.resteasy.plugins.server.vertx.VertxResteasyDeployment; import org.jboss.resteasy.spi.ResteasyDeployment; import org.junit.jupiter.api.Test; import org.littlewings.resteasy.vertx.CalcResource; import static org.assertj.core.api.Assertions.assertThat; public class ResteasyVertxTest { // ここに、テストを書く!! }
シンプルに使ってみる
最初は、1番シンプルなパターンで使ってみましょう。
こんな感じです。
@Test public void gettingStarted() { ResteasyDeployment deployment = new VertxResteasyDeployment(); deployment.getResources().add(new CalcResource()); VertxJaxrsServer server = new VertxJaxrsServer(); server.setDeployment(deployment); server.setPort(8080); server.setRootResourcePath(""); server.start(); try { Client client = ClientBuilder.newBuilder() .build(); int result = client .target(UriBuilder.fromUri("http://localhost:8080/calc/add?a={a}&b={b}").build(5, 3)) .request() .get(Integer.class); assertThat(result).isEqualTo(8); client.close(); } finally { server.stop(); } }
ResteasyDeploymentには、Applicationのサブクラスや、JAX-RSリソースクラスなどを設定します。今回は、作成した
リソースクラスのみです。
ResteasyDeployment deployment = new VertxResteasyDeployment(); deployment.getResources().add(new CalcResource());
サーバーを起動するには、VertxJaxrsServerクラスを使用します。こちらで、パスやポートの設定を行い、先ほど作成した
ResteasyDeploymentを使用してJAX-RSサーバーとしての設定を行います。
VertxJaxrsServer server = new VertxJaxrsServer(); server.setDeployment(deployment); server.setPort(8080); server.setRootResourcePath(""); server.start();
あとは、startするだけ。
終了時には、stopメソッドを呼び出せばOKです。
} finally {
server.stop();
}
確認は、JAX-RSクライアントで。
Client client = ClientBuilder.newBuilder() .build(); int result = client .target(UriBuilder.fromUri("http://localhost:8080/calc/add?a={a}&b={b}").build(5, 3)) .request() .get(Integer.class); assertThat(result).isEqualTo(8); client.close();
まずは、これで確認できました、と。
Vert.xの設定を行う
次に、もうちょっと細かくVert.xの設定を行ってみましょう。
こちらです。
@Test public void customizeVertx() { ResteasyDeployment deployment = new VertxResteasyDeployment(); deployment.getResources().add(new CalcResource()); VertxOptions vertxOptions = new VertxOptions(); vertxOptions.setEventLoopPoolSize(Runtime.getRuntime().availableProcessors() * 2); // default vertxOptions.setWorkerPoolSize(30); HttpServerOptions serverOptions = new HttpServerOptions(); serverOptions.setMaxHeaderSize(8192); serverOptions.setPort(8080); serverOptions.setReuseAddress(true); VertxJaxrsServer server = new VertxJaxrsServer(); server.setDeployment(deployment); // server.setPort(8080); server.setRootResourcePath(""); server.setVertxOptions(vertxOptions); server.setServerOptions(serverOptions); server.start(); try { Client client = ClientBuilder.newBuilder() .build(); int result = client .target(UriBuilder.fromUri("http://localhost:8080/calc/add?a={a}&b={b}").build(5, 3)) .request() .get(Integer.class); assertThat(result).isEqualTo(8); client.close(); } finally { server.stop(); } }
スレッド数の設定などは、VertxOptionsで行います。
VertxOptions vertxOptions = new VertxOptions(); vertxOptions.setEventLoopPoolSize(Runtime.getRuntime().availableProcessors() * 2); // default vertxOptions.setWorkerPoolSize(30);
また、HTTPサーバーとしての設定は、HttpServerOptionsで行います。
HttpServerOptions serverOptions = new HttpServerOptions(); serverOptions.setMaxHeaderSize(8192); serverOptions.setPort(8080); serverOptions.setReuseAddress(true);
こちらを、VertxJaxrsServerに設定します。
VertxJaxrsServer server = new VertxJaxrsServer(); server.setDeployment(deployment); // server.setPort(8080); server.setRootResourcePath(""); server.setVertxOptions(vertxOptions); server.setServerOptions(serverOptions);
VertxOptionsやHttpServerOptionsは、Vert.x自体が提供するクラスです。
VertxJaxrsServer#setPortなどは、実はVertxJaxrsServerが内部的に持っているHttpServerOptionsへ設定しているだけなので、
直接HttpServerOptionsを使う時は、設定はこちらに任せた方がよいのかもしれません。
JAX-RSクライアントを使った確認は、先ほどと同じなので省略。
あと、今回はRESTEasyを動かすためのEmbedded ContainerとしてVert.xを使用しましたが、Vert.xにRESTEasyを組み込む
という方法もあるようです(パスしましたが)。
クライアント側は、今回の確認パターンでは問題があったので…ちょっとなんとかしたいですね。