5

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?

0

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.

  • Yes, that will work, but it requires whoever is developing the business logic (which will change and expand) to plan and implement logging when setting all of that up. If we are applying the concept of Separation of Concerns (I am), it makes more sense for logging to happen automatically at that external interface layer than it does at the business logic layer. – John Thompson Feb 23 '17 at 15:08
  • @JohnThompson Indeed it would. But in this case the "Uncommitted work pending" constraint makes that AFAIK impossible. – Keith C Feb 23 '17 at 15:23

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.