tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:Platform Eventsを試してみました

Trailheadを見ながらPlatform Eventsの機能を試してみました。

Platform Eventsの作成

設定で「Platform Events」と検索。New Platform Eventボタンをクリックします。
f:id:tyoshikawa1106:20170717171844p:plain


ラベルや説明項目を入力します。
f:id:tyoshikawa1106:20170717172939p:plain


拡張子は__eとなりました。
f:id:tyoshikawa1106:20170717173013p:plain


検証用に下記項目を作成します。(詳細はTrailheadを確認のこと)
f:id:tyoshikawa1106:20170717173624p:plain

ReplayIdシステムのフィールドとイベントの保持

Salesforceはプラットフォームイベントを24時間保存します。Apexではなく、APIクライアントで保存されたイベントを取得できます。各イベントレコードには、ReplayIDというフィールドが含まれています。このフィールドは、イベントが発行された後にシステムに取り込まれます。各リプレイIDは、前のイベントのIDよりも高いことが保証されていますが、連続するイベントでは必ずしも連続している必要はありません。格納されているすべてのイベントを取得することも、取得したイベントのベースラインとしてイベントのリプレイIDを指定することもできます。

Salesforceはイベントレコードを一時的に保持していますが、SOQLまたはSOSLを使用してイベントレコードを照会することはできません。同様に、レポート、リストビュー、および検索のユーザーインターフェイスでイベントレコードを使用することはできません。CometDを購読し、ReplayIdオプションを使用している場合にのみ、過去のイベントを取得できます。次のユニットのイベントを購読する方法を示します。

イベントを公開する

アプリケーションがSalesforceプラットフォームにある場合は、Apexメソッドを使用するか、Process BuilderやCloud Flow Designerなどの宣言ツールを使用してイベントをパブリッシュできます。アプリが外部アプリの場合、Salesforce APIを使用してイベントを公開できます。

Apexを使用してイベントメッセージを発行する

設定画面でPlatform Eventsを作成後はApexで処理を行えばいいみたいです。

// Create an instance of the event and store it in the newsEvent variable
Cloud_News__e newsEvent = new Cloud_News__e(
           Location__c='Mountain City', 
           Urgent__c=true, 
           News_Content__c='Lake Road is closed due to mudslides.');

// Call method to publish events
Database.SaveResult sr = EventBus.publish(newsEvent);

// Inspect publishing result 
if (sr.isSuccess()) {
    System.debug('Successfully published event.');
} else {
    for(Database.Error err : sr.getErrors()) {
        System.debug('Error returned: ' +
                     err.getStatusCode() +
                     ' - ' +
                     err.getMessage());
    }
}
複数のイベントを公開する場合はこちら
// List to hold event objects to be published.
List<Cloud_News__e> newsEventList = new List<Cloud_News__e>();
// Create event objects.
Cloud_News__e newsEvent1 = new Cloud_News__e(
           Location__c='Mountain City', 
           Urgent__c=true, 
           News_Content__c='Lake Road is closed due to mudslides.');
Cloud_News__e newsEvent2 = new Cloud_News__e(
           Location__c='Mountain City', 
           Urgent__c=false, 
           News_Content__c='Small incident on Goat Lane causing traffic.');
// Add event objects to the list.
newsEventList.add(newsEvent1);
newsEventList.add(newsEvent2);

// Call method to publish events.
List<Database.SaveResult> results = EventBus.publish(newsEventList);

// Inspect publishing result for each event
for (Database.SaveResult sr : results) {
    if (sr.isSuccess()) {
        System.debug('Successfully published event.');
    } else {
        for(Database.Error err : sr.getErrors()) {
            System.debug('Error returned: ' +
                        err.getStatusCode() +
                        ' - ' +
                        err.getMessage());
        }
    }       
}
プロセスビルダーをつかった公開

f:id:tyoshikawa1106:20170717204911p:plain

Salesforce APIを使用してイベントメッセージを公開

sObject RESTエンドポイント:

/services/data/v40.0/sobjects/Cloud_News__e/

POSTリクエストの本文をリクエストする:

{
   "Location__c" : "Mountain City",
   "Urgent__c" : true,
   "News_Content__c" : "Lake Road is closed due to mudslides."
}

プラットフォーム・イベント・レコードが作成されると、REST応答はこの出力のようになります。ヘッダーは簡潔にするために削除されます。

HTTP/1.1 201 Created 

{   
   "id" : "e00xx000000000B",
   "success" : true,
   "errors" : [ ],
   "warnings" : [ ] 
}

Apexから実行

試しにApexから実行してみました。
f:id:tyoshikawa1106:20170717205910p:plain


結果はこちら
f:id:tyoshikawa1106:20170717205952p:plain


ひとまず正常にPlatform Eventsを公開できました。

Platform Eventsの購読

Apexトリガをつかって通知を確認するそうです。

// Trigger for listening to Cloud_News events.
trigger CloudNewsTrigger on Cloud_News__e (after insert) {    
    System.debug('Apex Trigger Go!');
    // List to hold all cases to be created.
    List<Case> cases = new List<Case>();
    
    // Get queue Id for case owner
    //Group queue = [SELECT Id FROM Group WHERE Name='Regional Dispatch' LIMIT 1];
       
    // Iterate through each notification.
    for (Cloud_News__e event : Trigger.New) {
        if (event.Urgent__c == true) {
            // Create Case to dispatch new team.
            Case cs = new Case();
            cs.Priority = 'High';
            cs.Subject = 'News team dispatch to ' + 
                event.Location__c;
            //cs.OwnerId = queue.Id;
            cs.OwnerId = UserInfo.getUserId();
            cases.add(cs);
        }
   }
    
    // Insert all cases corresponding to events received.
    insert cases;
}

f:id:tyoshikawa1106:20170717210423p:plain


ケースを作成するトリガを用意した後に、先程のApexをつかったPlatform EventsのINSERT処理を実行します。するとApexトリガが実行されて無事にケースが登録されました。
f:id:tyoshikawa1106:20170717211201p:plain


使い方はこんな感じで良いみたいです。

Apexテスト

専用のテストの書き方が用意されています。
f:id:tyoshikawa1106:20170717211327p:plain

f:id:tyoshikawa1106:20170717211348p:plain

@isTest
public class PlatformEventTest {
    @isTest static void test1() {
        // Create test event instance
        Cloud_News__e newsEvent = new Cloud_News__e(
            Location__c='Mountain City', 
            Urgent__c=true, 
            News_Content__c='Test message.');
        
        Test.startTest();

        // Call method to publish events
        Database.SaveResult sr = EventBus.publish(newsEvent);
        
        Test.stopTest();
        
        // Perform validation here
        // Check that the case that the trigger created is present.
        List<Case> cases = [SELECT Id FROM Case];
        // Validate that this case was found.
        // There is only one test case in test context.
        System.assertEquals(1, cases.size());
    }
}

CometDでプラットフォームイベント通知を購読する

f:id:tyoshikawa1106:20170717211439p:plain

f:id:tyoshikawa1106:20170717211457p:plain

f:id:tyoshikawa1106:20170717211521p:plain


この辺は試していないのでTrailhead要確認という感じです。


Platform Eventsの使い方はこんな感じでした。