I have a managed packaged that I recently updated and it threw an error for a future method I have that sends information to a third party. The error I received was:
Future method cannot be called from a future or batch method.
Since I cannot see any of the classes in the package I am assuming the method that triggered mine is a future/batch method.
Knowing that, I decided to put in a check:
If(System.future()){
//do non-future method
else{
//future method
However in other posts I read that I should just remove "@future"since we can not call a future from a future so that is what my non-future method is. When I did and included the check above, it threw this error:
Callout from triggers are currently not supported.
My future method(My non-future method is basically the same but without the @future annotation:
@future(callout = true)
public static void updateOrderStatus(Set<Id> orderIds, String errorMessage){
List<OrderStatus> ordStatus = new List<OrderStatus>();
Map<Id, Id> orderToDistributionMap = new Map<Id, Id>();
List<Package__c> relevantPacks = [SELECT ID, Order__c, distribution__c FROM package__c WHERE Order__c IN :orderIds];
for(Package__c pack : relevantPacks){
if(orderToDistributionMap.get(pack.Order__c) == null){
orderToDistributionMap.put(pack.Order__c, pack.Distribution__c);
}
}
List<Order> orders = [SELECT ID, Status__c FROM Order WHERE ID IN :orderIds];
for(order ord : orders){
ordStatus.add(new OrderStatus(ord, orderToDistributionMap.get(ord.id)));
}
HttpRequest req = new HttpRequest();
String env = ERFUtils.getEnvironment();
String endpoint = Link__c.getValues(env).ERFapi__c+'Packages/status';
String token = Link__c.getValues(env).Token__c;
req.setEndpoint(endpoint);
req.setHeader('x-ERF-auth', token);
req.setHeader('Content-Type', 'application/json');
req.setMethod('POST');
Http http = new Http();
HttpResponse res = new HttpResponse();
if(!Test.isRunningTest()){
try {
for(OrderStatus status : ordStatus){
req.setBody(JSON.serialize(status));
res = http.send(req);
}
} catch(System.CalloutException e) {
Tasks.statusFailTask(e.getMessage() + ' ERROR:'+orderIds + ' '+e.getStackTraceString() +errorMessage);
}
}
}
I also then read I should try to convert my method to "queueable". I Have not tried it yet and was wondering if I'm just missing something or is that the approach I should go for. I would like to send my information to the 3rd party in real time after the managed package's method is triggered. So I guess how can I implement a future method to then be followed by another future method? Or what are my other options?
Edit:
public class updateStatusOnOrders implements Queueable {
public Set<Id> orderIds;
public String errorMessage;
public updateStatusOnOrders(Set<Id> orderIds, String errorMessage){
this.shipmentIds = orderIds;
this.errorMessage = errorMessage;
}
public void execute(QueueableContext context) {
EDFService.updateOrderStatus(orderIds, errorMessage);
}
}