フォームストレージアダプターの書き込み
利用可能: LPS-97208 の修正(Liferay DXP 7.2 SP3で計画)を含むLiferay DXP 7.3およびLiferay DXP 7.2バージョン。
デフォルトでは、フォームはLiferay DXPのデータベースにJSONとして保存されます。 この例では、フォームレコードの永続化イベントにカスタムロジックを挿入するために、新しいストレージアダプターを実装する方法を紹介します。
まず デフォルトストレージアダプタ がどのように Liferay DXP データベースのフォームレコードを JSON コンテンツとして保存するか見てみましょう。 そして、各フォームレコードをファイルシステムに保存するロジックを追加します。
実行中のDDMストレージアダプターを調べる
ストレージアダプターの動作を確認するために、サンプルをデプロイし、サンプルアダプターを使用していくつかのフォームデータを追加します。
サンプルをデプロイする
新しい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 に変更します。
次に、以下の手順を実行します。
-
DDM Storage Adapter プロジェクト をダウンロードして解凍します。
curl https://resources.learn.liferay.com/dxp/latest/en/process-automation/forms/developer-guide/liferay-r2f1.zip -O
unzip liferay-r2f1.zip
-
モジュールのルートから、ビルドおよびデプロイします。
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
tipこのコマンドは、デプロイされたjarをDockerコンテナの/opt/liferay/osgi/modulesにコピーするのと同じです。
-
Liferay Dockerコンテナコンソールでデプロイを確認します。
STARTED com.acme.r2f1.impl_1.0.0 [1009]
デプロイされたストレージアダプターを使用する
-
ブラウザでhttp://localhost:8080を開きます。
-
[サイトメニュー] → [コンテンツ & データ] → [フォーム] のフォームアプリケーションに移動します。
-
追加 ボタン()をクリックして、フォームビルダーを開きます。
-
[フォームビルダー]ビューで、 オプション ボタン()をクリックし、 [Settings] ウィンドウを開きます。
-
[ストレージの種類を選択する] で、 [R2F1 Dynamic Data Mapping Storage Adapter] タイプを選択し、 [Done] をクリックします。
-
フォームにテキストフィールドを追加し、フォームを公開して、何度か送信します。
-
フォームデータが保持されていることを確認するには、フォームのレコードに移動します。
[サイトメニュー] → [コンテンツ] → [フォーム] から、フォームの アクション ボタン()をクリックして、 [エントリの参照] をクリックします。
-
さらに、各CRUDメソッドにロギングが提供され、サンプルのメソッドが呼び出されていることが示されています。
WARN [http-nio-8080-exec-5][R2F1DDMStorageAdapter:82] Acme storage adapter's save method was invoked
拡張ポイントを理解する
この例には、R2F1DDMStorageAdapter
という1つのクラスのみが含まれています。これは、フォームエントリーを格納するためのロジックを提供するDDMStorageAdapter
を実装しているサービスです。 配置されたサンプルは現在、デフォルトの JSON 実装をラップしているだけです: DefaultDDMStorageAdapter
. 後で、すでにここにあるコードにファイルシステムのストレージを追加します。
アダプタークラスをOSGiコンテナに登録する
DDMFileSystemStorageAdapter
は、DDMStorageAdapter
インターフェイスを実装していますが、OSGiサービスとして登録する必要があります。
@Component(
property = "ddm.storage.adapter.type=r2f1-ddm-storage-adapter",
service = DDMStorageAdapter.class
)
public class R2F1DDMStorageAdapter implements DDMStorageAdapter {
r2f1-ddm-storage-adapter
キーは、src/main/resources/content/Language.properties
ファイルとbnd.bnd
内のProvide-Capability
ヘッダーによって、R2F1 Dynamic Data Mapping Storage Adapter
という値にローカライズされます。
service
コンポーネントプロパティは、実装をDDMStorageAdapter
サービスとして登録します。
プロパティddm.storage.adapter.type
は識別子を提供し、サービスが一意のDDMStorageAdapter
の実装として登録されるようにします。 他のサービスでも次のように参照できるようになりました。
@Reference(target = "(ddm.storage.adapter.type=r2f1-ddm-storage-adapter)")
private DDMStorageAdapter defaultWrapperDDMStorageAdapter;
DDMStorageAdapterインターフェイスを理解する
このインターフェイスでは、フォームレコードのCRUD操作を処理するために、delete
、get
、save
の3つのメソッドが必要です(更新ロジックも処理します)。
public DDMStorageAdapterDeleteResponse delete(
DDMStorageAdapterDeleteRequest ddmStorageAdapterDeleteRequest)
throws StorageException;
public DDMStorageAdapterGetResponse get(
DDMStorageAdapterGetRequest ddmStorageAdapterGetRequest)
throws StorageException;
public DDMStorageAdapterSaveResponse save(
DDMStorageAdapterSaveRequest ddmStorageAdapterSaveRequest)
throws StorageException;
各メソッドは DDMStorageAdapter[ Save / Get / Delete ]Response オブジェクトを返す必要があり、静的なインナー Builder
クラスの newBuilder
メソッドを使用して構築されます。
すべてのメソッドにDDMStorageAdapter[Save/Delete/Get]Request
が渡されます。 リクエストオブジェクトには、有用なコンテキスト情報を返すgetterメソッドが含まれています。
ファイルシステムストレージを実装する
この例では、必要なメソッドをすでに上書きしています。 機能性を考慮したプライベートのユーティリティーメソッドを作成し、上書きされたメソッドからそれらを呼び出します。
サービスの依存関係を宣言する
このコードは、OSGiコンテナにデプロイされた2つのサービスに依存しています。 org.osgi.service.component.annotations.Reference
によって提供されるDeclarative Services @Reference
アノテーションを使用して、クラスの最後にこれらの宣言を追加します。
@Reference
private DDMContentLocalService _ddmContentLocalService;
@Reference
private DDMFormValuesSerializerTracker _ddmFormValuesSerializerTracker;
com.liferay.dynamic.data.mapping.service.DDMContentLocalService
およびcom.liferay.dynamic.data.mapping.io.DDMFormValuesSerializerTracker
をインポートします。
ロガーを作成する
クラスのロガーを作成し、_log
変数に設定します。
private static final Log _log = LogFactoryUtil.getLog(
R2F1DDMStorageAdapter.class);
これは、CRUDメソッドの1つが呼び出されるたびに、いくつかのログメッセージを追加するために使用されます。
ファイル削除を実装する
-
プライベート変数
_PATHNAME
を設定することで、ファイルの保存先をコントロールすることができます。 ここでのパスは、Dockerコンテナ内のLiferayのインストール場所を指しています。private static final String _PATHNAME = "/opt/liferay/form-records";
-
_deleteFile
ユーティリティメソッドを作成します(java.io.File
クラスをインポート)。private void _deleteFile(long fileId) { File file = new File(_PATHNAME + "/" + fileId); file.delete(); if (_log.isWarnEnabled()) { _log.warn("Deleted file with the ID " + fileId); } }
-
上書きされた
delete
メソッドを探します。return
ステートメントの直前に以下を追加します。long fileId = ddmStorageAdapterDeleteRequest.getPrimaryKey(); _deleteFile(fileId);
これで、このコードは、データベース内のコピーを削除する前に、まずファイルシステムからファイルを削除します。
ファイル取得を実装する
get
メソッドと同じ手順で、プライベートのユーティリティメソッドを作成し、それを呼び出します。
-
_getFile
ユーティリティメソッドを追加します。private void _getFile(long fileId) throws IOException { try { if (_log.isWarnEnabled()) { _log.warn( "Reading the file with the ID " + fileId + ": " + FileUtil.read(_PATHNAME + "/" + fileId)); } } catch (IOException e) { throw new IOException(e); } }
com.liferay.portal.kernel.util.FileUtil
およびjava.io.IOException
をインポートします。 -
上書きされた
get
メソッド(try
ブロック内)で、return
ステートメントの直前に以下を挿入し、storageId
(ddmStorageAdapterGetRequest.getPrimaryKey()
で取得)をfileId
として設定し、取得したコンテンツをLiferayのログに出力する_getFile
ユーティリティメソッドを呼び出します。long fileId = ddmStorageAdapterGetRequest.getPrimaryKey(); _getFile(fileId);
ファイル作成ロジックを実装する
保存リクエストには、新しいレコードが追加される場合と既存のレコードが更新される場合の2つのタイプがあります。 保存するたびに、現在のddmFormValues
コンテンツを使用して、update
メソッドで既存のファイルを上書きします。
-
_saveFile
ユーティリティメソッドを作成します。private void _saveFile(long fileId, DDMFormValues formValues) throws IOException { try { String serializedDDMFormValues = _serialize(formValues); File abstractFile = new File(String.valueOf(fileId)); FileUtil.write( _PATHNAME, abstractFile.getName(), serializedDDMFormValues); if (_log.isWarnEnabled()) { _log.warn("Saved a file with the ID" + fileId); } } catch (IOException e) { throw new IOException(e); } }
com.liferay.dynamic.data.mapping.storage.DDMFormValues
およびjava.io.File
をインポートします。 -
_serialize
ユーティリティメソッドを作成し、DDMFormValues
オブジェクトをJSONに変換します。private String _serialize(DDMFormValues ddmFormValues) { DDMFormValuesSerializer ddmFormValuesSerializer = _ddmFormValuesSerializerTracker.getDDMFormValuesSerializer("json"); DDMFormValuesSerializerSerializeRequest.Builder builder = DDMFormValuesSerializerSerializeRequest.Builder.newBuilder( ddmFormValues); DDMFormValuesSerializerSerializeResponse ddmFormValuesSerializerSerializeResponse = ddmFormValuesSerializer.serialize(builder.build()); return ddmFormValuesSerializerSerializeResponse.getContent(); }
com.liferay.dynamic.data.mapping.io.DDMFormValuesSerializer
、com.liferay.dynamic.data.mapping.io.DDMFormValuesSerializerSerializeRequest
、およびcom.liferay.dynamic.data.mapping.io.DDMFormValuesSerializerSerializeResponse
をインポートします。 -
このロジックと
_saveFile
への呼び出しを、既存のreturn
ステートメントを置き換えてsave
メソッドに追加します。DDMStorageAdapterSaveResponse defaultStorageAdapterSaveResponse = _defaultStorageAdapter.save(ddmStorageAdapterSaveRequest); long fileId = defaultStorageAdapterSaveResponse.getPrimaryKey(); _saveFile(fileId, ddmStorageAdapterSaveRequest.getDDMFormValues()); return defaultStorageAdapterSaveResponse;
_defaultStorageAdapter.save
が最初にコールされ、新しいフォーム項目に主キーが作成されます。 このプライマリーキーは、fielId
を作成するためにResponse
オブジェクトから取得されます。
ストレージアダプターをデプロイしてテストする
先ほどと同じdeploy
コマンドを使用してストレージアダプターをデプロイします。 モジュールルートから、以下を実行します。
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
以下のように動作を確認します。
-
サイトメニュー → コンテンツ → フォーム にあるフォームアプリケーションにアクセスします。
-
追加 ボタンをクリックして、フォームビルダーを開きます。
-
[フォームビルダー]ビューで、 オプション ボタン()をクリックし、 [Settings] ウィンドウを開きます。
-
リストを選択フィールド [ストレージの種類を選択する] から、 [R2F1 Dynamic Data Mapping Storage Adapter] タイプを選択し、 [完了] をクリックします。
-
フォームにテキストフィールドを追加し、フォームを公開して、何度か送信します。
-
フォームレコードがコンテナのファイルシステムに書き込まれたことを確認するには、ログを確認します。 以下のようなメッセージが表示されます。
WARN [http-nio-8080-exec-5][R2F1DDMStorageAdapter:82] Acme storage adapter's save method was invoked WARN [http-nio-8080-exec-5][R2F1DDMStorageAdapter:134] Saved a file with the ID42088 WARN [http-nio-8080-exec-5][R2F1DDMStorageAdapter:61] Acme storage adapter's get method was invoked WARN [http-nio-8080-exec-5][R2F1DDMStorageAdapter:112] Reading the file with the ID 42088: {"availableLanguageIds":["en_US"],"defaultLanguageId":"en_US","fieldValues":[{"instanceId":"EJ5UglA1","name":"Field51665758","value":{"en_US":"Stretched limousine"}}]}
まとめ
DDMStorageAdapter
を実装することで、フォームレコードを任意のストレージ形式で保存することができます。