Getting the error below while introducing a new app. The new app is attempting to update all accounts and this is happening. Most likely because it is maxing out the callout limit. I can deactivate it temporarily, but I would prefer to make the the code more stable in order to avoid prevent this from happening again. Any help?
UNIQUE ERRORS UPDATING THE ACCOUNT RECORDS:
AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String) () Please
Specify the Campaign for this Trade Show. Required fields are missing:
[Parent_Company__c]
We have a trigger:
trigger AccountChangeToCerbWebhook on Account (After insert) {
String webhook_url = 'https://HIDDEN CONTENT';
for(Account a : Trigger.new) {
Map<String, Object> fields = a.getPopulatedFieldsAsMap();
string body = '_=';
for(String fieldKey : fields.keySet()) {
Object fieldValue = fields.get(fieldKey);
String paramValue = '';
if(fieldValue instanceof Datetime) {
paramValue = String.valueOf(((DateTime)fieldValue).getTime()/1000);
} else if(
fieldValue instanceof Boolean
|| fieldValue instanceof Date
|| fieldValue instanceof Decimal
|| fieldValue instanceof Double
|| fieldValue instanceof ID
|| fieldValue instanceof Integer
|| fieldValue instanceof Long
|| fieldValue instanceof String
|| fieldValue instanceof Time
) {
paramValue = String.valueOf(fieldValue);
}
body += '&' + fieldKey + '=' + EncodingUtil.urlEncode(paramValue, 'UTF-8');
}
//if(!Test.isRunningTest()){
CerbWebhookRequest.Post(webhook_url, body);
//}
}
}
Here is the class:
public with sharing class CerbWebhookRequest {
@future (callout=true)
static public void Post(String url, String body) {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setEndpoint(url);
req.setMethod('POST');
req.setBody(body);
try {
if(!Test.isRunningTest()){
res = http.send(req);
}
} catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(res.toString());
}
}
}
Best Answer
If you are using a batch to update all records, then you cannot call a
@future
method from within that batch. You should add a method which will do the processing synchronously instead. That way, when you are already asynchronous (such as in a batch), you can just run the synchronous code. That would look roughly like the below: