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 Jakarta REST (formerly known as JAX-RS) implementation until Quarkus 2.8.

It is now recommended to use Quarkus REST (formerly RESTEasy Reactive), which supports both traditional blocking workloads and reactive workloads equally well.

For more information about Quarkus REST, please see the introductory REST JSON guide or the Quarkus REST reference documentation.

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

アーキテクチャ

The application created in this guide is straightforward: users can add elements to a list through a form, and the list gets updated accordingly.

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

Maven プロジェクトの作成

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

コマンドラインインタフェース
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:3.9.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-json-quickstart \
    -Dextensions='resteasy-jackson' \
    -DnoCode
cd rest-json-quickstart

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

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=rest-json-quickstart"

This command generates a new project importing the RESTEasy/Jakarta REST 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")

To improve user experience, Quarkus registers the three Jackson Java 8 modules, so you do not need to do it manually.

Quarkus also supports JSON-B, so if you prefer JSON-B over Jackson, you can create a project relying on the RESTEasy JSON-B extension instead:

コマンドラインインタフェース
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:3.9.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-json-quickstart \
    -Dextensions='resteasy-jsonb' \
    -DnoCode
cd rest-json-quickstart

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

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=rest-json-quickstart"

This command generates a new project importing the RESTEasy/Jakarta REST 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")

Creating the first JSON REST service

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

First, let us create the Fruit bean as follows:

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 jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.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;
    }
}

実装は非常に簡単で、Jakarta RESTアノテーションを使用してエンドポイントを定義するだけです。

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

When a JSON extension like quarkus-resteasy-jackson or quarkus-resteasy-jsonb is installed, Quarkus defaults to the application/json media type for most return values. This can be overridden using @Produces or @Consumes annotations, except for certain well-known types like String (defaulting to text/plain) and File (defaulting to application/octet-stream).

To disable the default JSON behavior, set quarkus.resteasy-json.default-json=false, and the default will return to auto-negotiation. In this case, you must include @Produces(MediaType.APPLICATION_JSON) and @Consumes(MediaType.APPLICATION_JSON) annotations in your endpoints to use JSON.

If you don’t depend on the JSON default, it’s highly advisable to use @Produces and @Consumes annotations on your endpoints to specify the expected content types precisely. This helps reduce the number of Jakarta REST providers (essentially converters) included in the native executable.

JSON サポートの設定

Jackson

In Quarkus, the default Jackson ObjectMapper obtained via CDI (utilized by Quarkus extensions) is set to ignore unknown properties (by disabling DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).

To revert to Jackson’s default behavior, set quarkus.jackson.fail-on-unknown-properties=true in your application.properties, or set it on a per-class basis with @JsonIgnoreProperties(ignoreUnknown = false).

Additionally, the ObjectMapper formats dates and times in ISO-8601 (by disabling SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).

To restore Jackson’s default behavior, use quarkus.jackson.write-dates-as-timestamps=true in your application.properties. For custom date format on a single field, use the @JsonFormat annotation.

Quarkus simplifies Jackson configuration via CDI beans. Create a CDI bean of type io.quarkus.jackson.ObjectMapperCustomizer to apply various Jackson settings. Here’s an example for registering a custom module:

@ApplicationScoped
public class MyObjectMapperCustomizer implements ObjectMapperCustomizer {
    @Override
    public void customize(ObjectMapper objectMapper) {
        // Add custom Jackson configuration here
    }
}

This approach is recommended for configuring Jackson settings.

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

@Singleton
public class RegisterCustomModuleCustomizer implements ObjectMapperCustomizer {

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

Users can even provide their own ObjectMapper bean if they so choose. If this is done, it is very important to manually inject and apply all io.quarkus.jackson.ObjectMapperCustomizer beans in the CDI producer that produces ObjectMapper. Failure to do so will prevent Jackson-specific customizations provided by various extensions from being applied.

import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.arc.All;
import io.quarkus.jackson.ObjectMapperCustomizer;
import java.util.List;
import jakarta.inject.Singleton;

public class CustomObjectMapper {

    // Replaces the CDI producer for ObjectMapper built into Quarkus
    @Singleton
    ObjectMapper objectMapper(@All List<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 を使用するオプションを提供しています。

Following the same approach described in the previous section, JSON-B can be configured using an io.quarkus.jsonb.JsonbConfigCustomizer bean.

If, for example, a custom serializer named FooSerializer for type com.example.Foo needs to be registered with JSON-B, the addition of a bean like the following would suffice:

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

@Singleton
public class FooSerializerRegistrationCustomizer implements JsonbConfigCustomizer {

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

A more advanced option would be to directly provide a bean of jakarta.json.bind.JsonbConfig (with a Dependent scope) or, in the extreme case, to provide a bean of type jakarta.json.bind.Jsonb (with a Singleton scope). If the latter approach is leveraged it is very important to manually inject and apply all io.quarkus.jsonb.JsonbConfigCustomizer beans in the CDI producer that produces jakarta.json.bind.Jsonb. Failure to do so will prevent JSON-B specific customizations provided by various extensions from being applied.

import io.quarkus.jsonb.JsonbConfigCustomizer;

import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Instance;
import jakarta.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;
    }
}

HAL 標準は、ウェブリンクを表現するためのシンプルなフォーマットです。

HAL のサポートを有効にするには、 quarkus-hal エクステンションをプロジェクトに追加します。また、 HAL は JSON サポートを必要とするため、 quarkus-resteasy-jsonb または quarkus-resteasy-jackson のいずれかのエクステンションモジュールを追加する必要があります。

Table 1. Table Contect オブジェクト
GAV 使用方法

io.quarkus:quarkus-hal

HAL

エクステンションを追加したら、次は 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() {
        // ...
    }
}

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"
        }
    }
}

フロントエンドの作成

Now let us add a simple web page to interact with our FruitResource. Quarkus automatically serves static resources located under the META-INF/resources directory. In the src/main/resources/META-INF/resources directory, add a fruits.html file with the content from this fruits.html file in it.

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

  • 以下のように Quarkus を起動します。

    コマンドラインインタフェース
    quarkus dev
    Maven
    ./mvnw quarkus:dev
    Gradle
    ./gradlew --console=plain quarkusDev
  • ブラウザーで http://localhost:8080/fruits.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/fruits.html を開いてアプリケーションを使用します。

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

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

When using native executables with GraalVM, all classes that will be used with reflection need to be registered. The good news is that Quarkus does that work for you most of the time. So far, we have not registered any class, not even Fruit, for reflection usage, and everything is working fine.

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

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

Quarkus does that for you automatically by analyzing the REST methods at build time, and that is why we did not need any reflection registration in the first part of this guide.

Jakarta RESTの世界でよく見られるもう一つのパターンは、 Response オブジェクトを使うことです。 Response には、いくつかの良い特典があります:

  • You can return different entity types depending on what happens in your method (a Legume or an Error for instance).

  • You can set the attributes of the Response (the status comes to mind in the case of an error).

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

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

Quarkus cannot determine at build time the type included in the Response as the information is not available. In this case, Quarkus won’t be able to register for reflection in the required classes automatically.

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

Using response

Let us create the Legume class, which will be serialized as JSON, following the same model as for our Fruit class:

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;
    }
}

Now let’s create a LegumeResource REST service with only one method that returns the list of legumes.

このメソッドは Legume のリストではなく Response を返ます。

package org.acme.rest.json;

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

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.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();
    }
}

Now, let us add a simple web page to display our list of legumes. In the src/main/resources/META-INF/resources directory, add a legumes.html file with the content from this legumes.html file in it.

ブラウザーを開いて 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 にアクセスします。

There are no legumes there.

As mentioned above, the issue is that Quarkus could not determine the Legume class, which 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.

At the moment, when JSON-B or Jackson tries to get the list of fields of a class, if the class is not registered for reflection, no exception will be thrown. GraalVM will return an empty list of fields.

将来的にはこの点が変わり、エラーがより明白になることが期待されます。

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

import io.quarkus.runtime.annotations.RegisterForReflection;

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

Let us do that and follow the same steps as before:

  • 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 にアクセスします。

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

リアクティブであること

For reactive workloads, please always use Quarkus REST.

非同期処理を処理するために リアクティブ型 を返すことができます。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 は、非同期的に放出される可能性のある複数の項目がある場合に使用します。

Uni<Response> のように、 UniResponse を使用して、非同期 HTTP レスポンスを返すことができます。

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

HTTP フィルターとインターセプター

Both HTTP request and response can be intercepted by providing ContainerRequestFilter or ContainerResponseFilter implementations respectively. These filters are suitable for processing the metadata associated with a message: HTTP headers, query parameters, media type, and other metadata. They also can abort the request processing, for instance, when the user does not have permission to access the endpoint.

Let’s use ContainerRequestFilter to add logging capability to our service. We can do that by implementing ContainerRequestFilter and annotating it with the @Provider annotation:

package org.acme.rest.json;

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

import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.UriInfo;
import jakarta.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 includes a CORS filter at the HTTP layer level. For more information about the CORS filters and their usage, see the CORS filter section of the Quarkus "Cross-origin resource sharing" guide.

GZipのサポート

