[SalesForce] Cant catch exception and log to custom object if I throw exception

Background: I have worked w/ a consultant to build an Apex rest endpoint, and its working well.

Now I am adding some basic error handling, by putting the insert / update statements into try/catch blocks. If there is an exception, I would like to log it to a custom object. I have a simple utility class that can take an exception and a few optional parameters and it will do the logging.

Question: I've been flummoxed because the error log records are not being created if I throw the exception. Looking in the debug logs I can see that the writetoLog method is being called, and that it rolls back due to a fatal error, which has me thinking that throwing the exception results in the entire transaction being rolled back, including the logging, which I validated on another post on StackExchange.

I found one article on developer.force.com that suggested using a future method to handle the logging – would that address this issue?

I have a hunch that throwing a custom exception might be another alternative, but dont know if that is in fact the case.

So my question is: what are the simplest ways to catch the exception, log it to a custom object, and throw an exception (as else the transaction returns as a success, instead of an error).

The code is below. If I comment out throw e and instead return a string of the error message, the error log is created successfully, so I know there are no underlying permissions issues.

@HttpPost
global static string CreateContact(WebContactData wcd){              
    WebContact__c  wc = TranslateToInternalModel(wcd);
    try{
        Insert wc;
        return wc.Id;
    }catch(exception e){
       utils_logging.writeToLog(e, wcd.FormType, JSON.serializePretty(wcd));
       throw e; 
    }   
}

Best Answer

Unfortunately if your ending point in the code is throwing an error ALL of the transaction gets rolled back including your log creation. This creates quite the issue.

Future methods also get canceled.

IIRC you CAN make a callout to another restful endpoint that will persist a log entry as long as you have not done DML prior which in unlikely.

What you can do is this though, return a custom response object that the external system can use to determine if there is an error or not. Catch all errors and set the appropriate values in the response object. Modify as needed

@HttpPost
global static myResponse CreateContact(WebContactData wcd){ 
    WebContact__c  wc = TranslateToInternalModel(wcd);
    myResponse res = New MyResponse();
    try{
        Insert wc;
        res.result = wc.id;
        res.isError = false;
    }catch(exception e){
       utils_logging.writeToLog(e, wcd.FormType, JSON.serializePretty(wcd));
       res.isError = true;
    }   
        return res;

}

public class myResponse{
     public boolean isError {get;set;}
     public string result {get;set;}

     public myResponse(){       
     }
}
Related Topic