Design pattern for logging HTTP Callouts

I’m building an application that integrates with an external service. Two items on our list of requirements is:

  1. Log all Callouts to the external system in Salesforce
  2. Execute all Callouts in a synchronous context

I’ve made a Class that handles all of the Callouts, and for each resource & operation there are one or more methods. Ideally, I want to execute the logging operations at an atomic level kind of like this…

public sObject getService(){
  sObject returnObj = new sObject();
  HttpRequest req = new HttpRequest();
  req.setEndpoint(some_endpoint + '/someservice');
  req.setMethod('GET');
  Http http = new Http();
  HTTPResponse res = http.send(req);
  CalloutLogs.log(req, res);    // I want to do logging here!
  //Some more useful stuff, deserialize, etc...
  return returnObj;
}

I know about the dreaded “…Uncommitied work pending…” Callout Exception, and I’m trying to avoid it. To do that I made the CalloutLogs.log(req, res) method asynchronous, like this.

public static Id log(HttpRequest request, HttpResponse response){
  CalloutLogClass log = convert2strings(request,response); //turns everything to strings...
  log.Time_Stamp = DateTime.now();
  log.User_Id = UserInfo.getUserId(); 
  Id JobId = system.enqueueJob(new CalloutLogger(log)); //asynchronous!!
  return JobId;
}

Where I am running into a problem is that the external system can be a little bit “chatty”. To implement the business logic, sometimes I have to make a GET followed by a PUT, maybe a couple of GETs followed by a POST.

In spite of the fact that I am using an asynchronous logging system, I’m still getting the uncommited work pending exception. The Case I opened with SFDC came back with a response that seems to suggest enqueueing a job (even @future) counts as a pending operation.

The thing is you cannot have a pending operations before the callouts in a given transactions.And pending transactions include future,DML,Queueable,batch,send emails.

SO… Has anyone built a Callout logging system that comes close to meeting my requirements above? Synchronous Callouts with atomic logging?

Answer

Maybe I’m missing something here, but if this sequence is pre-determined:

GET followed by a PUT, maybe a couple of GETs followed by a POST

then you know when the last request has completed. So your logging solution can be a class that gathers a list of log entries and then has a method you call when the last request has completed to insert all the log entries.

Attribution
Source : Link , Question Author : John Thompson , Answer Author : Keith C

Leave a Comment