Service Builder Basics
ご覧のページは、お客様の利便性のために一部機械翻訳されています。また、ドキュメントは頻繁に更新が加えられており、翻訳は未完成の部分が含まれることをご了承ください。最新情報は都度公開されておりますため、必ず英語版をご参照ください。翻訳に問題がある場合は、 こちら までご連絡ください。

モデル、永続性、およびサービスコードの生成

サービスビルダーを使用すると、モデルを簡単に定義し、モデルコード、永続性コード、およびサービスコードを生成できます。 これは、Y7G4Entryというモデルを定義し、サービスビルダーを使用してコードを生成することで体験できます。 次に、コードをDXPにデプロイし、そのコードを使用するサービスを呼び出します。

サンプルプロジェクトをダウンロードする

サンプルプロジェクトをダウンロードして解凍します。

curl https://resources.learn.liferay.com/examples/liferay-y7g4.zip -O
unzip liferay-y7g4.zip

liferay-y7g4 プロジェクトには、次の2つのモジュールがあります。

  • y7g4-api
  • y7g4-service

APIモジュール(-api)は、パブリックインターフェイスとユーティリティを提供します。 サービスモジュール(-service)は実装を提供します。

APIモジュールを調べる

APIモジュールには、bndメタデータファイルとGradleビルドファイルしかありません。

y7g4-api
 ├── bnd.bnd // Defines the module artifact, package exports, and includes the service XML file
 └── build.gradle // Declares dependencies

bnd.bndファイルは次のとおりです。

Bundle-Name: Acme Y7G4 API
Bundle-SymbolicName: com.acme.y7g4.api
Bundle-Version: 1.0.0
Export-Package:\
	com.acme.y7g4.exception,\
	com.acme.y7g4.model,\
	com.acme.y7g4.service,\
	com.acme.y7g4.service.persistence

Bundle- ヘッダーはモジュールアーティファクトを記述します。 Export-Package ヘッダーは、公開する API パッケージを指定します。 bnd メタデータとその使用方法の詳細については、 モジュール プロジェクト を参照してください。

build.gradle ファイルは、モジュールが DXP/Portal に依存していることを宣言します。

dependencies {
	compileOnly group: "com.liferay.portal", name: "release.dxp.api"
}

サービスモジュールを調べます

サービスモジュールには、bndメタデータファイル、Gradleビルドファイル、およびサービス定義ファイルが含まれています。

y7g4-service
 ├── bnd.bnd // モジュールアーティファクト、データスキーマバージョンなどを定義します
 ├── build.gradle // 依存関係とコード生成パラメータを宣言します
 └── service.xml // モデルとその関係を指定します

bnd.bnd ファイルはこちらです:

Bundle-Name: Acme Y7G4 Service
Bundle-SymbolicName: com.acme.y7g4.service
Bundle-Version: 1.0.0
Liferay-Require-SchemaVersion: 1.0.0
Liferay-Service: true
-dsannotations-options: inherit

繰り返しになりますが、 Bundle- ヘッダーはモジュールアーティファクトを記述します。 サービスメタデータと指示が続きます。

メタデータ説明
Liferay-Require-SchemaVersion: 1.0.0アプリケーションのデータスキーマのバージョン。 データベーススキーマの変更を含むアプリケーションバージョンをリリースする場合は、バージョン番号をインクリメントします。
Liferayサービス: trueこのモジュールはLiferayサービスを提供します。
-dsannotations-options: inheritOSGi サービス コンポーネント クラスは、クラス階層から OSGi 宣言型サービス アノテーションを継承します。 例えば、拡張クラスは、 @Reference アノテーションを介して、祖先フィールドが参照するすべてのサービスにアクセスできます。

build.gradle ファイルはこちらです。

buildService {
	apiDir = "../y7g4-api/src/main/java"
}

dependencies {
	compileOnly group: "com.liferay.portal", name: "release.dxp.api"
	compileOnly project(":y7g4-api")
}

buildService タスクは、 apiDir で指定された API モジュール Java ソース フォルダーにサービスの API クラスを生成します。 サービスモジュールは、DXP/Portal および API モジュール (同名のフォルダ y7g4-api 内) に依存しています。

サービスモデル定義を確認する

service.xml ファイルは、 Y7G4Entry モデルエンティティを定義します。 Service Builder は、 service.xml ファイルの仕様に従って、モデル、永続性、およびサービス クラスを生成します。

service.xml ファイルはこちらです。

<?xml version="1.0"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 7.4.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_7_4_0.dtd">

<service-builder dependency-injector="ds" mvcc-enabled="true" package-path="com.acme.y7g4" short-no-such-exception-enabled="false">
	<namespace>Y7G4</namespace>
	<entity local-service="true" name="Y7G4Entry" remote-service="false">

		<!-- PK フィールド -->

		<column name="y7g4EntryId" primary="true" type="long" />

		<!-- 監査フィールド -->

		<column name="companyId" type="long" />

		<!-- その他のフィールド -->

		<column name="description" type="String" />
		<column name="name" type="String" />
	</entity>
