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

Spring Web APIのためのQuarkus エクステンション

RESTエンドポイントの定義にはJAX-RSアノテーションを使用することが推奨されていますが、QuarkusはSpring-webエクステンションという形でSpring Webとの互換性のあるレイヤーを提供しています。

このガイドでは、よく知られているSpring Webアノテーションを利用して、QuarkusアプリケーションでRESTfulサービスを定義する方法を説明します。

前提条件

このガイドを完成させるには、以下が必要です:

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 11+ がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.8.6

  • 使用したい場合は、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

ソリューション

次のセクションで紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。

Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.gitアーカイブ をダウンロードします。

このソリューションは spring-web-quickstart ディレクトリにあります。

Mavenプロジェクトの作成

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

コマンドラインインタフェース
quarkus create app org.acme:spring-web-quickstart \
    --extension='spring-web,resteasy-reactive-jackson' \
    --no-code
cd spring-web-quickstart

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

Quarkus CLIのインストール方法や使用方法については、<a href="cli-tooling.html">Quarkus CLIガイド</a> を参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.16.0.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=spring-web-quickstart \
    -Dextensions='spring-web,resteasy-reactive-jackson' \
    -DnoCode
cd spring-web-quickstart

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

このコマンドは、プロジェクトを生成し、 spring-web エクステンションをインポートします。

すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリで以下のコマンドを実行することで、 spring-web エクステンションをプロジェクトに追加することができます:

コマンドラインインタフェース
quarkus extension add 'spring-web,resteasy-reactive-jackson'
Maven
./mvnw quarkus:add-extension -Dextensions='spring-web,resteasy-reactive-jackson'
Gradle
./gradlew addExtension --extensions='spring-web,resteasy-reactive-jackson'

これにより、ビルドファイルに以下が追加されます:

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

quarkus-spring-web は、 quarkus-resteasy-jackson または quarkus-resteasy-reactive-jackson のいずれかで補完されないと動作しません。

GreetingController

RESTエンドポイントを定義するためのSpring Webアノテーションを持つコントローラである src/main/java/org/acme/spring/web/GreetingController.java ファイルを以下のように作成します:

package org.acme.spring.web;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/greeting")
public class GreetingController {

    @GetMapping
    public String hello() {
        return "hello";
    }
}

GreetingControllerTest

なお、コントローラのテストも作成されています:

package org.acme.spring.web;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingControllerTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/greeting")
          .then()
             .statusCode(200)
             .body(is("hello"));
    }

}

アプリケーションをパッケージ化して実行する

アプリケーションを次のように実行します:

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

ブラウザで http://localhost:8080/greeting を開きます。

結果は {"message": "hello"} のようになります。

アプリケーションをネイティブ実行可能ファイルとして実行する

以下を使用して、ネイティブ実行可能ファイルを生成することができます:

コマンドラインインタフェース
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native

JSONを返すエンドポイントでその先へ

上の GreetingController は、非常にシンプルなエンドポイントの例でした。しかし、多くの場合、JSONコンテンツを返さなければなりません。次の例では、Spring RestControllerを使用して実現しています:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/greeting")
public class GreetingController {

    @GetMapping("/{name}")
    public Greeting hello(@PathVariable(name = "name") String name) {
        return new Greeting("hello " + name);
    }

    public static class Greeting {
        private final String message;

        public Greeting(String message) {
            this.message = message;
        }

        public String getMessage(){
            return message;
        }
    }
}

対応するテストは次のようになります:

package org.acme.spring.web;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingControllerTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/greeting/quarkus")
          .then()
            .statusCode(200)
            .body("message", is("hello quarkus"));
    }

}

なお、QuarkusでSpring Webサポートを使用する場合、 Jacksonは自動的にクラスパスに追加され、適切に設定されます。

OpenAPIとSwagger-UIの追加

quarkus-smallrye-openapi エクステンションを使うことで、 OpenAPISwagger-UIのサポートを追加することができます。

このコマンドを実行してエクステンションを追加:

./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-openapi"

これにより、 pom.xml に以下が追加されます:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>

これだけでRESTエンドポイントから基本的なOpenAPIスキーマドキュメントを生成するのには十分です:

curl http://localhost:8080/q/openapi

生成されたOpenAPIスキーマのドキュメントが表示されます:

---
openapi: 3.0.1
info:
  title: Generated API
  version: "1.0"
paths:
  /greeting:
    get:
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                type: string
  /greeting/{name}:
    get:
      parameters:
      - name: name
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            'application/json':
              schema:
                $ref: '#/components/schemas/Greeting'
components:
  schemas:
    Greeting:
      type: object
      properties:
        message:
          type: string

OpenAPI ガイド も参照してください。

MicroProfile OpenAPIアノテーションの追加

MicroProfile OpenAPIを使用して、スキーマをより良く文書化することができます。例えば、 GreetingController のクラスレベルに以下を追加します:

@OpenAPIDefinition(
    info = @Info(
        title="Greeting API",
        version = "1.0.1",
        contact = @Contact(
            name = "Greeting API Support",
            url = "http://exampleurl.com/contact",
            email = "techsupport@example.com"),
        license = @License(
            name = "Apache 2.0",
            url = "https://www.apache.org/licenses/LICENSE-2.0.html"))
)

そして、エンドポイントをこのように記述します:

