The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

RESTEasy Classic

This guide is about RESTEasy Classic which used to be the default JAX-RS implementation until Quarkus 2.8.

It is now recommended to use RESTEasy Reactive, which supports equally well traditional blocking workloads and reactive workloads. For more information about RESTEasy Reactive, please see the introductory REST JSON guide or the more detailed RESTEasy Reactive guide.

there is another guide if you need a REST client based on RESTEasy Classic (including support for JSON).

アーキテクチャ

このガイドで開発するアプリケーションは非常にシンプルです: ユーザーはフォームを使用してリストに要素を追加することができ、リストが更新されます。

ブラウザとサーバー間の情報はすべて JSON 形式になっています。

Creating the Maven project

まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。

CLI
quarkus create app org.acme:rest-json-quickstart \
    --extension=resteasy-jackson \
    --no-code
cd rest-json-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストール方法については、Quarkus CLIガイドをご参照ください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.11.1.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-json-quickstart \
    -Dextensions="resteasy-jackson" \
    -DnoCode
cd rest-json-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

This command generates a new project importing the RESTEasy/JAX-RS and Jackson extensions, and in particular adds the following dependency:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-resteasy-jackson")

ユーザーエクスペリエンスを向上させるために、Quarkusは3つのJackson Java 8モジュール を登録しているので、手動で登録する必要はありません。

Quarkusは JSON-B もサポートしているので、JacksonよりもJSON-Bが好きな場合は、代わりにRESTEasy JSON-B エクステンションに依存したプロジェクトを作成することができます。

CLI
quarkus create app org.acme:rest-json-quickstart \
    --extension=resteasy-jsonb \
    --no-code
cd rest-json-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストール方法については、Quarkus CLIガイドをご参照ください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.11.1.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-json-quickstart \
    -Dextensions="resteasy-jsonb" \
    -DnoCode
cd rest-json-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

This command generates a new project importing the RESTEasy/JAX-RS and JSON-B extensions, and in particular adds the following dependency:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-resteasy-jsonb")

初めてのJSON RESTサービスの作成

この例では、果物のリストを管理するアプリケーションを作成します。

まず、以下のように Fruit Bean を作成してみましょう。

package org.acme.rest.json;

public class Fruit {

    public String name;
    public String description;

    public Fruit() {
    }

    public Fruit(String name, String description) {
        this.name = name;
        this.description = description;
    }
}

派手なことは何もありません。注意すべき重要なことは、デフォルトのコンストラクタを持つことはJSONシリアライズレイヤーで必須であるということです。

Now, create the org.acme.rest.json.FruitResource class as follows:

package org.acme.rest.json;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;

@Path("/fruits")
public class FruitResource {

    private Set<Fruit> fruits = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));

    public FruitResource() {
        fruits.add(new Fruit("Apple", "Winter fruit"));
        fruits.add(new Fruit("Pineapple", "Tropical fruit"));
    }

    @GET
    public Set<Fruit> list() {
        return fruits;
    }

    @POST
    public Set<Fruit> add(Fruit fruit) {
        fruits.add(fruit);
        return fruits;
    }

    @DELETE
    public Set<Fruit> delete(Fruit fruit) {
        fruits.removeIf(existingFruit -> existingFruit.name.contentEquals(fruit.name));
        return fruits;
    }
}

The implementation is pretty straightforward, and you just need to define your endpoints using the JAX-RS annotations.

Fruit オブジェクトは、プロジェクトの初期化時に選択したエクステンションに応じて、 JSON-B または Jackson によって自動的にシリアライズ/デシリアライズされます。

quarkus-resteasy-jacksonquarkus-resteasy-jsonb などの JSON エクステンションがインストールされている場合、メディアタイプが @Produces@Consumes アノテーションで明示的に設定されていない限り、Quarkus はほとんどの戻り値に application/json メディアタイプをデフォルトで使用します( StringFile などのよく知られたタイプには例外があり、それぞれ text/plainapplication/octet-stream がデフォルトとなっています)。

デフォルトでJSONを使用したくない場合は、 quarkus.resteasy-json.default-json=false を設定すると、デフォルトは自動ネゴシエーションに戻ります。これを設定した場合、JSON を使用するためには @Produces(MediaType.APPLICATION_JSON)@Consumes(MediaType.APPLICATION_JSON) をエンドポイントに追加する必要があります。

JSON のデフォルトに頼らない場合は、エンドポイントに @Produces@Consumes のアノテーションを付けて、期待されるコンテンツタイプを正確に定義することを強くお勧めします。これにより、ネイティブ実行可能ファイルに含まれる JAX-RS プロバイダ (コンバータとみなすことができます) の数を絞り込むことができます。

Configuring JSON support

Jackson

Quarkusでは、CDI経由で取得した(そしてQuarkusのエクステンションによって消費される)デフォルトのJackson ObjectMapper は、未知のプロパティーを無視するように設定されています( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 機能を無効にすることで)。

You can restore the default behavior of Jackson by setting quarkus.jackson.fail-on-unknown-properties=true in your application.properties or on a per-class basis via @JsonIgnoreProperties(ignoreUnknown = false).

さらに、 ObjectMapper 、日付と時刻をISO-8601でフォーマットするように設定されています( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS の機能を無効にすることで)。

application.propertiesquarkus.jackson.fail-on-unknown-properties=true を設定するか、 @JsonIgnoreProperties(ignoreUnknown = false) を経由してクラスごとに設定することで、Jackson のデフォルトの動作を復元することができます。

また、Quarkusは、CDI Bean を介して、様々なJackson設定を非常に簡単に設定することができます。最も単純な(そして推奨される)アプローチは、 io.quarkus.jackson.ObjectMapperCustomizer 型の CDI Bean を定義し、その中で、Jackson の設定を適用することです。

カスタムモジュールを登録する必要がある場合の例は次のようになります。

import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.jackson.ObjectMapperCustomizer;
import javax.inject.Singleton;

@Singleton
public class RegisterCustomModuleCustomizer implements ObjectMapperCustomizer {

    public void customize(ObjectMapper mapper) {
        mapper.registerModule(new CustomModule());
    }
}

ユーザーは、選択すれば自分の ObjectMapper Beanを提供することもできます。この場合、 ObjectMapper を生成する CDI プロデューサの中で、すべての io.quarkus.jackson.ObjectMapperCustomizer Bean を手動で注入して適用することが非常に重要です。これを怠ると、様々なエクステンションによって提供される Jackson 固有のカスタマイズが適用されなくなります。

import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.jackson.ObjectMapperCustomizer;

import javax.enterprise.inject.Instance;
import javax.inject.Singleton;

public class CustomObjectMapper {

    // Replaces the CDI producer for ObjectMapper built into Quarkus
    @Singleton
    ObjectMapper objectMapper(Instance<ObjectMapperCustomizer> customizers) {
        ObjectMapper mapper = myObjectMapper(); // Custom `ObjectMapper`

        // Apply all ObjectMapperCustomizer beans (incl. Quarkus)
        for (ObjectMapperCustomizer customizer : customizers) {
            customizer.customize(mapper);
        }

        return mapper;
    }
}

JSON-B

上記のように、Quarkusでは、 quarkus-resteasy-jsonb エクステンションを使用することで、Jacksonの代わりにJSON-Bを使用するオプションを提供しています。

前項と同様のアプローチで、 io.quarkus.jsonb.JsonbConfigCustomizer beanを使用してJSON-Bを設定することができます。

例えば、 FooSerializer という名前のカスタムシリアライザを com.example.Foo タイプで JSON-B で登録する必要がある場合、以下のような Bean を追加すれば十分です。

import io.quarkus.jsonb.JsonbConfigCustomizer;
import javax.inject.Singleton;
import javax.json.bind.JsonbConfig;
import javax.json.bind.serializer.JsonbSerializer;

@Singleton
public class FooSerializerRegistrationCustomizer implements JsonbConfigCustomizer {

    public void customize(JsonbConfig config) {
        config.withSerializers(new FooSerializer());
    }
}

