运行 通过触发器的异步 Apex Class
Running an Async Apex Class through a trigger
我正在 SF 中的自定义对象上创建 Apex 触发器。现在我有对象约会,我想在保存新记录时触发标注。由于我们的内部流程,我们无需担心更新。只有新记录。
话虽这么说,我已经创建了触发器和 class 的基础知识并且它们起作用了。触发器 运行 是标记为 Future 到 运行 异步的 class。但是, class 是我迷路的地方。
我想将一些变量从正在创建的 Appointment 对象中的记录传递到代码中。我的代码将 HTTP POST 发送到向客户发送 SMS 的服务。我想使用 phone 号码、客户姓名和消息中包含约会日期和时间的消息。此数据存储的字段是:
i360__Prospect_Phone__c
i360__Correspondence_Name__c
i360__Start__c
i360__Start_Time__c
例如,我需要phone号码和姓名转入下面的class代码。至于消息,我想以包含变量的字符串形式发送出去。示例:"Hello i360__Correspondence_Name__c, your appointment with COMPANY has been scheduled on i360__Start__c at i360__start_Time__c. Please respond or call if you have any questions."
这是我的触发代码:
trigger sendtext on i360__Appointment__c (after insert) {
System.debug('Making future call to update account');
for (i360__Appointment__c app : Trigger.New) {
PodiumText.updateAccount(app.Id, app.Name);
}
}
这是我的 Class 代码:
public class PodiumText {
//Future annotation to mark the method as async.
@Future(callout=true)
public static void updateAccount(String id, String name) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.podium.com/api/v2/conversations');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Accept', 'application/json');
request.setHeader('Authorization', 'IDSTRING');
request.setBody('{"customerPhoneNumber":"PHONENUMBER","message":"Testing","locationId":"49257","customerName":"CORRESPONDENCENAME"}');
HttpResponse response = http.send(request);
// Parse the JSON response
if (response.getStatusCode() != 201) {
System.debug('The status code returned was not expected: ' +
response.getStatusCode() + ' ' + response.getStatus());
} else {
System.debug(response.getBody());
}
}
}
任何帮助都会很棒。
理想情况下,您不会一次一个帐户调用此@future 方法。每笔交易有 50 次调用的限制(https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm 寻找 "Maximum number of methods with the future annotation"。因此,当您从 UI 插入 1 条记录时,您现在拥有的将完美运行,但如果您进行大量操作,将会严重失败数据加载。
因此您可以调用它一次,但将一个列表(数组)与您的数据一起传递。我们可以只传递记录 ID,然后在方法本身中我们可以查询您需要的字段。或者您可以在触发器中构建消息文本并将字符串列表传递给@future 方法。这有点个人喜好,我认为只传递记录 ID 更干净。这样触发器就不会关心到底发生了什么,它只是 "yo, send whatever message you need based on this data"。实际的标注代码保存在一起(端点和消息构建),因此如果您想要更改某些内容,只需 1 个文件即可。
类似的东西(消息的顺序重要吗?如果不重要,甚至可以更简单一点)
trigger sendtext on i360__Appointment__c (after insert) {
List<Id> ids = new List<Id>();
for (i360__Appointment__c app : trigger.New) {
ids.add(app.Id);
}
System.debug('Making future call to update account');
PodiumText.updateAccounts(ids);
}
然后
@future(callout=true)
public static void updateAccounts(List<Id> ids){
Map<Id, i360__Appointment__c> appointments = new Map<Id, i360__Appointment__c>([SELECT Id, Name,
i360__Prospect_Phone__c, i360__Correspondence_Name__c, i360__Start__c, i360__Start_Time__c
FROM i360__Appointment__c
WHERE Id IN :ids]);
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.podium.com/api/v2/conversations');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Accept', 'application/json');
request.setHeader('Authorization', 'IDSTRING');
for(Id i : ids){
i360__Appointment__c appointment = appointments.get(i);
Map<String, String> message = new Map<String, String>{
'customerPhoneNumber' => appointment.i360__Prospect_Phone__c,
'message' => 'Testing',
'locationId' => '49257',
'customerName' => appointment.i360__Correspondence_Name__c
};
String messageJson = JSON.serialize(message);
System.debug(messageJson);
request.setBody(messageJson);
HttpResponse response = http.send(request);
// Parse the JSON response
if (response.getStatusCode() != 201) {
System.debug('The status code returned was not expected: ' +
response.getStatusCode() + ' ' + response.getStatus());
} else {
System.debug(response.getBody());
}
}
}
如果这可行(我没有检查它是否可以编译并且我没有安装这个应用程序)那么最后一部分将是放置真实消息而不是 "Testing"。这部分取决于这些字段到底是什么(开始时间是 text/picklist 字段吗?时间字段?)。有一个有趣的 String.format() 方法,但我们可以保持简单(感觉我已经向您展示了很多东西,查询、地图、JSON 序列化...)
String message = 'Hello ' + appointment.i360__Correspondence_Name__c + ', your appointment with COMPANY has been scheduled on ' + appointment.i360__Start__c + ' at ' + appointment.i360__start_Time__c + '. Please respond or call if you have any questions.';
(实际上我给你的也不是 100% 完美的。有一个 "Total number of callouts" 限制,100。所以如果你做海量数据加载,你需要重新编写这段代码,也许 2 未来每个调用 100 条记录或 10 * 20...)
我正在 SF 中的自定义对象上创建 Apex 触发器。现在我有对象约会,我想在保存新记录时触发标注。由于我们的内部流程,我们无需担心更新。只有新记录。
话虽这么说,我已经创建了触发器和 class 的基础知识并且它们起作用了。触发器 运行 是标记为 Future 到 运行 异步的 class。但是, class 是我迷路的地方。
我想将一些变量从正在创建的 Appointment 对象中的记录传递到代码中。我的代码将 HTTP POST 发送到向客户发送 SMS 的服务。我想使用 phone 号码、客户姓名和消息中包含约会日期和时间的消息。此数据存储的字段是:
i360__Prospect_Phone__c
i360__Correspondence_Name__c
i360__Start__c
i360__Start_Time__c
例如,我需要phone号码和姓名转入下面的class代码。至于消息,我想以包含变量的字符串形式发送出去。示例:"Hello i360__Correspondence_Name__c, your appointment with COMPANY has been scheduled on i360__Start__c at i360__start_Time__c. Please respond or call if you have any questions."
这是我的触发代码:
trigger sendtext on i360__Appointment__c (after insert) {
System.debug('Making future call to update account');
for (i360__Appointment__c app : Trigger.New) {
PodiumText.updateAccount(app.Id, app.Name);
}
}
这是我的 Class 代码:
public class PodiumText {
//Future annotation to mark the method as async.
@Future(callout=true)
public static void updateAccount(String id, String name) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.podium.com/api/v2/conversations');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Accept', 'application/json');
request.setHeader('Authorization', 'IDSTRING');
request.setBody('{"customerPhoneNumber":"PHONENUMBER","message":"Testing","locationId":"49257","customerName":"CORRESPONDENCENAME"}');
HttpResponse response = http.send(request);
// Parse the JSON response
if (response.getStatusCode() != 201) {
System.debug('The status code returned was not expected: ' +
response.getStatusCode() + ' ' + response.getStatus());
} else {
System.debug(response.getBody());
}
}
}
任何帮助都会很棒。
理想情况下,您不会一次一个帐户调用此@future 方法。每笔交易有 50 次调用的限制(https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm 寻找 "Maximum number of methods with the future annotation"。因此,当您从 UI 插入 1 条记录时,您现在拥有的将完美运行,但如果您进行大量操作,将会严重失败数据加载。
因此您可以调用它一次,但将一个列表(数组)与您的数据一起传递。我们可以只传递记录 ID,然后在方法本身中我们可以查询您需要的字段。或者您可以在触发器中构建消息文本并将字符串列表传递给@future 方法。这有点个人喜好,我认为只传递记录 ID 更干净。这样触发器就不会关心到底发生了什么,它只是 "yo, send whatever message you need based on this data"。实际的标注代码保存在一起(端点和消息构建),因此如果您想要更改某些内容,只需 1 个文件即可。
类似的东西(消息的顺序重要吗?如果不重要,甚至可以更简单一点)
trigger sendtext on i360__Appointment__c (after insert) {
List<Id> ids = new List<Id>();
for (i360__Appointment__c app : trigger.New) {
ids.add(app.Id);
}
System.debug('Making future call to update account');
PodiumText.updateAccounts(ids);
}
然后
@future(callout=true)
public static void updateAccounts(List<Id> ids){
Map<Id, i360__Appointment__c> appointments = new Map<Id, i360__Appointment__c>([SELECT Id, Name,
i360__Prospect_Phone__c, i360__Correspondence_Name__c, i360__Start__c, i360__Start_Time__c
FROM i360__Appointment__c
WHERE Id IN :ids]);
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.podium.com/api/v2/conversations');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Accept', 'application/json');
request.setHeader('Authorization', 'IDSTRING');
for(Id i : ids){
i360__Appointment__c appointment = appointments.get(i);
Map<String, String> message = new Map<String, String>{
'customerPhoneNumber' => appointment.i360__Prospect_Phone__c,
'message' => 'Testing',
'locationId' => '49257',
'customerName' => appointment.i360__Correspondence_Name__c
};
String messageJson = JSON.serialize(message);
System.debug(messageJson);
request.setBody(messageJson);
HttpResponse response = http.send(request);
// Parse the JSON response
if (response.getStatusCode() != 201) {
System.debug('The status code returned was not expected: ' +
response.getStatusCode() + ' ' + response.getStatus());
} else {
System.debug(response.getBody());
}
}
}
如果这可行(我没有检查它是否可以编译并且我没有安装这个应用程序)那么最后一部分将是放置真实消息而不是 "Testing"。这部分取决于这些字段到底是什么(开始时间是 text/picklist 字段吗?时间字段?)。有一个有趣的 String.format() 方法,但我们可以保持简单(感觉我已经向您展示了很多东西,查询、地图、JSON 序列化...)
String message = 'Hello ' + appointment.i360__Correspondence_Name__c + ', your appointment with COMPANY has been scheduled on ' + appointment.i360__Start__c + ' at ' + appointment.i360__start_Time__c + '. Please respond or call if you have any questions.';
(实际上我给你的也不是 100% 完美的。有一个 "Total number of callouts" 限制,100。所以如果你做海量数据加载,你需要重新编写这段代码,也许 2 未来每个调用 100 条记录或 10 * 20...)