</service-builder>

このファイルは、ID(主キー)、名前、および説明を持つ Y7G4Entry モデルを定義します。

サービスビルダー 要素

service-builder 要素の属性は、 service.xml ファイル内のすべてのモデル エンティティに影響します。

サービスビルダー 属性説明
依存性注入器依存性注入器の型を宣言します。 宣言型サービス (ds) がデフォルトです。
パッケージパス生成されるクラスの先頭パッケージパスを宣言します。
short-no-such-exception-enabledtrueに設定されている場合、 NoSuchY7G4EntryException メッセージではエンティティ名の短縮版を使用します。それ以外の場合は、完全なエンティティ名を使用します。

名前空間 要素

グローバル 名前空間 要素は、すべてのモデルエンティティデータベーステーブルのプレフィックスを指定します。

エンティティ 要素

エンティティ 要素は、モデルデータベースのテーブルとサービスタイプを定義します。

エンティティ 属性説明
名前その団体の名称。 Service Builder は、 [名前空間]_[名前] という命名形式を使用してエンティティ テーブルを生成します (例: Y7G4_Y7G4Entry)。
ローカルサービスが trueの場合、JVM 内から呼び出すサービス クラスを生成します。
リモートサービスが真の場合、JVM の外部から呼び出すための Web サービス クラスを含むサービス クラスを生成します。

列 要素

各 列 要素は、エンティティのテーブル内の列を定義します。 以下は Y7G4Entry エンティティ列の要素です。

カラム説明
y7g4EntryIdモデルインスタンスのID(長整数)と主キー。
名前インスタンスの名前(文字列)。
説明インスタンスの説明(文字列)。

service.xml 要素の詳細については、 Liferay Service Builder DTD を参照してください。

永続化コードを生成する

サービスビルダーを呼び出して、永続化コードとデータベーススクリプトを生成します。

cd liferay-y7g4
./gradlew y7g4-service:buildService

出力:

> タスク :y7g4-service:buildService
Y7G4Entry をビルド中
src/main/java/com/acme/y7g4/service/persistence/impl/Y7G4EntryPersistenceImpl.java を書き込み中
../y7g4-api/src/main/java/com/acme/y7g4/service/persistence/Y7G4EntryPersistence.java を書き込み中
../y7g4-api/src/main/java/com/acme/y7g4/service/persistence/Y7G4EntryUtil.java を書き込み中
src/main/java/com/acme/y7g4/service/persistence/impl/Y7G4EntryModelArgumentsResolver.java を書き込み中
src/main/java/com/acme/y7g4/model/impl/Y7G4EntryModelImpl.java を書き込み中
src/main/java/com/acme/y7g4/model/impl/Y7G4EntryBaseImpl.java を書き込み中
src/main/java/com/acme/y7g4/model/impl/Y7G4EntryImpl.java を書き込み中
書き込み中../y7g4-api/src/main/java/com/acme/y7g4/model/Y7G4EntryModel.java
書き込み中 ../y7g4-api/src/main/java/com/acme/y7g4/model/Y7G4Entry.java
書き込み中 src/main/java/com/acme/y7g4/model/impl/Y7G4EntryCacheModel.java
書き込み中 ../y7g4-api/src/main/java/com/acme/y7g4/model/Y7G4EntryWrapper.java
書き込み中../y7g4-api/src/main/java/com/acme/y7g4/model/Y7G4EntryTable.java
書き込み中 src/main/java/com/acme/y7g4/service/impl/Y7G4EntryLocalServiceImpl.java
書き込み中 src/main/java/com/acme/y7g4/service/base/Y7G4EntryLocalServiceBaseImpl.java
書き込み中 ../y7g4-api/src/main/java/com/acme/y7g4/service/Y7G4EntryLocalService.java
書き込み中../y7g4-api/src/main/java/com/acme/y7g4/service/Y7G4EntryLocalServiceUtil.java
書き込み中 ../y7g4-api/src/main/java/com/acme/y7g4/service/Y7G4EntryLocalServiceWrapper.java
書き込み中 src/main/resources/META-INF/module-hbm.xml
書き込み中 src/main/resources/META-INF/portlet-model-hints.xml
書き込み中../y7g4-api/src/main/java/com/acme/y7g4/exception/NoSuchY7G4EntryException.java
src/main/java/com/acme/y7g4/service/persistence/impl/constants/Y7G4PersistenceConstants.java を書き込み中
src/main/resources/META-INF/sql/tables.sql を書き込み中
src/main/resources/META-INF/sql/tables.sql を書き込み中
src/main/resources/service.properties を書き込み中