より高度なオプションとしては、 javax.json.bind.JsonbConfig ( Dependent スコープ付き)の Bean を直接提供するか、極端な場合には javax.json.bind.Jsonb ( Singleton スコープ付き)のタイプの Bean を提供することが考えられます。後者のアプローチを利用する場合は、 javax.json.bind.Jsonb を生成する CDI プロデューサに io.quarkus.jsonb.JsonbConfigCustomizer Bean をすべて手動で注入して適用することが非常に重要です。これを怠ると、様々なエクステンションによって提供される JSON-B 固有のカスタマイズが適用されなくなります。

import io.quarkus.jsonb.JsonbConfigCustomizer;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Instance;
import javax.json.bind.JsonbConfig;

public class CustomJsonbConfig {

    // Replaces the CDI producer for JsonbConfig built into Quarkus
    @Dependent
    JsonbConfig jsonConfig(Instance<JsonbConfigCustomizer> customizers) {
        JsonbConfig config = myJsonbConfig(); // Custom `JsonbConfig`

        // Apply all JsonbConfigCustomizer beans (incl. Quarkus)
        for (JsonbConfigCustomizer customizer : customizers) {
            customizer.customize(config);
        }

        return config;
    }
}

The HAL standard is a simple format to represent web links.

To enable the HAL support, add the quarkus-hal extension to your project. Also, as HAL needs JSON support, you need to add either the quarkus-resteasy-jsonb or the quarkus-resteasy-jackson extension.

Table 1. Table Context object
GAV 使用方法

io.quarkus:quarkus-hal

HAL

After adding the extensions, we can now annotate the REST resources to produce the media type application/hal+json (or use RestMediaType.APPLICATION_HAL_JSON). For example:

@Path("/records")
public class RecordsResource {

    @GET
    @Produces({ MediaType.APPLICATION_JSON, "application/hal+json" })
    @LinkResource(entityClassName = "org.acme.Record", rel = "list")
    public List<TestRecord> getAll() {
        // ...
    }

    @GET
    @Path("/first")
    @Produces({ MediaType.APPLICATION_JSON, "application/hal+json" })
    @LinkResource(rel = "first")
    public TestRecord getFirst() {
        // ...
    }
}

Now, the endpoints /records and /records/first will accept the media type both json and hal+json to print the records in Hal format.

たとえば、curl を使用して /records エンドポイントを呼び出してレコードのリストを返す場合、HAL 形式は次のようになります。

& curl -H "Accept:application/hal+json" -i localhost:8080/records
{
    "_embedded": {
        "items": [
            {
                "id": 1,
                "slug": "first",
                "value": "First value",
                "_links": {
                    "list": {
                        "href": "http://localhost:8081/records"
                    },
                    "first": {
                        "href": "http://localhost:8081/records/first"
                    }
                }
            },
            {
                "id": 2,
                "slug": "second",
                "value": "Second value",
                "_links": {
                    "list": {
                        "href": "http://localhost:8081/records"
                    },
                    "first": {
                        "href": "http://localhost:8081/records/first"
                    }
                }
            }
        ]
    },
    "_links": {
        "list": {
            "href": "http://localhost:8081/records"
        }
    }
}

When we call a resource /records/first that returns only one instance, then the output is:

& curl -H "Accept:application/hal+json" -i localhost:8080/records/first
{
    "id": 1,
    "slug": "first",
    "value": "First value",
    "_links": {
        "list": {
            "href": "http://localhost:8081/records"
        },
        "first": {
            "href": "http://localhost:8081/records/first"
        }
    }
}

フロントエンドの作成

ここで、 FruitResource .Quarkusと対話するための簡単なウェブページを追加してみましょう。Quarkusは、 META-INF/resources ディレクトリーの下にある静的リソースを自動的に提供します。 src/main/resources/META-INF/resources ディレクトリーに、この fruits.html ファイルの内容を含む fruits.html ファイルを追加します。

これで、REST サービスと対話できるようになりました。

  • Quarkusを起動します。

    CLI
    quarkus dev
    Maven
    ./mvnw quarkus:dev
    Gradle
    ./gradlew --console=plain quarkusDev
  • ブラウザで http://localhost:8080/fruits.html を開きます。

  • フォームを使って新しいフルーツをリストに追加します。

ネイティブ実行可能ファイルの構築

You can build a native executable with the usual command:

CLI
quarkus build --native
Maven
./mvnw package -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native

実行は簡単で、 ./target/rest-json-quickstart-1.0-SNAPSHOT-runner を実行するだけです。

その後、ブラウザで http://localhost:8080/fruits.html を開いてアプリケーションを使用します。

シリアライゼーションについて

JSONシリアライズライブラリは、Javaのリフレクションを使用してオブジェクトのプロパティーを取得してシリアライズします。

GraalVMでネイティブ実行可能ファイルを使用する場合、リフレクションで使用されるすべてのクラスを登録する必要があります。良いニュースは、Quarkusがほとんどの場合、その作業を代行してくれるということです。これまでのところ、 Fruit でさえ、リフレクトを使用するためのクラスを登録しておらず、すべてが正常に動作しています。

Quarkusは、RESTメソッドからシリアライズされた型を推論することができる場合に、何らかのマジックを実行します。以下のようなRESTメソッドがある場合、Quarkusは、 Fruit がシリアライズされると判断します。

@GET
public List<Fruit> list() {
    // ...
}

Quarkusは、ビルド時にRESTメソッドを分析することで、自動的にそのような処理を行ってくれます。

JAX-RSの世界では、 Response オブジェクトを使用するのがもう一つの一般的なパターンです。 Response にはいくつかの素晴らしい特典があります。

  • メソッドで何が起こるかによって異なるエンティティータイプを返すことができます (例えば LegumeError )。

  • Response の属性を設定することができます (エラーが発生した時にステータスを知ることができます)。

RESTメソッドは次のようになります。

@GET
public Response list() {
    // ...
}

Response に含まれるタイプは情報がないため、Quarkusがビルド時に判断することはできません。この場合、Quarkusは必要なクラスを自動的に反映登録することができません。

これが次のセクションにつながります。

Using Response

Fruit クラスと同じモデルに従って、JSON としてシリアライズされる Legume クラスを作成してみましょう。

package org.acme.rest.json;

public class Legume {

    public String name;
    public String description;

    public Legume() {
    }

    public Legume(String name, String description) {
        this.name = name;
        this.description = description;
    }
}

それでは、マメ科植物のリストを返すメソッドを一つだけ持つ LegumeResource REST サービスを作成してみましょう。

このメソッドは Response を返し、 Legume のリストではありません。

package org.acme.rest.json;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/legumes")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class LegumeResource {

    private Set<Legume> legumes = Collections.synchronizedSet(new LinkedHashSet<>());

    public LegumeResource() {
        legumes.add(new Legume("Carrot", "Root vegetable, usually orange"));
        legumes.add(new Legume("Zucchini", "Summer squash"));
    }

    @GET
    public Response list() {
        return Response.ok(legumes).build();
    }
}

ここで、マメ科植物のリストを表示するための簡単なウェブページを追加してみましょう。 src/main/resources/META-INF/resources ディレクトリーに、この legumes.html ファイルの内容を含む legumes.html ファイルを追加します。

Open a browser to http://localhost:8080/legumes.html, and you will see our list of legumes.

興味深い部分は、アプリケーションをネイティブ実行可能ファイルとして実行するときに始まります。

  • create the native executable with:

    CLI
    quarkus build --native
    Maven
    ./mvnw package -Dnative
    Gradle
    ./gradlew build -Dquarkus.package.type=native
  • ./target/rest-json-quickstart-1.0-SNAPSHOT-runner で実行します

  • open a browser and go to http://localhost:8080/legumes.html

そこには豆類はありません。

As mentioned above, the issue is that Quarkus was not able to determine the Legume class will require some reflection by analyzing the REST endpoints. The JSON serialization library tries to get the list of fields of Legume and gets an empty list, so it does not serialize the fields' data.

