trigger OpportunityRemoteUpdate on Opportunity (after insert, after update, after delete) {
HttpRequest req = new HttpRequest();
req.setEndpoint('http://dev.xxxxx.com/ntm/trunk/opportunity/remote/sf_query&token=xxxxx&act=update&id=006P0000004NPIA4');
req.setMethod('POST'); Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
При отработке тригера выдается ошибка
Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger OpportunityRemoteUpdate caused an unexpected exception, contact your administrator: OpportunityRemoteUpdate: execution of AfterUpdate caused by: System.CalloutException: Callout from triggers are currently not supported.: Trigger.OpportunityRemoteUpdate: line 7, column 1
В чем может быть проблема?
Вот тут есть ответ на ваш вопрос.
Дело в том что в Salesforce есть такой нюанс - нельзя делать callout после DML операции. А триггер запускается в результате DML операции. Тут необходимо использовать @future метод. Но учтите, что это асинхронная операция и в debug log будет отображаться как отдельный процесс после основного.
Процетирую
You do need to use the @future annotation in an apex method that is stored in a separate class. Then call that class and method from within your trigger.
For example:
trigger justAnExample on Account (after update){
testCls.myMethod(); //call the static method, with the @future annotation
}
global testCls {
@future Public static void myMethod(callout=true){
System.debug('inside myMethod...');
//do your callout logic here...
System.debug('exiting myMethod...');
}
}
Да действительно так работает!
Есть еще одна проблема - когда я хочу передать параметр trigger.newMap
trigger OpportunityRemoteUpdate on Opportunity (after insert, after update, after delete) {
Opportunity_TriggerHelper.updateOpportunity(trigger.newMap);
}
public with sharing class Opportunity_TriggerHelper {
@future (callout=true)
public static void updateOpportunity (Map<Id, Opportunity> newMap);
HttpRequest req = new HttpRequest();
req.setEndpoint('http://dev.xxxxx.com/ntm/trunk/opportunity/remote/sf_query&token=xxxxx&act=update&id=xxxxx');
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
}
то при сохранении класса получаю ошибку: Error: Compile Error: expecting a right parentheses, found 'http://dev.xxxxx.com/ntm/trunk/opportunity/remote/sf_query&token=xxxxx&act=update&id=xxxxx' at line 5 column 21
причем если передавать string в качестве параметра то все норм, например так:
trigger OpportunityRemoteUpdate on Opportunity (after insert, after update, after delete) {
String OpportunityId = 'xxxxx';
Opportunity_TriggerHelper.updateOpportunity(OpportunityId);
}
public with sharing class Opportunity_TriggerHelper {
@future (callout=true)
public static void updateOpportunity (String OpportunityId) {
HttpRequest req = new HttpRequest();
req.setEndpoint('http://dev.xxxxx.com/ntm/trunk/opportunity/remote/sf_query&token=xxxxx&act=update&id='+OpportunityId);
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
}
В первом куске кода:
public with sharing class Opportunity_TriggerHelper {
@future (callout=true)
public static void updateOpportunity (Map<Id, Opportunity> newMap);
HttpRequest req = new HttpRequest();
req.setEndpoint('http://dev.xxxxx.com/ntm/trunk/opportunity/remote/sf_query&token=xxxxx&act=update&id=xxxxx');
req.setMethod('GET'); Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
}
У тебя в строке public static void updateOpportunity (Map<Id, Opportunity> newMap); в конце стоит ; а должна стоять {
Следующий нюанс
Если ничего не поменялось в последнем релизе то во future нельзя передавать объекты. Только примитивные данные (Integer, String, ID) или списки этих примитивных данных типо List<Id>, Set<Id>
В твоем случае надо из триггера передавать Set<Id>
Твой @future метод должен так объявляться
@future (callout=true)
public static void updateOpportunity (Set<Id> opportunityIds){}
Вот твой триггер, который передает во @future метод Set<Id> opportunity
trigger OpportunityRemoteUpdate on Opportunity (after insert, after update, after delete) {
Set<Id> opportunityIds = new Set<Id>(); if (Trigger.isInsert || Trigger.isUpdate) {
opportunityIds = Trigger.newMap.keySet();
}
if (Trigger.isDelete) {
opportunityIds = Trigger.oldMap.keySet();
}
Opportunity_TriggerHelper.updateOpportunity(opportunityIds);
}
Ну @future метод сам попробуй написать. Только учти, что тебе на вход будет приходить Set<Id> т.е. ты не знаешь будет 1 или N записей. Так что либо вставляй в запрос только первую opportunityIds[0] или пиши интеграцию, которая может принимать более 1 в одном запросе.
Осталась маленькая проблема
public static void updateOpportunity (String action, Set<Id> opportunityIds) {
String ids = String.join(opportunityIds, ',');
...
Error: Compile Error: Variable does not exist: String at line 5 column 22 (ругается на String.join)
new List<Id>(your Set instance);