ビルド3秒で成功
実行可能なタスク1件:実行済み1件

Service Builderは、モデル、永続化、およびサービス用のJavaクラス、データベーススクリプト、および構成ファイルを生成します。 ファイルパスは、 y7g4-service モジュールからの相対パスです。

生成された構造の概要は以下のとおりです。

liferay-y7g4
├── y7g4-api
│ └── src
│ └── main
│ └── java
│ └── com
│ └── acme
│ └── y7g4
│ ├── exception // 公開例外クラス & インターフェース
│ ├── model // 公開モデルクラス & インターフェース
│ └── service // 公開パーシステンスおよびサービスクラス
│ // & インターフェース
└── y7g4-service
 └── src/main
        ├── java/com/acme/y7g4
        │ ├── model // モデル実装
        │ └── service // 永続化とサービスの実装
        └── resources
            ├── META-INF
            │ ├── module-hbm.xml // Hibernate オブジェクトリレーショナルマップの設定
            │ ├── portlet-model-hints.xml // UI のフィールドタイプ情報を提供
            │ └── sql
            │ ├── indexes.sql
            │ ├── sequences.sql
            │ └── tables.sql
            └── service.properties // サービスのビルドバージョンを追跡します

モデル、永続性、およびサービス実装クラスは、Java パッケージパス com.acme.y7g4 に生成されました。 生成されたクラスの理解と拡張 でクラスについて学びましょう。

SQL スクリプトと永続化構成は resources/META-INF フォルダーに生成されました。

module-hbm.xml ファイルは、Hibernate オブジェクトリレーショナルマップを指定します。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping auto-import="false" default-lazy="false">
    <import class="com.acme.y7g4.model.Y7G4Entry" />
    <class name="com.acme.y7g4.model.impl.Y7G4EntryImpl" table="Y7G4_Y7G4Entry">
        <id access="com.liferay.portal.dao.orm.hibernate.LiferayPropertyAccessor" name="y7g4EntryId" type="long">
            <generator class="assigned" />
        </id>
        <property access="com.liferay.portal.dao.orm.hibernate.LiferayPropertyAccessor" name="description" type="com.liferay.portal.dao.orm.hibernate.StringType" />
        <property access="com.liferay.portal.dao.orm.hibernate.LiferayPropertyAccessor" name="name" type="com.liferay.portal.dao.orm.hibernate.StringType" />
    </class>
</hibernate-mapping>

module-hbm.xml ファイルは、 Y7G4EntryImpl オブジェクトを Y7G4_Y7G4Entry テーブルにマッピングします。 Hibernate を使用したマッピングの詳細については、 Hibernate を参照してください。

tables.sql スクリプトは、 Y7G4_Y7G4Entry テーブルを指定します。

CREATE TABLE Y7G4_Y7G4Entry (
    y7g4EntryId LONG NOT NULL PRIMARY KEY,
    description VARCHAR(75) NULL,
    name VARCHAR(75) NULL
);

y7g4EntryId は主キーです。 name および description は属性です。 モジュールをデプロイすると、DXP/Portal は tables.sql スクリプトを実行してテーブルを作成します。

この service.xml ファイルの要素はインデックスやシーケンスを指定していないため、 indexes.sql または sequences.sql スクリプトは空です。

永続化レイヤーとサービスをデプロイする

生成されたコードをDXPサーバーにデプロイして、永続化レイヤーとサービスを作成する段階に入りました。 サーバーは別の MariaDB データベース サーバー上のデータ ソースを使用します—バンドルされている Hypersonic サーバーよりも MariaDB 上のデータベースを調べる方が簡単です。 すべてをデプロイした後、テーブルを確認し、サービスをテストします。

データベースを作成する

  1. MariaDBのDockerコンテナを起動します。

    docker run --name some-mariadb -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mariadb:10.2
    
  2. MariaDB Dockerコンテナ内からDXPデータベースを作成します。

    データベースサーバーにログインしてください。

    docker exec -it some-mariadb bash -c "/usr/bin/mysql -uroot -pmy-secret-pw"
    

    DXP用のデータベースを作成します。

    データベースdxp_dbを作成し、デフォルトの文字セットをutf8mb4、照合順序をutf8mb4_unicode_ciに設定します。
    

    データベースセッションを終了します。

    やめる
    
  3. デフォルトのネットワーク(ブリッジ)でDockerのnetwork inspectコマンドを実行して、MariaDBコンテナのIPアドレスを取得する。

    docker network inspect bridge
    

    出力例:

    "コンテナ": {
       "162f5350ee9ba7c47c1ba91f54a84543aeada7feb35eb8153743b13ef54cb491": {
          "名前": "some-mariadb",
          "エンドポイントID": "8e97e35fb118e2024a52f2ecbfd40b0a879eba8dc3bc5ffceea8bb117c10bebc"、
          "Macアドレス": "02:42:ac:11:00:02"、
          "IPv4アドレス": "172.17.0.2/16"、
          "IPv6アドレス": ""
       }
    }
    

IPv4Address 値の最初の部分を some-mariadb コンテナに使用します。 例のIPアドレスは 172.17.0.2 です。

サーバーを起動する

別のターミナルで、以下のコマンドを使用してDXPを起動します。 [IP アドレス] を some-mariadb コンテナの IP アドレスに置き換えてください。

docker run -it \
--add-host some-mariadb:[IPアドレス] \
-e LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_JNDI_PERIOD_NAME="" \
-e LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_DRIVER_UPPERCASEC_LASS_UPPERCASEN_AME=org.mariadb.jdbc.Driver \
-e LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_URL="jdbc:mariadb://some-mariadb:3306/dxp_db?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false" \
-e LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_USERNAME=root \
-e LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_PASSWORD=my-secret-pw \
-m 8g \
-p 8080:8080 \
liferay/portal:7.4.2-ga3

モジュールをデプロイする

モジュールをデプロイしてデータベーステーブルを作成し、サービスをインストールします。

./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)

コンソール出力:

com.acme.y7g4.service_1.0.0 [1423] が起動しました
com.acme.y7g4.api_1.0.0 [1422] が起動しました

表を確認してください

データベーステーブルを検証および確認する。

  1. データベースサーバーにログインしてください。

    docker exec -it some-mariadb bash -c "/usr/bin/mysql -uroot -pmy-secret-pw"
    
  2. データベースに接続します。

    dxp_db に接続します。
    
  3. Y7G4_Y7G4Entry テーブルを確認するために、データベーステーブルを一覧表示します。

    テーブルを表示する。
    

    結果:

    +--------------------------------+
    | Tables_in_dxp_db |
    +--------------------------------++
    | AMImageEntry |
    | AccountEntry |
    | AccountEntryOrganizationRel |
    | ... |
    | Y7G4_Y7G4Entry |
    +--------------------------------+
    
  4. Y7G4_Y7G4Entry テーブルの列を一覧表示します。

    Y7G4_Y7G4Entry の列を表示します。
    

    結果:

    +-------------+-------------+------+-----+---------+-------+
    | フィールド | タイプ | Null | キー | デフォルト | 追加 |
    +-------------+-------------+------+-----+---------+-------+
    | y7g4EntryId | bigint(20) | NO | PRI | NULL | |
    | description | varchar(75) | YES | | NULL | |
    | name | varchar(75) | YES | | NULL | |
    +-------------+-------------+------+-----+---------+-------+
    

    すべてが揃っています。

  5. データベースセッションを終了します。

    やめる
    

サービスをテストする

サービスを呼び出して、データベースに Y7G4Entry データを入力します。

  1. ブラウザでDXPにアクセスします(http://localhost:8080)。

  2. デフォルトの認証情報を使用してサインインします。

    ユーザー名: test@liferay.com

    パスワード: テスト

  3. コントロール パネル → サーバー管理 → スクリプト の順に移動して、スクリプト コンソールを開きます。

  4. 以下のスクリプトを実行してエントリを追加してください。

    import com.acme.y7g4.service.Y7G4EntryLocalServiceUtil;
    
    import com.liferay.portal.kernel.dao.orm.QueryUtil;
    
    entry = Y7G4EntryLocalServiceUtil.createY7G4Entry(1234);
    
    entry.setName("床をモップがけする");
    entry.setDescription("キッチンとバスルームの床を石鹸と水でモップがけします。");
    
    Y7G4EntryLocalServiceUtil.addY7G4Entry(entry);
    
    entries = Y7G4EntryLocalServiceUtil.getY7G4Entries(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
    
    for (entry in entries){
       out.println(entry);
    }
    

    出力:

    {y7g4EntryId=1234, description=台所と浴室の床を石鹸と水で拭きます。, name=床を拭く}
    

    新しく追加されたY7G4EntryはJSON形式で印刷されます。

スクリプトが実行した内容は以下のとおりです。

  1. 生成された静的ユーティリティクラス Y7G4EntryLocalServiceUtil をインポートしました。
  2. ID(long)1234でY7G4Entryインスタンスを作成しました。
  3. Y7G4Entryインスタンスのnameとdescriptionの属性を入力しました。
  4. Y7G4Entryをデータベースに追加しました。
  5. データベースからすべてのY7G4Entryインスタンスを取得し、それらを印刷しました。

次は?

モデルの定義方法、およびそれに対応する永続化コードとサービスコードの生成方法がわかったので、生成されたサービス クラスを調べてみましょう。 生成されたクラスの理解と拡張 に進んでください。