現時点では、JSON-BやJacksonがクラスのフィールドのリストを取得しようとしたときに、そのクラスがリフレクションに登録されていない場合、例外はスローされません。GraalVMは単に空のフィールドのリストを返します。

うまくいけば、将来的にはこれが変化して、エラーがより明白になるでしょう。

Legume クラスに @RegisterForReflection アノテーションを追加することで、手動で Legume を リフレクション用に登録することができます。

import io.quarkus.runtime.annotations.RegisterForReflection;

@RegisterForReflection
public class Legume {
    // ...
}
@RegisterForReflection アノテーションは、ネイティブコンパイル時にクラスとそのメンバーを保持するようQuarkusに指示します。 @RegisterForReflection アノテーションの詳細については、 ネイティブアプリケーションのヒントのページを参照してください。

それを実行して、今までと同じ手順を踏んでみましょう。

  • Ctrl+C を叩いてアプリケーションを停止させる

  • create the native executable with:

    CLI
    quarkus build --native
    Maven
    ./mvnw package -Dnative
    Gradle
    ./gradlew build -Dquarkus.package.type=native
  • ./target/rest-json-quickstart-1.0-SNAPSHOT-runner で実行します

  • open a browser and go to http://localhost:8080/legumes.html

今回はマメ科の一覧が表示されました。

リアクティブであること

For reactive workloads, please always use RESTEasy Reactive.

非同期処理を処理するために リアクティブ型 を返すことができます。Quarkusでは、リアクティブで非同期なコードを書くために Mutiny の使用を推奨しています。

Mutiny と RESTEasy を統合するには、 quarkus-resteasy-mutiny 依存関係をプロジェクトに追加する必要があります。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-mutiny</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-resteasy-mutiny")

そして、エンドポイントは UniMulti のインスタンスを返すことができます。

@GET
@Path("/{name}")
public Uni<Fruit> getOne(@PathParam String name) {
    return findByName(name);
}

@GET
public Multi<Fruit> getAll() {
    return findAll();
}

単一の結果がある場合は Uni を使用します。 Multi は、非同期的に放出される可能性のある複数の項目がある場合に使用します。

UniResponse を使用して、非同期 HTTP レスポンスを返すことができます: Uni<Response> .

Mutinyについての詳細は、 Mutiny - 直感的なリアクティブプログラミングライブラリ に記載されています。

HTTP filters and interceptors

HTTP リクエストとレスポンスの両方とも、それぞれ ContainerRequestFilter または ContainerResponseFilter の実装を提供することで、 インターセプトすることができます。これらのフィルタは、メッセージに関連付けられたメタデータを処理するのに適しています。HTTP ヘッダ、クエリパラメーター、メディアタイプ、その他のメタデータです。また、ユーザーがエンドポイントにアクセスする権限を持っていない場合など、リクエスト処理を中止する機能も持っています。

ContainerRequestFilter を使用して、サービスにロギング機能を追加してみましょう。 ContainerRequestFilter を実装して、 @Provider アノテーションをつけることで実現できます。

package org.acme.rest.json;

import io.vertx.core.http.HttpServerRequest;
import org.jboss.logging.Logger;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;

@Provider
public class LoggingFilter implements ContainerRequestFilter {

    private static final Logger LOG = Logger.getLogger(LoggingFilter.class);

    @Context
    UriInfo info;

    @Context
    HttpServerRequest request;

    @Override
    public void filter(ContainerRequestContext context) {

        final String method = context.getMethod();
        final String path = info.getPath();
        final String address = request.remoteAddress().toString();

        LOG.infof("Request %s %s from IP %s", method, path, address);
    }
}

これで、RESTメソッドが呼び出されるたびに、リクエストがコンソールにログとして記録されるようになりました。

2019-06-05 12:44:26,526 INFO  [org.acm.res.jso.LoggingFilter] (executor-thread-1) Request GET /legumes from IP 127.0.0.1
2019-06-05 12:49:19,623 INFO  [org.acm.res.jso.LoggingFilter] (executor-thread-1) Request GET /fruits from IP 0:0:0:0:0:0:0:1
2019-06-05 12:50:44,019 INFO  [org.acm.res.jso.LoggingFilter] (executor-thread-1) Request POST /fruits from IP 0:0:0:0:0:0:0:1
2019-06-05 12:51:04,485 INFO  [org.acm.res.jso.LoggingFilter] (executor-thread-1) Request GET /fruits from IP 127.0.0.1

