カスタム通知タイプの実装
Liferay Commerceは、ストアの様々なイベントトリガーに対してメール通知を送信するように設定することができます。 ニーズに合う、すぐに使える通知トリガーがない場合、自分で実装することができます。
新しい通知タイプを追加するには、CommerceNotificationTypeインターフェイスを実装する必要があります。 通知テンプレートを設定し、使用可能な OOTB タイプを表示する方法については、 電子メールの送信 を参照してください。
このチュートリアルでは、Minium デモ サイト初期化子を使用します。
通知タイプの概要
通知はチャネルに範囲設定されています。 チャンネル設定の下に新しい通知テンプレートを作成することができ、通知タイプに基づいてトリガーされます。

上の図は、G2F3 Shipment Createdというタイプの通知テンプレートを示しています。 これは、新しい出荷の作成のためにトリガーされます。 出荷の作成中、通知テンプレートに記載されているように、受信者/受信者に通知が送信されます。 テンプレートの宛先、件名、本文フィールドにワイルドカードを使用することができ、これらは送信前に解決されます。
通知タイプのデプロイと言語キーの追加
新しいLiferay DXPインスタンスを起動し、以下を実行します。
docker run -it -m 8g -p 8080:8080 liferay/dxp:2025.q1.6-lts
メールアドレス test@liferay.com とパスワード testを使用して、 http://localhost:8080 で Liferay にサインインします。 プロンプトが表示されたら、パスワードを learnに変更します。
次に、以下の手順に従います。
-
Acme Commerce Notification Typeをダウンロードして解凍します。
curl https://resources.learn.liferay.com/commerce/latest/en/developer-guide/order-management/liferay-g2f3.zip -O unzip liferay-g2f3.zip -
サンプルをビルドしてデプロイします。
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)注このコマンドは、デプロイされたjarをDockerコンテナ上の
/opt/liferay/osgi/modulesにコピーするのと同じです。 -
Dockerコンテナコンソールでデプロイを確認します。
STARTED com.acme.g2f3.impl_1.0.0 -
管理者としてログインし、 グローバル メニュー (
) を開き、 コントロール パネル → サイトをクリックして、新しい Minium Demo サイトを追加します。 -
サイトを作成したら、 グローバル メニュー (
) を再度開き、 コントロール パネル → 言語の上書きに移動します。 追加 (
) をクリックし、次のキーを追加します。言語キー 値 g2f3-shipment-created G2F3 作成された出荷 g2f3-shipment-creator-name-definition-term 注文を作成したアカウント名 g2f3-order-shipping-address-definition-term 配送先 g2f3-shipment-id-definition-term 出荷ID g2f3-shipment-creator-email-definition-term 出荷を作成したユーザーのメール 重要Liferay DXP 7.4 U4以降、またはLiferay Portal 7.4 GA8以降の言語オーバーライドツールで言語キーを追加することができます。 以前のバージョンでは、ビルドとデプロイの前に、キーを含む
Language.propertiesファイルを/src/main/resources/content/の下に追加する必要があります。 -
次に、 グローバル メニュー (
) を開き、 コマース → チャネルに移動します。 -
最小 を選択し、 通知テンプレートに移動します。
-
新しいテンプレートを作成するには、 追加 (
) をクリックします。名前: テスト G2F3 出荷が作成されました
タイプ: G2F3 出荷が作成されました
宛先: [%SHIPMENT_CREATOR_EMAIL%]
送信元アドレス: test@liferay.com
送信者名: 管理者
件名: 新しい出荷が作成されました - 出荷ID: [%SHIPMENT_ID%]
本文:
こんにちは、
[%SHIPMENT_CREATOR_NAME%] によって新しい出荷が作成されました
配送先住所: [%ORDER_SHIPPING_ADDRESS%]
ありがとう、
管理者
-
[保存]をクリックします。
-
ログアウトして購入者としてログインし、ストアで新しい注文を行ってください。
-
ログアウトして管理者として再度ログインし、 グローバル メニュー (
) を開いて、 コマース → 注文に移動します。 -
注文を選択し、 「注文を承諾」をクリックします。 次に、 「出荷の作成」をクリックします。
-
受信通知を受信トレイで確認してください。
MockMock (https://github.com/tweakers/MockMock) のような偽の SMTP サーバーを使用して、ローカル開発環境でこれらの通知をテストできます。 portal-ext.properties ファイルに次の行を追加します: mail.send.blacklist=noreply@liferay.com, noreply@domain.invalid, test@domain.invalid。 java -jar MockMock.jar を使用して jar を実行し、受信したメールが localhost:8282 にあるかどうかを確認します。
カスタム通知タイプの仕組み
この例は 6 つの主なステップで構成されています。 最初に、OSGi登録用にクラスに注釈を付ける必要があります。 次に、 CommerceNotificationType インターフェースを確認します。 次に、カスタムのCommerceNotificationTypeの実装を終了します。
その後、ModelListenerをCommerceShipmentクラスに対して作成します。 次に、CommerceDefinitionTermContributorインターフェイスを確認します。 最後に、新しい通知のワイルドカードを解決するために、用語コントリビューターを実装します。
- OSGi登録用にクラスに注釈を付ける
- CommerceNotificationTypeインターフェースの確認
- 通知タイプの完了
- CommerceShipmentのModelListenerを作成します。
- CommerceDefinitionTermContributorインターフェースの確認
- 用語コントリビューターを完成する
OSGi登録用にクラスに注釈を付ける
Liferay Commerceが通知ステータスレジストリ内の他のものと区別できるように、通知タイプに個別のキーを指定する必要があります。 すでに使用されているキーを指定すると、既存の関連付けられているタイプが上書きされます。 順番は、ドロップダウンでのソート順で決まります。 この場合、注文は出荷待ち通知タイプは50、 一部発送済み通知タイプは60として注文を持ちます。 2つの間にステータスを配置するには、注文がこれら2つの数値の間にある必要があります(この場合は51)。
CommerceNotificationTypeインターフェースの確認
次のメソッドを実装します。
public String getClassName(Object object);
このメソッドは、通知タイプが実装されているクラスの名前を返します。
public long getClassPK(Object object);
このメソッドは、オブジェクトのプライマリーキーを返します。
public String getKey();
このメソッドは、通知タイプのユニークキーを返します。 既存のキーを使用すると、その通知タイプが上書きされます。
public String getLabel(Locale locale);
このメソッドは、UIに表示される通知タイプの名前を返します。 この名前は、言語キーまたは文字列です。
通知タイプを完了する
@Override
public String getClassName(Object object) {
if (!(object instanceof CommerceShipment)) {
return null;
}
return CommerceShipment.class.getName();
}
@Override
public long getClassPK(Object object) {
if (!(object instanceof CommerceShipment)) {
return 0;
}
CommerceShipment commerceShipment = (CommerceShipment)object;
return commerceShipment.getPrimaryKey();
}
@Override
public String getKey() {
return "g2f3";
}
@Override
public String getLabel(Locale locale) {
return LanguageUtil.get(locale, "g2f3-shipment-created");
}
通知タイプの実装を完了するには、上記のメソッドを実装する必要があります。 最初のメソッドでは、オブジェクトが CommerceShipment タイプであるかどうかを確認し、それがtrue の場合はそのクラス名を返します。 2 番目の方法では、これを再度確認し、それが真であれば出荷の主キーを返します。 3番目のメソッドはユニークキーを返し、最後のメソッドはUIに表示されるラベルを返します。
CommerceShipmentのModelListenerの作成
@Component(service = ModelListener.class)
public class G2F3CommerceShipmentModelListener
extends BaseModelListener<CommerceShipment> {
@Override
public void onAfterCreate(CommerceShipment commerceShipment)
throws ModelListenerException {
try {
_commerceNotificationHelper.sendNotifications(
commerceShipment.getGroupId(), commerceShipment.getUserId(),
"g2f3", commerceShipment);
}
catch (PortalException portalException) {
if (_log.isDebugEnabled()) {
_log.debug(portalException);
}
}
}
private static final Log _log = LogFactoryUtil.getLog(
G2F3CommerceShipmentModelListener.class);
@Reference
private CommerceNotificationHelper _commerceNotificationHelper;
}
出荷が作成されるたびに通知をトリガーするには、 BaseModelListener インターフェースを実装する ModelListener クラスを拡張する必要があります。 このインタフェースは、作成、アップデート、削除などのイベントをトリガーとするエンティティのメソッドを持ちます。 onAfterCreate(T model)メソッドを使用すると、出荷の作成時に通知をトリガーすることができます。
CommerceDefinitionTermContributorインターフェースの確認
次のメソッドを実装します。
public String getFilledTerm(String term, Object object, Locale locale) throws PortalException;
このメソッドは、ワイルドカードを適切な値に置き換え、それを文字列として返す。
public String getLabel(String term, Locale locale);
このメソッドは、UIに表示される用語コントリビューターの名前を返します。 この名前は、言語キーまたは文字列です。
public List<String> getTerms();
このメソッドは、通知タイプで利用可能なすべての用語コントリビュータを返します。
用語コントリビューターを完成する
用語コントリビューターは、宛先、件名、本文フィールドに存在するワイルドカードを解決します。 この例では、件名と本文フィールド、および宛先フィールドの2つの用語コントリビューターが実装されています。
本文と件名にgetFilledTermメソッドを実装する
@Override
public String getFilledTerm(String term, Object object, Locale locale)
throws PortalException {
if (!(object instanceof CommerceShipment)) {
return term;
}
CommerceShipment commerceShipment = (CommerceShipment)object;
if (term.equals(_SHIPMENT_CREATOR_NAME)) {
AccountEntry accountEntry = commerceShipment.getAccountEntry();
if (accountEntry.isPersonalAccount()) {
User user = _userLocalService.getUser(accountEntry.getUserId());
return user.getFullName(true, true);
}
return accountEntry.getName();
}
if (term.equals(_ORDER_SHIPPING_ADDRESS)) {
CommerceAddress commerceAddress =
commerceShipment.fetchCommerceAddress();
return commerceAddress.getStreet1() + ", " +
commerceAddress.getCity() + ", " + commerceAddress.getZip();
}
if (term.equals(_SHIPMENT_ID)) {
if (commerceShipment == null) {
return term;
}
return String.valueOf(commerceShipment.getCommerceShipmentId());
}
return term;
}
ワイルドカードを解決する前に、オブジェクトがヌルであるか、またはCommerceShipment型であるかを確認するためのチェックがあります。 次に、用語にワイルドカードが含まれている場合、ワイルドカードは出荷作成者の名前、出荷先住所、または出荷 ID に置き換えられます。 出荷作成者の名前には、出荷のアカウントの名前が返されます。 配送先住所は、住所(丁目、番地など)、市町村、郵便番号を連結した文字列として返されます。 出荷IDは、出荷オブジェクトから直接返されます。
受信者のgetFilledTermメソッドを実装する
@Override
public String getFilledTerm(String term, Object object, Locale locale)
throws PortalException {
if (!(object instanceof CommerceShipment)) {
return term;
}
CommerceShipment commerceShipment = (CommerceShipment)object;
if (commerceShipment == null) {
return term;
}
if (term.equals(_SHIPMENT_CREATOR_EMAIL)) {
AccountEntry accountEntry = commerceShipment.getAccountEntry();
if (accountEntry.isPersonalAccount()) {
User user = _userLocalService.getUser(accountEntry.getUserId());
return String.valueOf(user.getUserId());
}
return String.valueOf(commerceShipment.getUserId());
}
return term;
}
ワイルドカードを解決する前に、オブジェクトがヌルであるか、またはCommerceShipment型であるかを確認するためのチェックがあります。 そして、その用語にワイルドカードが含まれている場合、ワイルドカードはアカウントのユーザーIDに置き換えられます。 通知が送信されると、この ID を使用してユーザーのメール アドレスが検索されます。
getLabel メソッドと getTerms メソッドを実装する
getLabelメソッドは、UIに表示される用語の名前を返します。 言語キーを使ってこれを行うか、直接文字列を返すことができます。
@Override
public String getLabel(String term, Locale locale) {
return LanguageUtil.get(locale, _languageKeys.get(term));
}
このメソッドは、通知タイプで利用可能なすべての用語コントリビュータを返します。 言語キーを使ってこれを行うか、UIに用語を表示するハードコードされた文字列を直接返すことができます。
@Override
public List<String> getTerms() {
return new ArrayList<>(_languageKeys.keySet());
}
さいごに
CommerceNotificationTypeインターフェイスを実装するための基本がわかりましたね。 また、通知の仕組みの基本や、独自の通知タイプを送信するための MessageListenerの使い方もおわかりだと思います。