マルチパートでのRESTクライアントの使用
このガイドは、Quarkus 2.8までデフォルトのJakarta REST(旧JAX-RS)実装であった RESTEasy Classic 互換のREST Clientのマルチパート対応に関するものです。 It is now recommended to use Quarkus REST (formerly RESTEasy Reactive), which supports equally well traditional blocking workloads and reactive workloads. For more information about Quarkus REST, please see the REST Client guide and, for the server side, the introductory REST JSON guide or the more detailed Quarkus REST guide. |
RESTEasyは、 multipart/*
と multipart/form-data
のマイムタイプを豊富にサポートしています。マルチパートマイムフォーマットは、コンテンツボディのリストを渡すために使用されます。 multipart/form-data
は、Web アプリケーションのHTMLフォームドキュメントでよく見られ、一般的にはファイルのアップロードに使用されます。form-dataフォーマットは、他のマルチパートフォーマットと同じですが、インラインの各コンテンツには名前が関連付けられています。
このガイドでは、マルチパートでRESTEasy RESTクライアントを使用して、 multipart/form-data
コンテンツタイプを必要とするREST APIとわずかな労力でやりとりする方法を説明します。
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。
Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.git
、 アーカイブ をダウンロードします。
The solution is located in the resteasy-client-multipart-quickstart
directory.
Mavenプロジェクトの作成
まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=resteasy-client-multipart-quickstart"
This command generates a Maven project with a REST endpoint and imports the resteasy-client
and resteasy
extensions.
It also adds the resteasy-multipart
extension to support multipart/form-data
requests.
Quarkusプロジェクトがすでに設定されている場合は、プロジェクトのベースディレクトリで次のコマンドを実行することで、 resteasy-multipart
エクステンションをプロジェクトに追加できます:
quarkus extension add resteasy-multipart
./mvnw quarkus:add-extension -Dextensions='resteasy-multipart'
./gradlew addExtension --extensions='resteasy-multipart'
これにより、 pom.xml
に以下が追加されます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-multipart</artifactId>
</dependency>
implementation("io.quarkus:quarkus-resteasy-multipart")
モデルのセットアップ
このガイドでは、 multipart/form-data
の入力を受け付けるRESTサービスを起動する方法を紹介します。リクエストが送信される前にペイロードが既知であることを想定しているので、POJOとしてモデル化することができます。
ペイロードが不明な場合は、代わりにRESTEasy のカスタムAPIを使用することもできます。その場合は、ガイドの最後にある RESTEasy Multipart Providers のリンクを参照してください。 |
まず最初に、 multipart/form-data
のペイロードを定義するために使用するモデルを、 MultipartBody
POJO の形で設定します。
src/main/java/org/acme/rest/client/multipart/MultipartBody.java
ファイルを作成し、以下の内容を設定します。
package org.acme.rest.client.multipart;
import java.io.InputStream;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.providers.multipart.PartType;
public class MultipartBody {
@FormParam("file")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
public InputStream file;
@FormParam("fileName")
@PartType(MediaType.TEXT_PLAIN)
public String fileName;
}
上のコードのアノテーションの目的は以下の通りです。
-
@FormParam
は、リクエストエンティティ本体に含まれるフォームパラメータを定義するために使用される Jakarta REST の標準アノテーションです。 -
@PartType
は、クライアントがマルチパートのリクエストを実行し、パートのコンテンツタイプを定義する際に必要となる、RESTEasy特有のアノテーションです。
インターフェースの作成
RESTEasy REST Client の使用方法は、適切な Jakarta REST と MicroProfile アノテーションを使用してインターフェースを作成するだけです。この場合、インターフェースは src/main/java/org/acme/rest/client/multipart/MultipartService.java
で作成し、以下の内容を持つ必要があります:
package org.acme.rest.client.multipart;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
@Path("/echo")
@RegisterRestClient
public interface MultipartService {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
String sendMultipartData(@MultipartForm MultipartBody data);
}
sendMultipartData
メソッドは、コードに multipart/form-data
リクエストをEchoサービスに POST する機能を与えます(デモ用に同じサーバーで実行しています)。このデモでは、 multipart/form-data
パケットの正確に把握しているので、 @org.jboss.resteasy.annotations.providers.multipart.MultipartForm
アノテーションを使用して、前のセクションで作成したモデルクラスにマッピングすることができます。
ネットワーキングやマーシャリングはすべてクライアントが行うので、私たちのコードにはそのような技術的な詳細は含まれません。
上のコードのアノテーションの目的は以下の通りです。
-
@RegisterRestClient
により、Quarkusは、このインターフェイスがRESTクライアントとしてCDIインジェクションに利用可能であることを知ることができます。 -
@Path
と@POST
は、サービスへのアクセス方法を定義するために使用される、標準的な Jakarta REST アノテーションです。 -
@MultipartForm
は、multipart/form-dataマイムタイプの受信/送信リクエスト/レスポンスの値オブジェクトとして、パラメータを定義しています。 -
@Consumes
は、このリクエストで消費されると予想されるコンテンツタイプを定義します(パラメータ)。 -
@Produces
は、このリクエストによって生成されると予想されるコンテンツタイプを定義します(リターンタイプ)。
これにより、ネイティブ実行可能ファイルに含まれるJakarta RESTプロバイダー(コンバーターとも言える)の数を絞ることができるようになります。 |
コンフィグレーションの作成
REST 呼び出しが行われるベース URL を決定するために、REST クライアントは application.properties
からの設定を使用します。プロパティーの名前は、以下のコードで表示される特定の規則に従う必要があります。
# Your configuration properties
quarkus.rest-client."org.acme.rest.client.multipart.MultipartService".url=http://localhost:8080/
この設定を行うと、 org.acme.rest.client.multipart.MultipartService
を使用して実行されるすべてのリクエストは、 http://localhost:8080/
をベースURLとします。
なお、org.acme.rest.client.multipart.MultipartService
は、前のセクションで作成した MultipartService
インターフェースの完全修飾名と一致していなければならないことに注意してください。
Jakarta RESTリソースの作成
src/main/java/org/acme/rest/client/multipart/MultipartClientResource.java
のファイルを、以下の内容で作成します。
package org.acme.rest.client.multipart;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import jakarta.inject.Inject;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RestClient;
@Path("/client")
public class MultipartClientResource {
@Inject
@RestClient
MultipartService service;
@POST
@Path("/multipart")
@Produces(MediaType.TEXT_PLAIN)
public String sendFile() throws Exception {
MultipartBody body = new MultipartBody();
body.fileName = "greeting.txt";
body.file = new ByteArrayInputStream("HELLO WORLD".getBytes(StandardCharsets.UTF_8));
return service.sendMultipartData(body);
}
}
なお、標準のCDI @Inject
アノテーションに加えて、マイクロプロファイル @RestClient
アノテーションを使って MultipartService
を入れる必要があることに注意してください。
サーバーの作成
デモ用に、サーバー部分として機能するシンプルなEchoエンドポイントを作成してみましょう。
src/main/java/org/acme/rest/client/multipart/server
ディレクトリを作成し、以下の内容の EchoService.java
ファイルを入れます。
package org.acme.rest.client.multipart.server;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/echo")
public class EchoService {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public String echo(String requestBody) throws Exception {
return requestBody;
}
}
これは単にリクエストボディを返すだけなので、テスト目的として便利です。
テストの更新
また、エンドポイントに加えられた変更を反映させるために、機能テストを更新する必要があります。 src/test/java/org/acme/rest/client/multipart/MultipartClientResourceTest.java
ファイルを下記のように編集します。
package org.acme.rest.client.multipart;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
@QuarkusTest
public class MultipartClientResourceTest {
@Test
public void testMultipartDataIsSent() {
given()
.when().post("/client/multipart")
.then()
.statusCode(200)
.body( containsString("Content-Disposition: form-data; name=\"file\""),
containsString("HELLO WORLD"),
containsString("Content-Disposition: form-data; name=\"fileName\""),
containsString("greeting.txt"));
}
}
上記のコードでは、 REST Assuredを使用して、エコーサービスから返されるコンテンツにマルチパート要素が含まれていることをアサートしています。
テストは別のポートで実行されるため、 src/test/resources
に、次に示す内容で application.properties
を含める必要があります。
# Your configuration properties
quarkus.rest-client."org.acme.rest.client.multipart.MultipartService".url=http://localhost:8081/
アプリケーションをパッケージ化して実行する
アプリケーションを実行します:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
ターミナルで、 curl -X POST http://localhost:8080/client/multipart
を実行します。
以下のような出力が表示されるはずです。
--89d288bd-960f-460c-b266-64c5b4d170fa
Content-Disposition: form-data; name="fileName"
Content-Type: text/plain
greeting.txt
--89d288bd-960f-460c-b266-64c5b4d170fa
Content-Disposition: form-data; name="file"
Content-Type: application/octet-stream
HELLO WORLD
--89d288bd-960f-460c-b266-64c5b4d170fa--
いつものように、アプリケーションは以下の方法でパッケージ化されます。
quarkus build
./mvnw install
./gradlew build
そして、java -jar target/quarkus-app/quarkus-run.jar
で実行されます。
次のようにネイティブ実行可能ファイルを生成することもできます。
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true