how to solve callout error? You have uncommitted work pending. Please commit or rollback before calling out

I have written 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 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 List<SelectOption> lstOptions {get; private set;}
List<String> lstC2Goptions= new List<String>();
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 Map<String,Double> mapOptionCodePrice = new Map<String,Double>();

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('<<<<<selected value'+strModelCode+''+strVersionCode);

  } 


public List<SelectOption> getOptions(){

   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<SelectOption>();
        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('<<<<<selected value in save'+strop+'quanity'+strQuantity);
    strCode=strop.substringbefore('-').trim();
    strLabel =strop.substringafter('-').trim();
    system.debug('<<<<<strCode'+strCode+''+strLabel);
    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('<<<<<objService up'+objService);
        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:

<apex:page standardController="Service__c" extensions="ServiceOptionsChange_CLS" sidebar="true" >
<apex:form >
<apex:pageBlock >
<apex:pageblockbuttons location="bottom">
<apex:commandbutton value="Save" action="{!customSave}" /> 
</apex:pageblockbuttons> <apex:pageblocksection columns="2" title="Main Information" >
<apex:selectList size="1" value="{!objService.CodeC2G__c}" >
<apex:selectOptions value="{!Options }" > </apex:selectOptions>
<apex:actionSupport event="onchange" action="{!customSave}" reRender="a" />
</apex:selectList>
<br></br>
<apex:inputfield value="{!objService.Quantity__c}" required="false" />
<apex:pageblocksectionitem />
</apex:pageblocksection>
</apex:pageBlock>
</apex:form>
</apex:page>

Answer

The issue occurs when you first perform DML and then callout in the same transaction

check this doc

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 serialize it to pass to the future method. Because we can’t pas list of sobject 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.

Attribution
Source : Link , Question Author : uma451 , Answer Author : Ratan Paul

Leave a Comment