0

This is my scenario. I have a trigger on a custom object. The trigger invokes a future method in a class. This future method then does a series of callouts using a helper class to update other custom objects in the org.

TriggerA --> FutureMethod --> Helper --> ExternalCallouts

When the FutureMethod creates a request or receives a response it does this via the Helper class. I want to log the raw response of the external callout to a custom object called StoreMyLogs__c

The only inserts / updates I can have are available in the FutureMethod and at that point I have already lost the raw response. It is not possible to do inserts / updates in the Helper class, where the raw response is available.

So I created a static property on the Helper class to accommodate the raw response. This is not working 100% of the times.

So does anyone have any other ideas to log the http response received from the callout?

2
  • Why it is not possible to insert/update in helper class? You have response there right? Sep 20 '17 at 16:41
  • If you perform a DML Operation in the helper class, the DML operations in the FutureMethod will fail.
    – abhi
    Sep 20 '17 at 17:33
0

Sounds familiar... You can create a Class who's job it is to collect your StoreMyLogs__c records, and eventually commit them to the database.

You can pass your HttpRequest and HttpResponse along to a static list in that Class using a static method immediately after your HTTP.send(request) methods in your future/helper/wherever in the execution context.

Then (here's the tricky bit) just before the return statement in your future Class, call another static method to commit your list of StoreMyLogs__c records...

global class CalloutLogs {

  public static list<StoreMyLogs__c> logEntries {get;set;} //need a static variable to avoid the pending work exception
  static{
    logEntries = new list<StoreMyLogs__c>();              //We want to make sure that we have an instance of the static var
  }

  public static StoreMyLogs__c log(HttpRequest request, HttpResponse response){
    //Converts HttpRequest and HttpResponse to string representations
    //Creates a StoreMyLogs__c record, and adds it to the static list<StoreMyLogs__c> member
    //Returns the StoreMyLogs__c record that was converted
    StoreMyLogs__c returnLog = new StoreMyLogs__c ();
    //marshal your request and response into your StoreMyLogs__c
    //...
    logEntries.add(returnLog);
    return returnLog;
  }

  public static string commitLogs(){
    string returnString = 'Failed to commit StoreMyLogs__c ...';
    if(logEntries != null){
      if(logEntries.size() == 0){
        returnString = 'No StoreMyLogs__c to commit...';
      } else {
        insert logEntries;
        returnString = 'Committed ' + logEntries.size() + ' StoreMyLogs__c  Entries';
      }
    }
    return returnString;
  }
}

THEN: just before you return from your future method... call the commitLogs() method.

system.debug(CalloutLogs.commitLogs());
return; //like the absolute final return!

You just need to make sure that you commit only after ALL callouts have been made to avoid the dreaded "pending work" exception.

3
  • I am going to give this a shot. Thanks for the suggestion.
    – abhi
    Sep 21 '17 at 12:14
  • I did attempt this, but I am back to You have uncommitted work pending. Please commit or rollback before calling out
    – abhi
    Sep 21 '17 at 13:35
  • I have accepted your answer. I had to tweak a bit of code on my end to get this going. Thanks once again.
    – abhi
    Sep 21 '17 at 15:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.