CORS filter

クロスオリジンリソース共有 (CORS)は、ウェブページ上の制限されたリソースを、最初のリソースが提供されたドメイン以外の別のドメインから要求できるようにするメカニズムです。

Quarkus comes with a CORS filter. Read the HTTP Reference Documentation to learn how to use it.

GZip Support

QuarkusにはGZipサポートが搭載されています(デフォルトでは有効になっていませんが)。以下の設定ノブを使用して、GZipサポートを設定できます。

quarkus.resteasy.gzip.enabled=true (1)
quarkus.resteasy.gzip.max-input=10M (2)
1 Gzipサポートを有効にします。
2 デフレーションされたリクエストボディの上限を設定します。これは、リーチを制限することで潜在的な攻撃を緩和するのに便利です。既定値は 10M です。この設定オプションは、以下の形式の文字列を認識します(正規表現で表示されます): [0-9]+[KkMmGgTtPpEeZzYy]? .サフィックスが指定されていない場合は、バイトとみなします。

GZip サポートが有効になったら、エンドポイントメソッドに @org.jboss.resteasy.annotations.GZIP アノテーションを追加することで、エンドポイントで使用することができます。

The configuration property quarkus.http.enable-compression has no effect on compression support of RESTEasy Classic endpoints.

マルチパートサポート

RESTEasyは RESTEasy Multipart Provider を介してマルチパートをサポートしています。

Quarkusは、 quarkus-resteasy-multipart というエクステンションを提供しています。

このエクステンションは、デフォルトの文字セットが US-ASCII ではなく UTF-8 であるため、RESTEasy のデフォルトの動作とは若干異なります。

この動作は、以下の構成プロパティーで設定できます。

ビルド時に固定される設定プロパティ - それ以外の設定プロパティは実行時に上書き可能

Configuration property

タイプ

デフォルト

Default charset. Note that the default value is UTF-8 which is different from RESTEasy’s default value US-ASCII.

Environment variable: QUARKUS_RESTEASY_MULTIPART_INPUT_PART_DEFAULT_CHARSET

Charset

UTF-8

The default content-type.

Environment variable: QUARKUS_RESTEASY_MULTIPART_INPUT_PART_DEFAULT_CONTENT_TYPE

string

text/plain

サーブレットとの互換性

Quarkusでは、RESTEasyはVert.x HTTPサーバーの上で直接実行するか、サーブレットに依存している場合はUndertowの上で実行することができます。

その結果、 HttpServletRequest のような特定のクラスが常にインジェクションに利用できるわけではありません。この特定のクラスのほとんどのユースケースは、リモートクライアントの IP を取得することを除いて、JAX-RS と同等のものでカバーされています。RESTEasy には、インジェクション可能な代替 API が付属しています。 HttpRequest これは以下のメソッドを持っています。 getRemoteAddress() そして getRemoteHost() を解決するために、この問題を解決します。

RESTEasy and REST Client interactions

In Quarkus, the RESTEasy extension and the REST Client extension share the same infrastructure. One important consequence of this consideration is that they share the same list of providers (in the JAX-RS meaning of the word).

例えば、 WriterInterceptor を宣言した場合、デフォルトではサーバーの呼び出しとクライアントの呼び出しの両方をインターセプトしますが、これは望ましい動作ではないかもしれません。

しかし、このデフォルトの動作を変更してプロバイダを制約することができます。

  • プロバイダに @ConstrainedTo(RuntimeType.SERVER) アノテーションを追加することで、 サーバー コールのみを考慮します。

  • プロバイダに @ConstrainedTo(RuntimeType.CLIENT) アノテーションを追加することで、 クライアント コールのみを考慮します。

What’s Different from Jakarta EE Development

Application クラスは不要

