+ Start a Discussion
Sharath ChikkannaSharath Chikkanna 

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

I'm getting this error while i'm running my test class. I have a webservice class which will send sms when i insert a new record or if i update a an existing record

Here are my webservice class, trigger which is invoking webservice call and test class for both class & trigger.

Web Service call

public class CreatingAccountsendsms { 
@Future(callout=true)
    public static void Creating_Lead(string mobile,string leadname,string Uname,string UMobilePhone) {
    
   // list<account> acc=[SELECT Id,Phone FROM Account where id=:conId];
    
                  String Username ='management@abc.com';
                  String Password = '321@admin';
                  String TempID='21341';
                  String MobileNo=mobile;
                  String SenderID = 'ABC';
                  String F1= leadname;
                  String F3= Uname;
                  String F2= UMobilePhone;
                  String F4= '';
       String postData = 'username=' +Username + '&pass=' + Password + '&dest_mobileno=' + MobileNo +'&senderid=' + SenderID + '&tempid=' + TempID+'&F1=' + F1+ '&F2=' + F2+ '&F3=' + F3+'&F4=' + F4;
       
       HttpRequest req = new HttpRequest();
    req.setEndpoint('http://123.01.01.01/blank/sms/user/urlsmstemp.php?'+postdata);
    req.setMethod('GET');
    system.debug(req);
    Http h = new Http();
    HttpResponse res = h.send(req);
    
    //system.debug(res);
    //return res;
    } 

     @Future(callout=true)
    public static void CreatingAccountsendsms1(string mobile,string leadname,string Uname,string UMobilePhone) {
   
   // list<account> acc=[SELECT Id,Phone FROM Account where id=:conId];
   
                  String Username ='management@ABC.com';
                  String Password = '321@admin';
                  String TempID='21342';
                  String MobileNo=mobile;
                  String SenderID = 'ABC';
                  String F1= leadname;
                  String F2= Uname;
                  String F3= UMobilePhone;
                  String F4= 'creatorname';
       String postData = 'username=' +Username + '&pass=' + Password + '&dest_mobileno=' + MobileNo +'&senderid=' + SenderID + '&tempid=' + TempID+'&F1=' + F1+ '&F2=' + F2+ '&F3=' + F3+'&F4=' + F4;
      
       HttpRequest req = new HttpRequest();
    req.setEndpoint('http://123.01.01.01/blank/sms/user/urlsmstemp.php?'+postdata);
    req.setMethod('GET');
    system.debug(req);
    Http h = new Http();
    HttpResponse res = h.send(req);
   
    //system.debug(res);
    //return res;
    }

}

Trigger to invoke my webservice method

trigger sms on Account (after insert,after update) {


for(Account acc:trigger.new)
{
user u=[SELECT Alias,Id,MobilePhone,Name,Phone,ProfileId FROM User where Id=:acc.OwnerId];
Profile p = [SELECT id,Name FROM Profile WHERE Id = :u.profileid];
system.debug('@@@@@@@@@+++++++++++++++++++++++++++++++++++++++++++++++++++++='+p.name);


if(trigger.isafter){
 CreatingAccountsendsms.Creating_Lead(acc.PersonMobilePhone,acc.Lastname,u.name,u.phone);
}
if(trigger.isupdate)
{
user u1=[SELECT Alias,Id,MobilePhone,Name,Phone FROM User where Id=:acc.CreatedById];
if(acc.ownerid != trigger.oldmap.get(acc.id).ownerid )
{
if(p.name=='SPU - Sales Manager' || p.name=='Unishire Sales Profile' || p.name=='Channel Sales Manager')
{
system.debug('@@@@@@@@@+++++++++++++++++++++++++++++++++++++++++++++++++++++='+p.name);
 sendsms.sendsms1(u.MobilePhone,u.name,acc.Lastname,acc.PersonMobilePhone,acc.Project_Interested__c,u1.name);
 CreatingAccountsendsms.CreatingAccountsendsms1(acc.PersonMobilePhone,acc.Lastname,u.name,u.MobilePhone);
 //acc.name=u.Lastname;
//sendsms.sendsms1(acc.Phone1__c,acc.name);
}
}
}
}
}

the above class and trigeer is for Account object and I have same kind of class and trigger for Debit Note also. 

In my test class if i just insert account test method will be passed if i insert new debit note record along with account then i'm getting this callout exception

Error Message : System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out
Stack Trace  :  Class.CreatingAccountsendsms.Creating_Lead: line 50, column 1

Here is my test class

@isTest(SeeAllData=true)
public class new_test_class1{
    @isTest static void Test_lead(){
        
        Account acc= new Account(); 
        acc.name='Acc1';
        acc.Status__c='new';
        acc.Custom_AN__c=1;
        acc.Project_Interested__c='atrium';
        acc.Phone1__c='8015825819';
        acc.Email__c='samdbinu@gmail.com';
        insert acc;
        
        Debit_Note__c DN = new Debit_Note__c();
        DN.Name = 'test';
        DN.Account__c = acc.id;
        insert DN;
        
        
                
        Test.startTest();
         Test.setMock(HttpCalloutMock.class, new Stubby());
         string mobile = '12345';
         string name = 'Sharat';
         string status = 'done';
         string dateon = '1/1/2014';
         string Uname = 'New';
         string Umobile = '90086573';
         string leadname = 'Test';
         string UMobilePhone = '90087345';
        
         CreatingAccountsendsms.CreatingAccountsendsms1(mobile,leadname,Uname,UMobilePhone);
        Test.StopTest();
    }
}



Pramod_SFDCPramod_SFDC
Hi,

I am providing you a answer in general, i hope this helps you to overcome the issue.

A Web Service Callout may not occur after a DML statement within the same transaction. To acheive the required action, the transaction must be separated into two parts so that the DML transaction is completed before the Web Service Callout occurs.


>> This workaround splits the transaction into two separate Ajax processes. The first inserts the record and the second performs the callout and is able to      update the newly inserted record.

<!-- 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.cls

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;
    }
}







Thanks
Pramod
VIVEK KUMAR 105VIVEK KUMAR 105
Hi Sharath, did you get any solution for this problem as I'm facing a similar issue
Pramod_SFDCPramod_SFDC
Check this article : https://help.salesforce.com/apex/HTViewSolution?urlname=Error-You-have-uncommitted-work-pending-Please-commit-or-rollback-before-calling-out&language=en_US
Prajyot KerkarPrajyot Kerkar
Make callout from @future method and call the future (asynchronous) methods after executing DML statements