カスタム通知タイプの実装
Liferay Commerceは、ストアの様々なイベントトリガーに対してメール通知を送信するように設定することができます。 ニーズに合う、すぐに使える通知トリガーがない場合、自分で実装することができます。
新しい通知タイプを追加するには、CommerceNotificationType
インターフェイスを実装する必要があります。 メール送信 を参照して、通知テンプレートの設定方法と利用可能な OOTB タイプを確認します。
通知タイプの概要
通知はチャネルに範囲設定されています。 チャンネル設定の下に新しい通知テンプレートを作成することができ、通知タイプに基づいてトリガーされます。
上の図は、 G2F3 Shipment Created というタイプの通知テンプレートを示しています。 これは、新しい出荷の作成のためにトリガーされます。 出荷の作成中、通知テンプレートに記載されているように、受信者/受信者に通知が送信されます。 テンプレートの宛先、件名、本文フィールドにワイルドカードを使用することができ、これらは送信前に解決されます。
通知タイプのデプロイと言語キーの追加
新しいLiferay DXPインスタンスを起動し、以下を実行します。
docker run -it -m 8g -p 8080:8080 liferay/dxp:2024.q2.11。
メールアドレス test@liferay.com とパスワード test を使用して、http://localhost:8080でLiferayにサインインしてください。 プロンプトが表示されたら、パスワードを learn に変更します。
次に、以下の手順に従います:
-
アクメ商会通知型をダウンロードし、解凍します。
curl https://resources.learn.liferay.com/commerce/latest/en/developer-guide/order-management/liferay-g2f3.zip unzip liferay-g2f3.zip
-
サンプルをビルドしてデプロイします。
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
Noteこのコマンドは、デプロイされたjarをDockerコンテナの
/opt/liferay/osgi/modules
にコピーするのと同じです。 -
Dockerコンテナコンソールでデプロイを確認します。
STARTED com.acme.g2f3.impl_1.0.0
-
管理者としてログインし、 グローバルメニュー() を開き、 [コントロールパネル] → [言語オーバーライド] をクリックしてください。 追加 ボタン () をクリックし、以下のキーを追加します。
言語キー 値 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 出荷を作成したユーザーのメール ImportantLiferay DXP 7.4 U4以降、またはLiferay Portal 7.4 GA8以降の言語オーバーライド ツールで言語キーを追加することができます。 以前のバージョンでは、ビルドとデプロイの前に、
/src/main/resources/content/
の下にLanguage.properties
ファイルを追加し、キーを指定する必要があります。 -
グローバルメニュー() を開き、 [コマース] → [チャネル] をクリックし、 [通知テンプレート] を選択します。
-
追加 ボタン () を使用して、新しいテンプレートを作成します。
名前: 作成されたG2F3出荷テスト
タイプ: 作成されたG2F3出荷
宛先:[%SHIPMENT_CREATOR_EMAIL%]
送信者メールアドレス: test@liferay.com
送信者名: 管理者
件名: 作成された新しい出荷 - 出荷ID: [%SHIPMENT_ID%]
Body:
Hi,
[%SHIPMENT_CREATOR_NAME%]によって、新しい出荷が作成されました
配送先住所: [%ORDER_SHIPPING_ADDRESS%]
ありがとうございます。
管理者
-
[保存]をクリックします。
-
グローバルメニュー() を開き、 [コントロールパネル] → [サイト] をクリックし、新しいMiniumデモサイトを追加してください。
-
購入者としてログインし、ストアで新しく注文をします。
-
管理者としてログアウトしてログインし直し、 グローバルメニュー を開いて、 [コマース] → [注文] をクリックします。
-
注文を選択し、 [受注] をクリックします。 次に、 [出荷を作成] をクリックします。
-
受信通知を受信トレイで確認してください。
MockMock などの偽のSMTPサーバを使って、ローカル開発環境下でこれらの通知をテストすることができます。 Portal-ext.properties
ファイルに以下の行を追加します。mail.send.blacklist=noreply@liferay.com, noreply@domain.invalid, test@domain.invalid
. java -jar MockMock.jar
でjarを実行し、受信したメールを localhost:8282
でチェックします。
カスタム通知タイプの仕組み
この例は、主に7つのステップで構成されています。 最初に、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
のタイプであるかどうかをチェックし、それが真であればそのクラス名を返すようになっています。 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;
}
出荷が作成される度に通知をトリガーするためには、 ModelListener
インターフェースを実装する BaseModelListener
クラスを拡張する必要があります。 このインタフェースは、作成、アップデート、削除などのイベントをトリガーとするエンティティのメソッドを持ちます。 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
の使い方もおわかりだと思います。