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.
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:
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;
}
}
000385374

We use three kinds of cookies on our websites: required, functional, and advertising. You can choose whether functional and advertising cookies apply. Click on the different cookie categories to find out more about each category and to change the default settings.
Privacy Statement
Required cookies are necessary for basic website functionality. Some examples include: session cookies needed to transmit the website, authentication cookies, and security cookies.
Functional cookies enhance functions, performance, and services on the website. Some examples include: cookies used to analyze site traffic, cookies used for market research, and cookies used to display advertising that is not directed to a particular individual.
Advertising cookies track activity across websites in order to understand a viewer’s interests, and direct them specific marketing. Some examples include: cookies used for remarketing, or interest-based advertising.