RESTビルダーを使用したAPIの作成と実装
RESTビルダーを使用すると、構築したいAPIを定義でき、RESTビルダーはフレームワークとエンドポイントを提供します。
サンプルのREST APIをデプロイする
RESTビルダーの動作を確認するために、カタログ内のIDによってダミー製品を取得するサンプルAPIをデプロイできます。 この簡単な例がどのように機能するかを理解したら、独自のアプリケーション用のAPIを作成できます。
新しいLiferay インスタンスを起動し、以下を実行します。
docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.112-ga112。
http://localhost:8080でLiferayへのサインインします。 メールアドレス test@liferay.com とパスワード test を使用してください。 プロンプトが表示されたら、パスワードを learn に変更します。
次に、以下の手順を実行します。
-
Acme Foo API を含む
.zip
アーカイブをダウンロードして解凍する:curl https://resources.learn.liferay.com/dxp/latest/en/headless-delivery/apis-with-rest-builder/liferay-r3b2.zip -O
unzip liferay-r3b2.zip
-
サンプルをビルドしてデプロイします。
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
noteこのコマンドは、デプロイされたjarをDockerコンテナの/opt/liferay/osgi/modulesにコピーするのと同じです。
-
api
バンドルとimpl
バンドルの両方のDockerコンテナコンソールでのデプロイを確認します。STARTED com.acme.headless.r3b2.api_1.0.0 STARTED com.acme.headless.r3b2.impl_1.0.0
-
DXPインスタンスにログインし、 グローバルメニュー()→ [コントロールパネル] → [Gogoシェル] に移動します。
-
Gogoシェルプロンプトで、次のコマンドを入力します。
jaxrs:check
このページには、新しくデプロイされたAPIである
Liferay.Headless.R3B2
を含む、インストールされているすべてのJAX-RSバンドルが一覧表示されます。 これでAPIがデプロイされ、呼び出す準備が整いました。 -
ターミナルから次のコマンドを実行し、
{fooId}
を1〜3の数字に置き換えて、APIをテストします。curl -u 'test@liferay.com:learn' "http://localhost:8080/o/headless-r3b2/v1.0/foo/{fooId}"
クエリは、JSONオブジェクトでラップされた対応する製品のID、名前、および説明を返します。
{ "description": "Universal truth must be transcendental.", "id": 1, "name": "Truth" }
新しいREST APIを正常にデプロイして使用しました。
RESTビルダーで生成されたAPIを確認したので、次はそれがどのように機能するかを理解します。
初期設定
Liferay Workspaceプロジェクトでimpl
およびapi
モジュールを作成することから始めます。 impl
モジュールのbuild.gradle
ファイルは、RESTビルダーをプラグインとしてインストールして適用する必要があります。
buildscript {
dependencies {
classpath group: "com.liferay", name: "com.liferay.gradle.plugins.rest.builder", version: "1.1.32"
}
repositories {
maven {
url "https://repository-cdn.liferay.com/nexus/content/groups/public"
}
}
}
apply plugin: "com.liferay.portal.tools.rest.builder"
dependencies {
compileOnly group: "com.liferay.portal", name: "release.portal.api"
compileOnly project(":headless-r3b2-api")
}
両方のモジュールのbuild.gradle
ファイルも、ポータルリリースへの依存関係を宣言する必要があります。
YAML構成
最初のステップは、RESTビルダー構成ファイルを作成することです。 impl
モジュールのルートフォルダに、rest-config.yaml
とrest-openapi.yaml
の2つのファイルを追加します。 これらのファイルには、RESTビルダーがAPIのビルディングブロックコードを生成するために必要なすべての情報が含まれている必要があります。
RESTビルダー構成を追加する
RESTビルダーの構成はrest-config.yaml
ファイルに属します。 この構成では次のフィールドを定義します。
apiDir
:Javaソースコードフォルダ
apiPackagePath
:RESTビルダーがすべてのモジュールにわたってコードを生成する開始Javaパッケージパス
baseURI
:このプロジェクトのすべてのAPIのコンテキストURL
className
:ルートリソースクラスのJavaクラス名(JAX-RSで使用)
name
:APIのJAX-RS名
次の構造を使用して、これらのフィールドを定義します。
apiDir: "../headless-r3b2-api/src/main/java"
apiPackagePath: "com.acme.headless.r3b2"
application:
baseURI: "/headless-r3b2"
className: "HeadlessR3B2Application"
name: "Liferay.Headless.R3B2"
author: "Jonah the son of Amittai"
clientDir: "../headless-r3b2-client/src/main/java"
testDir: "../headless-r3b2-test/src/testIntegration/java"
OpenAPI構成に情報ブロックを追加する
次に、rest-openapi.yaml
ファイルを開いて、APIの構成を開始します。
追加する最初のセクションは、情報ブロックです。
info:
description:
"API to return a Foo."
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
title: "Headless R3B2"
version: v1.0
openapi: 3.0.1
ここで定義された version
フィールドは、APIパスがLiferayインスタンス内で公開されるときにURLの一部になります。
必要なスキーマを定義する
次に、components
ブロックで、エンティティのスキーマを定義します。 RESTビルダーは、ここで定義したものを使用して、これらのエンティティを表す対応するJavaBeansを作成します。
表現するエンティティごとにschema
ブロックを定義します。
components:
schemas:
Foo:
properties:
description:
type: string
id:
format: int64
type: integer
name:
type: string
type: object
Goo:
properties:
description:
type: string
fooId:
format: int64
type: integer
id:
format: int64
type: integer
name:
type: string
この例では、Foo
というスキーマが、このAPIを使用するための重要なデータを表しています。 Goo
エンティティは、fooId
を使用してFoo
にリンクされています。 スキーマでサポートされているデータタイプのリストについては、 OpenAPIの仕様 を参照してください。
スキーマ定義によって、RESTビルダーが生成するクラスの名前が決まります。これには、リソースファイル内のビルディングブロックとテンプレートが含まれます。 上記のスキーマはFoo
およびBar
と呼ばれるため、実装ロジックはFooResourceImpl
クラスとGooResourceImpl
クラスに属します。
APIを定義する
最後に、paths
ブロックを追加します。 これには、RESTビルダーで実装する予定のすべてのAPIが含まれている必要があります。 パスブロックの小さなスニペットを次に示します。
paths:
"/foo":
get:
# operations for get and post go here. See the project for full source code.
# ...
"/foo/{fooId}":
get:
operationId: getFoo
# ...
responses:
200:
content:
application/json:
schema:
$ref: "#/components/schemas/Foo"
application/xml:
schema:
$ref: "#/components/schemas/Foo"
# Place other operations, such as get, patch, and put here. See the project for full source code.
"/foo/{fooId}/goos":
get:
operationId: getFooGoosPage
# This is the relationship between Foos and Goos.
# Place your get and post operations here.
# ...
"/goo/{gooId}":
delete:
operationId: deleteGoo
# Place operations on other entities as needed.
get
、 post
、 put
、 patch
、 delete
など、さまざまな種類のリクエストのパスを追加できます。
このパス(foo/{fooId}
)は、URLの末尾にパス文字列を追加することでこのAPI(getFoo
)に到達できることを指定します(これには、rest-config.yaml
ファイルのbaseURI
とversion
の値も含まれます)。 たとえば、このサンプルAPIには、完全なURL:localhost:8080/o/headless-r3b2/v1.0/foo/{fooId}
を介してアクセスします。
fooId
の代わりに使用する値は、一致する名前のパラメーターとして使用されます。
各パスには、parameters
ブロックの下(およびget
ブロック内)にresponses
ブロックがあり、少なくとも成功した呼び出しの応答(200
応答で示される)を定義します。
このresponses
ブロックは、呼び出しの成功時にProduct
を返すことを指定します。 文字列#/components/schemas/Foo
は、同じファイルで以前に定義されたスキーマを参照し、RESTビルダーがこのAPIの戻り値のタイプとしてFoo
スキーマを使用できるようにします。
最後に、responses
ブロックの下に、このパスのtags
定義を追加します。
tags: ["Foo"]
このタグは、RESTビルダーがビルディングブロックコードにアノテーションを付けるときに生成されたドキュメンテーションに追加される情報を指定します。 タグ名は、スキーマの名前を反映している必要があります。
完全なリファレンスについては、以前にダウンロードしたrest-openapi.yaml
ファイルを参照してください。
関連をどのように行うかを示すGoo
オブジェクトもあります。Gooは、fooId
に関連付けられているという意味でFooに関連付けられています。
RESTビルダーを実行する
これで、RESTビルダーがほとんどの作業を実行するために必要なすべての構成が追加されたので、impl
モジュール内から次のコマンドを実行してbuildREST
Gradleタスクを実行します。
../gradlew buildREST
RESTビルダーはこの構成を使用して、api
クラスとimpl
クラスの両方にビルディングブロックコードと、実装ロジックを追加できるJavaクラスを取り込みます。
GraphQLエンドポイントコードは graphql
、JAX-RSアプリケーションコードは jaxrs
パッケージで、それぞれ生成されています。 独自のAPI実装は、resource
パッケージの適切な*ResourceImpl
クラスに追加されます。
実装ロジックを追加する
最後のステップは、定義した各APIのロジックを定義することです。 impl
モジュール内で、rest-openapi.yaml
で定義したスキーマ名(この例では、FooResourceImpl.java
とGooResourceImpl.java
)に基づいて、実装が配置されるJavaリソースクラスを見つけます。
実装のクラスの場所は、rest-config.yaml
ファイルでapiPackagePath
に定義した値によって異なります。 そのパスをたどり、その中のinternal/resource/<version>/
に移動します。 この例と同じパスを使用した場合、ファイルはsrc/main/java/com/acme/headless/r3b2/internal/resource/v1_0/
内にあります。
実装クラス([SchemaName]ResourceImpl
)は、基本クラス(Base[SchemaName]ResourceImpl
)の横にあります。 実装クラスを開きます。 これは単なる例であるため、この実装では事前に入力されたHashTable
を使用し、getFoo
メソッドは一致するfooId
を持つHashTable
から製品を返します。 完全な実装については、プロジェクト内のFooResourceImpl.java
を参照してください。
@Override
public Foo getFoo(Integer fooId) {
return _foos.get(fooId);
}
このメソッドは、特別なJAX-RSアノテーションを使用して定義された基本クラス(Base[SchemaName]ResourceImpl
)で定義された基本メソッドをオーバーライドします。
リクエストを完了するために、任意のビジネスロジックを追加できます。 RESTビルダーは、スキーマで定義したオブジェクトのデフォルトコンストラクターのみを作成します。 このサンプルのビジネスロジックは、オブジェクトを作成し、それに値を追加します(rest-openapi.yaml
でparameters
を定義した方法に基づく)。
Foo foo1 = new Foo() {
{
description = "Universal truth must be transcendental.";
id = 1L;
name = "Truth";
}
};
Goo
ロジックは似ていますが、この場合、Foo
オブジェクトに複数のGoo
を含めることができるため、複数のGoo
が返される点が異なります。 オブジェクトのコレクションを返すときは、Page
と呼ばれるページ付けに適したオブジェクトを使用する必要があります。
@Override
public Page<Goo> getFooGoosPage(Long fooId) {
List<Goo> goos = new ArrayList<>();
for (Goo goo : _goos.values()) {
if (Objects.equals(fooId, goo.getFooId())) {
goos.add(goo);
}
}
return Page.of(goos);
}
まとめ
これで、RESTビルダーを使用して新しいAPIを実装するための基本を理解し、DXPに新しいAPIを追加しました。