RESTEasy Classic
このガイドは、 Quarkus 2.8 までデフォルトの JAX-RS 実装として使用されていた RESTEasy Classic についてのガイドです。 現在では、従来のブロック型ワークロードとリアクティブ型ワークロードを同様にサポートする RESTEasy Reactive の使用が推奨されています。 RESTEasy Reactive の詳細については、 入門編の REST JSON ガイドまたは詳細な RESTEasy Reactive ガイドを参照してください。 |
RESTEasy Classic をベースにした REST クライアント( JSON のサポートを含む)が必要な場合は、別のガイドを参照してください。 |
アーキテクチャ
このガイドで開発するアプリケーションは非常にシンプルです。 ユーザーはフォームを使用してリストに要素を追加することができ、リストが更新されます。
ブラウザとサーバー間の情報はすべて JSON 形式になっています。
Maven プロジェクトの作成
最初に、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。
このコマンドは、 RESTEasy/JAX-RS および Jackson エクステンションをインポートする新しいプロジェクトを生成し、特に次の依存関係を追加します。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
implementation("io.quarkus:quarkus-resteasy-jackson")
ユーザーエクスペリエンスを向上させるために、 Quarkus は3つの Jackson Java 8 モジュール を登録するため、手動で登録する必要はありません。 |
Quarkus は JSON-B もサポートしているため、 Jackson よりも JSON-B を利用したい場合は、代わりに RESTEasy JSON-B エクステンションを依存関係に持つプロジェクトを作成することができます。
このコマンドは、 RESTEasy/JAX-RS および JSON-B エクステンションをインポートする新しいプロジェクトを生成し、特に次の依存関係を追加します。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
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 シリアライズレイヤーで必須であるということです。
次に、 org.acme.rest.json.FruitResource
クラスを以下のように作成します。
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;
}
}
実装は非常に簡単で、 JAX-RS のアノテーションを使ってエンドポイントを定義するだけです。
デフォルトで JSON を使用したくない場合は、 JSON のデフォルトに頼らない場合は、エンドポイントに |
JSON サポートの設定
Jackson
Quarkus では、 CDI経由で取得され、 Quarkusのエクステンションによって消費されるデフォルトの Jackson ObjectMapper
は、 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
機能を無効にすることで不明なプロパティを無視するように設定されています。
application.properties
で quarkus.jackson.fail-on-unknown-properties=true
を設定するか、 クラスごとに @JsonIgnoreProperties(ignoreUnknown = false)
を設定することで、Jackson のデフォルトの動作を復元することができます。
さらに、ObjectMapper
は、 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
機能を無効化することで日付と時刻を ISO-8601 でフォーマットするように設定されています。
application.properties
で quarkus.jackson.write-dates-as-timestamps=true
を設定すると、Jackson のデフォルトの動作を復元することができます。単一のフィールドのフォーマットを変更したい場合は、@JsonFormat
アノテーションを使用することができます。
また、 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());
}
}
より高度なオプションとしては、 Dependent
スコープ付きの javax.json.bind.JsonbConfig
の Bean を直接提供するか、極端な場合には Singleton
スコープ付きの javax.json.bind.Jsonb
のタイプの 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;
}
}
JSON Hypertext Application Language ( HAL ) のサポート
HAL 標準は、ウェブリンクを表現するためのシンプルなフォーマットです。
HAL のサポートを有効にするには、 quarkus-hal
エクステンションをプロジェクトに追加します。また、 HAL は JSON サポートを必要とするため、 quarkus-resteasy-jsonb
または quarkus-resteasy-jackson
のいずれかのエクステンションモジュールを追加する必要があります。
GAV | 使用方法 |
---|---|
|
エクステンションを追加したら、次は REST リソースにアノテーションを付け、メディアタイプ application/hal+json
(または RestMediaType.APPLICATION_HAL_JSON を使用) を生成できるようにします。例えば、以下のようになります。
@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() {
// ...
}
}
これで、エンドポイント /records
と /records/first
は、メディアタイプ json
と hal+json
の両方を受け入れ、HAL 形式のレコードを表示します。
例えば、 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 は、 META-INF/resources
ディレクトリーの下にある静的リソースを自動的に提供します。 src/main/resources/META-INF/resources
ディレクトリーに、この fruits.html ファイルの内容を含む fruits.html
ファイルを追加します。
これで、REST サービスと対話できるようになりました。
-
以下のように Quarkus を起動します。
コマンドラインインタフェースquarkus dev
Maven./mvnw quarkus:dev
Gradle./gradlew --console=plain quarkusDev
-
ブラウザーで
http://localhost:8080/fruits.html
を開きます。 -
フォームを使って新しい果物をリストに追加します。
ネイティブ実行可能ファイルのビルド
以下のコマンドでネイティブの実行ファイルをビルドすることができます。
quarkus build --native
./mvnw install -Dnative
./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
オブジェクトには、いくつかの便利な機能があります。
-
メソッド内で発生した内容に応じて異なるエンティティータイプを返すことができます ( 例えば
Legume
やError
) 。 -
Response
の属性 ( エラーの場合は、そのステータスなど ) を設定することができます。
REST メソッドは次のようになります。
@GET
public Response list() {
// ...
}
Response
に含まれるタイプは情報がないため、Quarkusがビルド時に判断することはできません。この場合、Quarkus は必要なクラスのリフレクションを自動的に登録することができません。
これが次のセクションにつながります。
レスポンスの利用
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;
}
}
それでは、マメ科植物 ( Legume ) のリストを返すメソッドを一つだけ持つ LegumeResource
REST サービスを作成してみます。
このメソッドは Legume
のリストではなく Response
を返ます。
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
ファイルを追加します。
ブラウザーを開いて http://localhost:8080/legumes.html にアクセスすると、マメ科植物のリストが表示されます。
興味深いのは、アプリケーションをネイティブ実行可能ファイルとして実行するときです。
-
以下でネイティブの実行ファイルを作成します。
コマンドラインインタフェースquarkus build --native
Maven./mvnw install -Dnative
Gradle./gradlew build -Dquarkus.package.type=native
-
./target/rest-json-quickstart-1.0-SNAPSHOT-runner
で実行します。 -
ブラウザーを起動し、 http://localhost:8080/legumes.html にアクセスします。
マメ科植物は見当たりません。
上記のように、問題は Quarkus が、 REST エンドポイントを分析することで Legume
クラスが何らかのリフレクションを必要とすることを判断できなかったことです。 JSON シリアライズライブラリーは、 Legume
のフィールドのリストを取得しようとすると空のリストを取得するため、フィールドのデータをシリアライズしません。
現時点では、 JSON-B や Jackson がクラスのフィールドのリストを取得しようとしたときに、そのクラスがリフレクションに登録されていない場合、例外は発生しません。 GraalVM は単に空のフィールドのリストを返します。 将来的にはこの点が変わり、エラーがより明白になることが期待されます。 |
Legume
クラスに @RegisterForReflection
アノテーションを追加することで、手動で Legume
を リフレクション用に登録することができます。
import io.quarkus.runtime.annotations.RegisterForReflection;
@RegisterForReflection
public class Legume {
// ...
}
@RegisterForReflection アノテーションは、ネイティブコンパイル時にクラスとそのメンバーを保持するよう Quarkus に指示します。 @RegisterForReflection アノテーションの詳細については、 ネイティブアプリケーションのヒントのページを参照してください。
|
上記を反映して、今までと同じ手順を実行してみます。
-
Ctrl+C
でアプリケーションを停止させます。 -
以下でネイティブの実行ファイルを作成します。
コマンドラインインタフェースquarkus build --native
Maven./mvnw install -Dnative
Gradle./gradlew build -Dquarkus.package.type=native
-
./target/rest-json-quickstart-1.0-SNAPSHOT-runner
で実行します。 -
ブラウザーを起動し、 http://localhost:8080/legumes.html にアクセスします。
今回はマメ科植物の一覧が表示されました。
リアクティブであること
リアクティブなワークロードには、常に RESTEasy Reactive を使用してください。 |
非同期処理を処理するために リアクティブ型 を返すことができます。Quarkusでは、リアクティブで非同期なコードを書くために Mutiny の使用を推奨しています。
Mutiny と RESTEasy を統合するには、 quarkus-resteasy-mutiny
依存関係をプロジェクトに追加する必要があります。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-mutiny</artifactId>
</dependency>
implementation("io.quarkus:quarkus-resteasy-mutiny")
そして、エンドポイントは Uni
や Multi
のインスタンスを返すことができます。
@GET
@Path("/{name}")
public Uni<Fruit> getOne(@PathParam String name) {
return findByName(name);
}
@GET
public Multi<Fruit> getAll() {
return findAll();
}
単一の結果がある場合は Uni
を使用します。 Multi
は、非同期的に発行される可能性のある複数の項目がある場合に使用します。
Uni<Response>
のように、 Uni
と Response
を使用して、非同期 HTTP レスポンスを返すことができます。
Mutiny についての詳細は、 Mutiny - 直感的なリアクティブプログラミングライブラリー に記載されています。
HTTP フィルターとインターセプター
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 フィルター
オリジン間リソース共有 ( CORS ) は、ウェブページ上の制限されたリソースを、最初のリソースが提供されたドメイン以外の別のドメインから要求できるようにするメカニズムです。
Quarkus には、 CORS フィルターが付属しています。使用方法については、 HTTP リファレンスドキュメント を参照してください。
GZipのサポート
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
アノテーションを追加することで、エンドポイントで使用することができます。
設定プロパティー quarkus.http.enable-compression は、RESTEasy Classic エンドポイントの圧縮サポートに影響を与えません。
|
マルチパートのサポート
RESTEasy は RESTEasy Multipart Provider を介してマルチパートをサポートしています。
Quarkusは 、 quarkus-resteasy-multipart
というエクステンションを提供しています。
このエクステンションは RESTEasy のデフォルトの動作とは若干異なり、リクエストで何も指定されていない場合のデフォルトの文字セットは US-ASCII ではなく UTF-8 となります。
この動作は、以下のプロパティーで設定できます。
ビルド時に固定される設定プロパティ - その他の設定プロパティはランタイムでオーバーライド可能です。
型 |
デフォルト |
|
---|---|---|
Default charset. Note that the default value is UTF-8 which is different from RESTEasy’s default value US-ASCII. Environment variable: |
|
|
The default content-type. Environment variable: |
string |
|
サーブレットとの互換性
Quarkus では、 RESTEasy は Vert.x HTTP サーバーの上で直接実行するか、サーブレットに依存している場合は Undertow の上で実行することができます。
その結果、 HttpServletRequest
のような特定のクラスは、常に注入に利用できるわけではありません。この特定のクラスのほとんどのユースケースは、リモートクライアントの IP を取得することを除いて、JAX-RS と同等のものでカバーされています。 RESTEasy には、 getRemoteAddress()
と getRemoteHost()
という、この問題を解決することができる注入可能な代替 API が付属しています。
RESTEasy と RESTクライアントのやりとり
Quarkus では、 RESTEasy エクステンションと REST Client エクテンションは同じインフラストラクチャーを共有しています。この考察の重要な結果の1つは、 JAX-RS の意味においての同じプロバイダーリストを共有していることです。
例えば、 WriterInterceptor
を宣言した場合、デフォルトではサーバーの呼び出しとクライアントの呼び出しの両方を横取りしますが、これは望ましい動作ではない可能性があります。
しかし、このデフォルトの動作を変更してプロバイダーに制約を設けることができます。
-
プロバイダーに
@ConstrainedTo(RuntimeType.SERVER)
アノテーションを追加することで、 サーバー の呼び出しのみを考慮します。 -
プロバイダーに
@ConstrainedTo(RuntimeType.CLIENT)
アノテーションを追加することで、 クライアント の呼び出しのみを考慮します。
Jakarta EE 開発との違い
単一の 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
で定義されたアプリケーションパス ( デフォルトは /
) を介して利用できるようになります。
JAX-RS アプリケーションのサポートの制限
RESTEasy エクステンションは、クラス javax.ws.rs.core.Application
のメソッド getProperties()
をサポートしていません。さらに、アノテーションされたリソース、プロバイダー、機能クラスをフィルタリングするために、 getClasses()
と getSingletons()
のメソッドにのみ依存しています。組み込みのリソース、プロバイダー、機能クラスや、他のエクステンションで登録されたリソース、プロバイダー、機能クラスはフィルタリングされません。最後に、メソッド getSingletons()
が返すオブジェクトは無視され、リソース、プロバイダー、機能クラスをフィルタリングするためにクラスのみが考慮されます。言い換えれば、メソッド getSingletons()
は実際には getClasses()
と同じように管理されます。
リソースのライフサイクル
Quarkus では、すべての JAX-RS リソースは CDI Bean として扱われます。 @Inject
を介して他の Bean を注入したり、 @Transactional
のようなバインディングを使用してインターセプターをバインドしたり、 @PostConstruct
コールバックを定義したりすることが可能です。
リソースクラスでスコープアノテーションが宣言されていない場合、そのスコープはデフォルトとなります。デフォルトのスコープは quarkus.resteasy.singleton-resources
プロパティーで制御することができます。 true
( デフォルト ) に設定すると、 @javax.inject.Singleton
で定義されているように、リソースクラスの 単一の インスタンスが作成され、すべてのリクエストに対応します。 false
に設定すると、各リクエストごとに、リソースクラスの 新しい インスタンスが作成されます。 @RequestScoped
, @ApplicationScoped
などの明示的な CDI スコープアノテーションは、常にデフォルトの動作を上書きし、リソースインスタンスのライフサイクルを指定することができます。
ビルド時条件による 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 アプリケーションで定義されているもののみを考慮することに注意してください。