In Salesforce Apex coding, developers have seen the situation where they need to make a callout after any DML statement and come out with exception. In Spring 24 Salesforce resolved that issue.
Learn step by step. First try to reproduce the exception i.e. the problem and next gradually resolve the issue introducing Database.releaseSavepoint.
Please see below a sample code snippet.
public class ReleaseRollbackCheck { public void checkReleaseRollback(){ insert new Account(name='SoftVowels'); Http h = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint('https://softvowels.com'); req.setMethod('POST'); HttpResponse res = new HttpResponse(); res = h.send(req); } }
In the above code snippet, we are trying to insert an Account record and then making a callout. If we run this code using developer console, then will get an error.
ReleaseRollbackCheck obj = new ReleaseRollbackCheck(); obj.checkReleaseRollback();
Let’s try in different way:
Keep the code withing Try…Catch block. Introduce Database.Savepoint. Within catch block use Database.rollback and then make the call again. See below screenshot.
The above screenshot shows that we made the call from Catch block after using Database.rollback. Still getting the error – System.CalloutException: All active Savepoints must be released before making callouts.
Actually, Database.rollback(sp) constitutes DML, so even though you rolled back your insert, you committed another DML (which hasn’t been rolled back, and so you still can’t do your callout).
Hence the understanding is No DML before a Callout.
In Spring 24, Salesforce introduced Database.releaseSavepoint(<Savepoint>) that will release mentioned savepoint and other created after.
So final code snippet is mentioned below:
public class ReleaseRollbackCheck { public void checkReleaseRollback(){ Savepoint sp = Database.setSavepoint(); try{ insert new Account(name='SoftVowels'); Http h = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint('https://softvowels.com'); req.setMethod('POST'); HttpResponse res = new HttpResponse(); res = h.send(req); }catch(Exception ex){ system.debug('---Exception: '+ex.getmessage()); Database.rollback(sp); Database.releaseSavepoint(sp); // Also releases any savepoints created after 'sp' Http h = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint('https://softvowels.com'); req.setMethod('POST'); HttpResponse res = new HttpResponse(); res = h.send(req); } } }
You can copy paste the code in your personal org for testing purposes. Just you need to add a Remote Site Setting for https://softvowels.com to avoid exception.
Conclusion
Before Spring 24 we developers need to remember No DML before a callout and act accordingly. Now all can use Database.releaseSavepoint just before making any callout. Importantly, all need to use/implement Database.savepoint correctly. Also please check the ideaexchange link.