Quarkus では、デフォルトでは有効になっていませんが GZip をサポートしています。以下のプロパティーを使用して、GZipのサポートを設定することができます。

quarkus.resteasy.gzip.enabled=true (1)
quarkus.resteasy.gzip.max-input=10M (2)
1 Gzipサポートを有効にします。
2 Configure the upper limit on the deflated request body. This is useful to mitigate potential attacks by limiting their reach. The default value is 10M. This configuration option would recognize strings in this format (shown as a regular expression): [0-9]+[KkMmGgTtPpEeZzYy]?. If no suffix is given, assume bytes.

Once GZip support has been enabled, you can use it on an endpoint by adding the @org.jboss.resteasy.annotations.GZIP annotation to your endpoint method.

There is also the quarkus.http.enable-compression configuration property, which enables HTTP response compression globally. If enabled, a response body is compressed if the Content-Type HTTP header is set and the value is a compressed media type configured via the quarkus.http.compress-media-types configuration property.

マルチパートのサポート

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

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

このエクステンションは RESTEasy のデフォルトの動作とは若干異なり、リクエストで何も指定されていない場合のデフォルトの文字セットは US-ASCII ではなく UTF-8 となります。

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

ビルド時に固定される構成プロパティ - 他のすべての構成プロパティは実行時にオーバーライド可能

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

Show more

Charset

UTF-8

The default content-type.

Environment variable: QUARKUS_RESTEASY_MULTIPART_INPUT_PART_DEFAULT_CONTENT_TYPE

Show more

string

text/plain

サーブレットとの互換性

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

As a result, certain classes, such as HttpServletRequest are not always available for injection. Most use cases for this particular class are covered by Jakarta REST equivalents, except for getting the remote client’s IP.

RESTEasy comes with a replacement API that you can inject: HttpRequest, which has the methods getRemoteAddress() and getRemoteHost() to solve this problem.

RESTEasy と RESTクライアントのやりとり

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 Jakarta REST meaning of the word).

For instance, if you declare a WriterInterceptor, it will, by default, intercept both the servers calls and the client calls, which might not be the desired behavior.

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

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

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

Jakarta EE 開発との違い

Application クラスは不要

Configuration via an application-supplied subclass of Application is supported but not required.

単一のJakarta RESTアプリケーション限定

In contrast to Jakarta REST (and RESTeasy) running in a standard servlet container, Quarkus only supports the deployment of a single Jakarta REST application. If multiple Jakarta REST Application classes are defined, the build will fail with the message Multiple classes have been annotated with @ApplicationPath which is currently not supported.

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

Jakarta RESTアプリケーションのサポートの制限

The RESTEasy extension doesn’t support the method getProperties() of the class jakarta.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 does not 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 managed the same way as getClasses().

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

In Quarkus, all Jakarta REST resources are treated as CDI beans. It’s possible to inject other beans via @Inject, bind interceptors using bindings such as @Transactional, define @PostConstruct callbacks, etc.

If no scope annotation is declared on the resource class, then the scope is defaulted. The quarkus.resteasy.singleton-resources property can control the default scope.

If set to true (default), then a single instance of a resource class is created to service all requests (as defined by @jakarta.inject.Singleton).

If set to false, then a new instance of the resource class is created per each request.

An explicit CDI scope annotation (@RequestScoped, @ApplicationScoped, etc.) always overrides the default behavior and specifies the lifecycle of resource instances.

ビルド時条件でのJakarta RESTのクラスのインクルード/エクスクルード

Quarkusでは、CDI Beanと同様に、ビルド時の条件によって、Jakarta RESTリソース、プロバイダ、フィーチャーを直接取り込んだり除外したりすることができます。したがって、さまざまなJakarta RESTクラスにプロファイル条件( @io.quarkus.arc.profile.IfBuildProfile または @io.quarkus.arc.profile.UnlessBuildProfile )やプロパティ条件( io.quarkus.arc.properties.IfBuildProperty または io.quarkus.arc.properties.UnlessBuildProperty )をアノテーションして、ビルド時にQuarkusに対して、どのような条件の下でJakarta RESTクラスを含めるべきかを示すことができます。

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

@IfBuildProfile("app1")
public class ResourceForApp1Only {

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

Jakarta REST Applicationが検出され、メソッド getClasses()getSingletons() がオーバーライドされている場合、Quarkusはビルド時の条件を無視し、Jakarta REST Applicationで定義されているもののみを考慮することに注意してください。

まとめ

Creating JSON REST services with Quarkus is easy as it relies on proven and well-known technologies.

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

There is only one thing to remember: if you use Response and Quarkus cannot determine the beans that are serialized, you need to annotate them with @RegisterForReflection.

関連コンテンツ