Apex-事件驱动(2)

学习目标

完成本单元后,您将能够:

  • 定义一个平台事件。
  • 描述如何发布平台事件消息。
  • 使用Apex方法发布一个事件。
  • 通过插入一个sObject来发布一个使用REST API的事件。

定义和发布平台事件

现在,您已经了解了平台事件以及何时使用了平台事件,接下来我们将介绍如何定义平台事件。还记得云端通讯社吗?我们来创建一个平台事件定义来保存新闻事件的数据。

定义一个名为Cloud News的平台事件:

  1. 从安装程序中,在快速查找框中输入平台事件,然后选择 Platform Events.
  2. 在“平台事件”页面上,单击 New Platform Event.
  3. 对于标签,请输入 Cloud News.
  4. 对于多标签,请输入 Cloud News.
  5. 对于描述,输入 Cloud news events deliver news at your fingertips.
  6. 点击 Save.
  7. 在“自定义字段和关系”相关列表中,单击 New.
  8. 选择 Text, 然后单击 Next.
  9. 对于字段标签/名称,输入 Location.
  10. 对于“长度”,请键入100.保留其他字段的默认值,并将“说明”字段保留为空。点击 Save.
  11. 按照步骤7,8和9添加下两个字段:
    字段标签/名称 字段类型
    Urgent Checkbox
    News Content Text Area (Long)

对于您刚定义的Cloud News事件,您创建了各种类型的字段,如文本字段或复选框。平台事件支持的所有字段类型是:

  • Checkbox
  • Date
  • Date/Time
  • Number
  • Text
  • Text Area (Long)

事件保留和ReplayId系统字段

Salesforce将平台事件存储24小时。您可以检索API CometD客户端中存储的事件,但不能检索Apex中的事件。您可以检索所有存储的事件,也可以将事件的重播ID指定为检索事件的基线。

即使Salesforce暂时保留事件记录,也不能通过SOQL或SOSL查询它们。同样,您不能在报告,列表视图和搜索中的用户界面中使用事件记录。只有在订购CometD和使用ReplayId选项时才能检索过去的事件。我们向您展示如何订阅下一单元的活动。

每个事件消息被分配一个包含在ReplayId字段中的不透明ID。由系统填充的ReplayId字段值指的是事件流中事件的位置。重放ID值不保证连续事件连续。例如,ID为999的事件之后的事件可以具有1,025的ID。订阅者可以存储重播ID值并在重新订阅时使用它来检索保留窗口内的事件。例如,用户可以在连接失败后检索错过的事件。订阅者不得根据存储的重播ID来计算新的重播ID,以引用流中的其他事件。

API名称后缀

在创建平台事件时,系统会附加__e后缀来创建事件的API名称。例如,对于Cloud News事件,API名称是Cloud_News__e。只要以编程方式引用该事件,请使用API​​名称,例如,在Apex,REST API和Enterprise API中。

发布事件

如果您的应用程序位于Salesforce平台上,则可以使用Apex方法或声明性工具(如Process Builder或Cloud Flow Designer)发布事件。如果您的应用是外部应用,则可以使用Salesforce API发布事件。

使用Apex发布事件消息

要发布事件消息,请创建事件的实例并将其传递给EventBus.publish方法。

以下示例创建一个类型为Cloud_News__e的事件,将其发布,然后检查发布是成功还是遇到错误。 EventBus.publish()方法返回一个Database.SaveResult对象,其中包含发布的结果。如果isSuccess()返回true,则事件已在Salesforce事件总线中发布。否则,该事件遇到在Database.Error对象中返回的错误。

// 创建一个事件的实例并将其存储在newsEvent变量中
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.');

// 调用方法来发布事件
Database.SaveResult sr = EventBus.publish(newsEvent);

// 检查发布结果
if (sr.isSuccess()) {
    System.debug('Successfully published event.');
} else {
    for(Database.Error err : sr.getErrors()) {
        System.debug('Error returned: ' +
                     err.getStatusCode() +
                     ' - ' +
                     err.getMessage());
    }
}
要在同一个调用中发布多个事件,请将您的事件添加到事件列表中,然后将该列表传递给EventBus.publish()方法。此方法的输出是Database.SaveResult对象的数组:每个发布的事件一个。 EventBus.publish()可以发布一些传入事件,即使由于错误而无法发布其他事件。 EventBus.publish()方法不会因发布操作失败而引发异常。在使用部分成功选项调用时,它的行为类似于Apex Database.insert()方法。
// List来保存要发布的事件对象。
List<Cloud_News__e> newsEventList = new List<Cloud_News__e>();
// 创建事件对象
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.');
// 将事件对象添加到列表中。
newsEventList.add(newsEvent1);
newsEventList.add(newsEvent2);

// 调用方法来发布事件。
List<Database.SaveResult> results = EventBus.publish(newsEventList);

// 检查每个事件的发布结果
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());
        }
    }       
}

注意

Salesforce平台对您可以在组织中定义的事件数量以及您可以在一个小时内发布的事件记录数量进行限制。此外,由于事件发布相当于DML插入操作,所以适用DML限制和其他Apex调控限制。有关平台事件限制和Apex调控器限制的更多信息,请参阅参考资料部分。

使用点击发布事件消息

要发布没有代码的事件消息,请在流程或流程中使用记录创建功能。

此屏幕截图显示了在发布Cloud News事件消息的Process Builder中创建记录操作的示例。基本上,将“记录类型”设置为要发布的平台事件(云新闻),然后设置事件的值。

The Create a Record action in Process Builder is set to the Cloud News record type. The fields of the Cloud News event are filled.

同样,您可以使用流发布平台事件消息。配置Record Create元素以创建平台事件(Cloud_News__c)的实例,然后设置事件的值。要设置布尔字段的值(如Urgent__c),请使用{!$ GlobalConstant.True}。

使用Salesforce API发布事件消息

外部应用使用API​​发布平台事件消息。您可以像插入sObjects一样创建事件记录来发布事件。您可以使用Salesforce API来创建平台事件记录,如SOAP API,REST API或Bulk API。

例如,对于Cloud News事件,您可以通过插入Cloud_News__e记录来发布事件通知。以下示例在REST API中创建一个类型为Cloud_News__e的事件。

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" : [ ] 
}
您可以使用任何REST API工具或HTTP客户端应用程序来进行REST API调用。例如,您可以按照以下步骤使用Workbench。
  1. 登录到您的Trailhead DE组织。
  2. 打开一个新标签页并导航到Workbench https://workbench.developerforce.com/login.php
  3. 对于环境,请选择 Production.
  4. 对于API版本,请选择可用的最高编号。
  5. 选择 I agree to the terms of service.
  6. 点击 Login with Salesforce.
  7. 在下一个屏幕上,单击 Allow.
  8. 在顶部菜单中,选择 utilities | REST Explorer.
  9. 点击 POST.
  10. 将URI替换为:
    /services/data/v40.0/sobjects/Cloud_News__e
  11. 对于请求正文,以JSON格式添加以下正文。
    {
       "Location__c" : "Mountain City",
       "Urgent__c" : true,
       "News_Content__c" : "Lake Road is closed due to mudslides."
    }
  12. 点击 Execute.

    Salesforce在发布事件后返回的响应类似于以下内容。

    {
      "id" : "e00xx0000000001AAA",
      "success" : true,
      "errors" : [ ],
      "warnings" : [ ]
    }
    
    或者,您可以通过create()调用或在Bulk API中使用批处理作业在SOAP API中发布事件。

平台事件和事务

与自定义对象不同,平台事件不在Salesforce平台的数据库事务中处理。 因此,发布的平台事件无法回滚。 请注意以下几点:

  • 当您通过API发布平台事件时,allOrNoneHeader API标头将被忽略。
  • 平台事件不支持Apex setSavepoint()和rollback()数据库方法。

当您发布平台事件时,适用DML限制和其他Apex调控限制。

现在你已经看到了如何定义和发布事件,让我们看看如何订阅它们!