Application のアプリケーションが提供するサブクラスによる設定もサポートされていますが、必須ではありません。

単一のJAX-RSアプリケーションのみ

JAX-RS(およびRESTeasy)が標準のサーブレットコンテナーで実行されているのとは対照的に、Quarkusは単一のJAX-RSアプリケーションのデプロイのみをサポートしています。複数のJAX-RS Application クラスが定義されている場合、ビルドは Multiple classes have been annotated with @ApplicationPath which is currently not supported というメッセージとともに失敗するでしょう。

複数の JAX-RS アプリケーションが定義されている場合、プロパティー quarkus.resteasy.ignoreApplicationClasses=true を使用して、すべての明示的な Application クラスを無視することができます。これにより、すべてのリソースクラスが quarkus.resteasy.path で定義されたアプリケーションパス(デフォルトは / )を介して利用できるようになります。

Support limitations of JAX-RS application

The RESTEasy extension doesn’t support the method getProperties() of the class javax.ws.rs.core.Application. Moreover, it only relies on the methods getClasses() and getSingletons() to filter out the annotated resource, provider and feature classes. It doesn’t filter out the built-in resource, provider and feature classes and also the resource, provider and feature classes registered by the other extensions. Finally, the objects returned by the method getSingletons() are ignored, only the classes are taken into account to filter out the resource, provider and feature classes, in other words the method getSingletons() is actually managed the same way as getClasses().

リソースのライフサイクル

Quarkusでは、すべてのJAX-RSリソースはCDI Bean として扱われます。 @Inject を介して他の Bean を注入したり、 @Transactional のようなバインディングを使用してインターセプターをバインドしたり、 @PostConstruct コールバックを定義したりすることが可能です。

リソースクラスでスコープ注釈が宣言されていない場合は、スコープはデフォルトになります。デフォルトのスコープは quarkus.resteasy.singleton-resources プロパティーで制御できます。 true (デフォルト) に設定すると、( @javax.inject.Singleton で定義されているように) すべてのリクエストにサービスを提供するためのリソースクラスの 単一のインスタンス が作成されます。 false に設定すると、各リクエストごとにリソースクラスの 新しい インスタンス が作成されます。明示的な CDI スコープ注釈 ( @RequestScoped , @ApplicationScoped , など) は常にデフォルトの動作を上書きし、リソースインスタンスのライフサイクルを指定します。

ビルド時条件でJAX-RSクラスを含める/除外する

Quarkusでは、CDI Beanの場合と同様に、ビルド時の条件に応じて、JAX-RSリソース、プロバイダー、および機能を直接包含または除外することができます。したがって、さまざまなJAX-RSクラスは、プロファイル条件( @io.quarkus.arc.profile.IfBuildProfile または @io.quarkus.arc.profile.UnlessBuildProfile )および/またはプロパティ条件( io.quarkus.arc.properties.IfBuildProperty または io.quarkus.arc.properties.UnlessBuildProperty )でアノテーションすることができ、構築時にどの条件でこれらのJAX-RSクラスが含まれるべきかをQuarkusに示すことができます。

次の例では、Quarkusは、ビルドプロファイル app1 が有効になっている場合に限り、エンドポイント sayHello を含めます。

@IfBuildProfile("app1")
public class ResourceForApp1Only {

    @GET
    @Path("sayHello")
    public String sayHello() {
        return "hello";
     }
}

JAX-RSアプリケーションが検出され、メソッド getClasses() および/または getSingletons() がオーバーライドされている/されている場合、Quarkusはビルド時の条件を無視し、JAX-RSアプリケーションで定義されているもののみを考慮することに注意してください。

まとめ

Quarkusを使用したJSON RESTサービスの作成は、実績のあるよく知られたテクノロジーに依存しているため、簡単に行えます。

いつものように、Quarkusは、アプリケーションをネイティブ実行可能ファイルとして実行する際に、水面下の作業をさらに簡略化しています。

覚えておくべきことは一つだけあります。 Response を使用していて、Quarkus がシリアライズされているBeanを特定できない場合は、 @RegisterForReflection を使ってアノテーションを付ける必要があります。