Loading

Salesforce Error 'You have uncommitted work pending. Please commit or rollback before calling out.'

Udgivelsesdato: Jun 25, 2026
Beskrivelse

You may need to create a record and then update it with information provided by a web service. However, in Salesforce Apex, a web service callout (also called a DML callout) cannot occur after a Data Manipulation Language (DML) statement within the same transaction. To achieve this, the transaction must be split into two separate parts so that the DML operation completes before the callout is made.

Løsning

Split Transaction into Two Separate Ajax Processes
The solution is to separate the insert operation and the callout into two distinct Ajax requests using Visualforce apex:actionFunction components.

How it works in the Visualforce page:
Create a Visualforce page with two apex:actionFunction elements. The first, named InsertRecord_JS, is linked to the InsertRecord controller action. When it completes (using the oncomplete attribute), it automatically triggers the second, named CallWebService_JS, which is linked to the CallWebService controller action. The two actions fire in sequence, but as separate HTTP requests, ensuring the database insert is fully committed before the callout begins.
How it works in the controller class:
The TestWsCallout controller contains two separate methods:

  1. InsertRecord: Creates a new Account record named 'Test Account' and inserts it into the database. This method does not make any callouts. After the insert completes, the Ajax response triggers CallWebService_JS on the page.
  2. CallWebService: Constructs an HTTP GET request to an external endpoint, passing the newly created Account ID as a parameter. It sends the request, receives the response, updates the Account name to 'Test Account 2', and adds a confirmation message to the page.

The critical point is that these two methods are invoked as separate Ajax calls — the DML insert completes and is committed in the first call, before the callout occurs in the second call.

TestWsCallout page

<apex:page controller="TestWsCallout" tabstyle="Account">
    <apex:form >
        <apex:actionFunction action="{!InsertRecord}" name="InsertRecord_JS" Rerender="statuses" status="Status1" oncomplete="CallWebService_JS();"/>
        <apex:actionFunction action="{!CallWebService}" name="CallWebService_JS" status="Status2" reRender="statuses, msg"/>
        <apex:outputPanel id="statuses">
            <apex:actionStatus id="Status1" startText="...Inserting Record Into DB..." />
            <apex:actionStatus id="Status2" startText="...Calling Web Service..." />
        </apex:outputPanel>
        <apex:outputPanel id="msg">
            <apex:pageMessages />
        </apex:outputPanel>
        <div><input name="DoAction" class="btn" type="button" value="Do Action" onclick="InsertRecord_JS();return false;"/></div>
    </apex:form>
</apex:page>


TestWsCallout Class

public class TestWsCallout{
    
    Account myAccount;
   
    public PageReference InsertRecord() {
        myAccount = new Account(name = 'Test Account');
        insert myAccount;
        // Calling a Web Service here would throw an exception
        return null;
    }
    
    public PageReference CallWebService() {
        
        // Execute a call to a Web Service
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://MyWebService12345678790.com?id=' + myAccount.Id);
        req.setMethod('GET');
        HttpResponse response = new Http().send(req);
        
        // Simulate an update
        myAccount.Name = 'Test Account 2';
        update myAccount;        
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM, 'WebService Called on New Account: ' + myAccount.Name));
        return null;
    }
}

Yderligere ressourcer

Apex DML Operations

Vidensartikelnummer

000385374

 
Indlæser
Salesforce Help | Article