+ Start a Discussion

Database.rollback not working as expected

I have an Apex script that basically performs the following:



Savepoint sp;
try {

  sp = Database.setSavepoint();

  // Do some dml inserts, updates

} catch (Exception ex) {


  // Make a web service callout

throw ex;



I'm explicitly rolling back my uncommitted dml operations to try to get around the fact that you can't make a callout when you have uncommitted work. This doesn't seem to work. I get the following messages in the system log:



13:35:26.797|USER_DEBUG|[190,4]|DEBUG|System.QueryException: List has no rows for assignment to SObject
13:35:26.799|METHOD_ENTRY|[203,5]|IPNMessageWSDL.IPNMessageService.upsertIPNMessage(String, String, String, String)
13:35:26.799|METHOD_ENTRY|[59,13]|MAP:String,IPNMessageWSDL.upsertIPNMessageResponse_element.put(String, IPNMessageWSDL.upsertIPNMessageResponse_element)
13:35:26.799|METHOD_EXIT|[59,13]|put(ANY, ANY)
13:35:26.799|METHOD_ENTRY|[60,13]|WebServiceCallout.invoke(IPNMessageWSDL.IPNMessageService, IPNMessageWSDL.upsertIPNMessage_element, MAP:String,IPNMessageWSDL.upsertIPNMessageResponse_element, LIST:String)
13:35:26.799|EXCEPTION_THROWN|[60,13]|System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out
13:35:26.799|METHOD_EXIT|[60,13]|invoke(APEX_OBJECT, APEX_OBJECT, MAP, LIST)
13:35:26.799|METHOD_EXIT|[203,5]|upsertIPNMessage(String, String, String, String)
13:35:26.799|USER_DEBUG|[206,5]|DEBUG|Error invoking upsertIPNMessage web service: System.QueryException: List has no rows for assignment to SObject


From the log, you can see that I am making the rollback call, yet the web service callout is failing with a error indicating I have uncommitted work pending. Any ideas why this doesn't work?



Sorry about the misleading error message there. Rolling back to a savepoint doesn't release the connection to the database which is what is restricting the callout attempt.  I'll check with the team to see if this is something we can consider changing if we can reliably detect that the savepoint was before any pending work was established. At a minimum I'll make sure the error message is not misleading.


For now your options are either to perform the callout before you set the savepoint (and before any dml) or perform your callout in an async method that you call from the catch.


Thanks Andrew,


I will try your suggestion.




Are you sure I can call a future method from within a catch block if I re-throws the exception at the end of the catch block? I do not think my future method is executing because my script is completing abnormally.