Apex workaround for doing callout after DML

If you are trying to do a callout after a DML operation you would have seen this error message:

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

A way around doing callouts after a DML is to do the DML as its own internal callout. This is possible by creating a internal endpoint which will be called first to insert the records. After the insert is complete serialize the response and use that for the external callout.

Steps to following:
1. Create internal endpoint to insert records
2. Create internal Httprequest to the endpoint above
3. Combine internal callout and external callout

Create internal endpoint to insert records

global with sharing class PostInternal implements Rest_Dispatcher.Dispatchable {
	private Rest_Global_Request_Json requestBody;

	global String getURIMapping(){
					return Rest_Constants.URI_ACCOUNT + '/internal';
	}

	global void setRequestBody(Rest_Global_Request_Json requestBody){
			this.requestBody = requestBody;
	}

	global Rest_Global_Json execute(Map<String, String> parameters){
			Rest_Global_Json globalJson = new Rest_Global_Json();
			List<Financial_Account__c> financialAccountList = (List<Financial_Account__c>)JSON.deserialize(requestBody.getRequest(), List<Financial_Account__c>.class);
			List<Financial_Account__c> bpFinancialAccounts = App_Service.instance.insertFinancialAccount(financialAccountList);
			globalJson.setResult(Selector_Financial_Account.newInstance().selectByFinAccountAccounts(bpFinancialAccounts).values());
			return globalJson;
	}
}

Create internal Httprequest to the internal endpoint

public static HttpResponse doInternalCalloutToInsertAccount(List<Financial_Account__c> financialAccountList){
	Http h = new Http();
	Httprequest req = new Httprequest();
	req.setMethod('POST');

	req.setHeader('Authorization','Bearer ' + UserInfo.getSessionId());
	req.setHeader('Content-Type','application/json');
	Object finaAccountListObject = (Object)financialAccountList;
	req.setBody(JSON.serialize(finaAccountListObject));
	req.setEndpoint(System.URL.getSalesforceBaseURL().toExternalForm() + '/services/apexrest/v1/account/internal');
	HttpResponse response = h.send(req);
	return response;
}

Combine internal callout and external callout

HttpResponse response = doInternalCalloutToInsertAccount(financialAccountList);

if (response!=null && response.getBody()!=null){
	Map<String,Object> serializeResponse = (Map<String,Object>)JSON.deserializeUntyped(response.getBody());
	bpAccountInserted = (List<Financial_Account__c>)JSON.deserialize(JSON.serialize(serializeResponse.get('result')), List<Financial_Account__c>.class);
	List<Metadata.BPUpdatedAccounts> bpAccountUpdateList = new List<Metadata.BPUpdatedAccounts>();

	for (Financial_Account__c bpAccount : bpAccountInserted){
		...
	}
}

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s