How To Resolve The Below Callout Error?
I have written an inline Vf page to update the record value. The values are coming from a web service. While updating the record the detail page redirected to the VF page. But the record was committed in the database with the error in debug log
"You have uncommitted work pending. Please commit or rollback before calling out"
I want to save the value in the record and the page remains in the same detail page. How could I achieve this?
controller:
public with sharing class ServiceOptionsChange_CLS{
public string strId;
public String strOppid{get;set;}
public String strModelCode {get;set;}
public String strVersionCode {get;set;}
public ListlstOptions {get; private set;} ListlstC2Goptions= new List public String strop{get;set;}();
public Service__c objService{get;set;}
public boolean refreshPage{get;set;}
public String strCode {get;set;}
public String strLabel {get;set;}
public MapmapOptionCodePrice = new Map ();
public ServiceOptionsChange_CLS(ApexPages.StandardController controller) {
objService = new Service__c();
strId=ApexPages.currentPage().getParameters().get('id');
Service__c objService=[select Opportunity_car_set__c from Service__c where id=:strId];
strOppid=objService.Opportunity_car_set__c;
Opportunity_car_set__c opp=[SELECT Model__r.ProductCode,Version__r.version_code__c,Country_Code__c FROM Opportunity_car_set__c where id=:strOppid];
strModelCode = opp.Model__r.ProductCode;
strVersionCode = opp.Version__r.version_code__c;
system.debug('<<<<
}
public ListgetOptions(){
OptionDetails_CLS optionValue=new OptionDetails_CLS();
if(String.isNotBlank(strModelCode) && String.isNotBlank(strVersionCode)){
lstC2Goptions=optionValue.getPriceListbasedOnReference(strModelCode,strVersionCode);
}
if(lstC2Goptions.size()>0){
lstOptions = new List(); lstOptions.add(new SelectOption('','--Select--'));
for(String strC2Goptions:lstC2Goptions) {
lstOptions .add(new SelectOption(strC2Goptions,strC2Goptions));
}
}
return lstOptions ;
}
public Pagereference customSave(){
strop=objService.CodeC2G__c;
String strQuantity=String.valueof(objService.Quantity__c);
system.debug('<<<<strCode=strop.substringbefore('-').trim();
strLabel =strop.substringafter('-').trim();
system.debug('<<<<objService.id=strId;
objService.Code__c=strCode;
objService.Label__c=strLabel;
Double dbPriceHT;
OptionDetails_CLS optionValues =new OptionDetails_CLS();
mapOptionCodePrice = optionValues.getOptionPrice(strModelCode,strVersionCode);
if (mapOptionCodePrice.containsKey(strCode)) {
dbPriceHT = mapOptionCodePrice.get(strCode);
}
if (dbPriceHT!=null) {
objService.Price_HT__c=dbPriceHT;
}
try{
update objService;
refreshPage=true;
system.debug('<<<<return null;
}
catch(Exception ex){
System.debug('Error in SOQL Fetching'+ex);
ApexPages.Message msg = new ApexPages.Message(Apexpages.Severity.ERROR, ex.getMessage() );
ApexPages.addMessage(msg);
return null;
}
}
}
vf:
The issue occurs when you first perform DML and then callout in the same transaction You have uncommitted work pending. Please commit or rollback before calling out You need to perform Callout in the future method so your callout and DML will be in the different transaction
This way you can resolve this issue create a list and deserialize it to pass to the future method. Because we can't pas list of as a parameter in the future method
insert listofAccount;
string jsonString = JSON.serializePretty(listofAccount );
callout(jsonString);
In future method make callout
@future(callout = true)
public static void callout(string jsonString){
//do callout here rest or soap
}
This way you can solve this issue.