@Tag(name = "Hello", description = "Just say hello")
@GetMapping(produces=MediaType.TEXT_PLAIN_VALUE)
public String hello() {
    return "hello";
}

@GetMapping(value = "/{name}", produces=MediaType.APPLICATION_JSON_VALUE)
@Tag(name = "Hello to someone", description = "Just say hello to someone")
public Greeting hello(@PathVariable(name = "name") String name) {
    return new Greeting("hello " + name);
}

これにより、このOpenAPIスキーマが生成されます:

---
openapi: 3.0.1
info:
  title: Greeting API
  contact:
    name: Greeting API Support
    url: http://exampleurl.com/contact
    email: techsupport@example.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.1
tags:
- name: Hello
  description: Just say hello
- name: Hello to someone
  description: Just say hello to someone
paths:
  /greeting:
    get:
      tags:
      - Hello
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                type: string
  /greeting/{name}:
    get:
      tags:
      - Hello to someone
      parameters:
      - name: name
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/Greeting'
components:
  schemas:
    Greeting:
      type: object
      properties:
        message:
          type: string

Swagger UIの使用

Swagger UIは、 Dev または Test モードで実行するとデフォルトで含まれており、オプションで Prod モードに追加することができます。詳細は Swagger UI ガイドをご覧ください。

localhost:8080/q/swagger-ui/ に移動すると、Swagger UIの画面が表示されます:

Swagger UI

サポートされているSpring Webの機能

Quarkusは現在、Spring Webが提供する機能のサブセットをサポートしています。具体的には、QuarkusはSpring WebのREST関連の機能をサポートしています( @Controller の代わりに @RestController を考えてみてください)。

アノテーション

下の表は、サポートされているアノテーションをまとめたものです:

Table 1. サポートされているSpring Webアノテーション
Name コメント

@RestController

@RequestMapping

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

@RequestParam

@RequestHeader

@MatrixVariable

@PathVariable

@CookieValue

@RequestBody

@ResponseStatus

@ExceptionHandler

コントローラごとではなく、@RestControllerAdviceクラスでのみ使用可能です

@RestControllerAdvice

サポートされているのは@ExceptionHandler機能のみです

コントローラメソッドの戻り値の型

以下のメソッドの戻り値の型がサポートされています:

  • プリミティブ型

  • 文字列 (リテラルとして使用されます。Spring MVC ビューのサポートはありません)

  • JSON 経由でシリアライズされる POJO クラス

  • org.springframework.http.ResponseEntity

コントローラメソッドのパラメーターの型

前述の表の適切なSpring Webアノテーションでアノテーションできるメソッドパラメータに加えて、 javax.servlet.http.HttpServletRequestjavax.servlet.http.HttpServletResponse もサポートされています。ただし、これを機能させるためには、 quarkus-undertow の依存関係を追加する必要があります。

例外ハンドラーメソッドの戻り値の型

以下のメソッドの戻り値の型がサポートされています:

  • org.springframework.http.ResponseEntity

  • java.util.Map

Spring ExceptionHandler javadoc に記載されているその他の戻り値型はサポートされていません。

例外ハンドラーメソッドのパラメーターの型

以下のパラメーターの型がサポートされています(順不同):

  • 例外の引数:一般的な Exception として、またはより具体的な例外として宣言されています。これは、アノテーション自体が value() を使って例外の型を狭めていない場合、マッピングのヒントにもなります。

  • リクエストおよび/またはレスポンスオブジェクト(通常、サーブレットAPIからのもの)。ServletRequest / HttpServletRequest のように、 特定のリクエスト/レスポンス型を選択することができます。Servlet APIを使用するには、 quarkus-undertow の依存関係を追加する必要があります。

Spring ExceptionHandler javadoc に記載されているその他のパラメーターの型はサポートされていません。

重要な技術的注意点

QuarkusのSpringサポートでは、SpringのApplication Contextは開始されず、いかなるSpringのインフラクラスも実行されないことに注意してください。Springのクラスやアノテーションは、メタデータを読み込んだり、ユーザーコードのメソッドの戻り値の型やパラメータの型として使用されるだけです。エンドユーザーにとっての意味は、任意のSpringライブラリを追加しても何の効果もないということです。さらに、Springのインフラクラス(例えば org.springframework.beans.factory.config.BeanPostProcessor )は実行されません。

変換テーブル

以下の表は、Spring WebアノテーションをJAX-RSアノテーションに変換する方法を示しています。

Spring JAX-RS コメント

@RestController

JAX-RSにはこれに相当するものはありません。クラスのアノテーションは@Pathだけで十分です

@RequestMapping(path="/api")

@Path("/api")

@RequestMapping(consumes="application/json")

@Consumes("application/json")

@RequestMapping(produce="application/json")

@Produces("application/json")

@RequestParam

@QueryParam

@PathVariable

@PathParam

@RequestBody

JAX-RSでは同等のものはありません。JAX-RSでは、リクエストのボディに対応するメソッドのパラメータは、アノテーションを必要とせずに処理されます

@RestControllerAdvice

JAX-RSには同等のものはありません

@ResponseStatus

JAX-RSには同等のものはありません

@ExceptionHandler

JAX-RSには同等のアノテーションはありません。例外は javax.ws.rs.ext.ExceptionMapper の実装によってハンドリングされます