+ Start a Discussion
deepakMdeepakM 

"System.CalloutException: . Please commit or rollback before calling out"?

Hi all 

 

i am getting the above strange error ("System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out") on one custom button click in salesforce.what i did is just fetch the value  and then pass paramters to url in http get as shown below:

 

   public PageReference Clone() 
  {
    Test_Flight_Request__c clFR = new Test_Flight_Request__c(); 
    Test_Flight_Request__c oldFR = [SELECT From__c, To__c,Outbound_del__c,Pax_del__c,Region_del__c,    
        Inbound_del__c,Outbound_Flexibility__c,Inbound_Flexibility__c,Opportunity__c,
        Budget__c,Flight_Request_Type__c,Publish_Fare__c,Searcher__c,Notes__c,Email_To__c,Email_Content__c,
        Subject__c,Status__c,Miles__c,Internal_Flight__c,Approx_Tax__c,Searcher_Notes__c,Field1__c
       FROM Test_Flight_Request__c WHERE Id = :fr.Id];

    clFR.From__c = oldFR.From__c;
    clFR.To__c = oldFR.To__c;
    clFR.Outbound_del__c = oldFR.Outbound_del__c;
    clFR.Pax_del__c = oldFR.Pax_del__c;
    clFR.Region_del__c = oldFR.Region_del__c;
    clFR.Inbound_del__c = oldFR.Inbound_del__c;
    clFR.Outbound_Flexibility__c = oldFR.Outbound_Flexibility__c;
    clFR.Inbound_Flexibility__c = oldFR.Inbound_Flexibility__c;
    clFR.Opportunity__c = oldFR.Opportunity__c;
    clFR.Budget__c = oldFR.Budget__c;
    clFR.Publish_Fare__c = oldFR.Publish_Fare__c;
    clFR.Flight_Request_Type__c = oldFR.Flight_Request_Type__c;
    clFR.Notes__c = oldFR.Notes__c;
    
    clFR.Searcher__c = oldFR.Searcher__c;
    
    clFR.Email_To__c = oldFR.Email_To__c;      
    clFR.Email_Content__c = oldFR.Email_Content__c;
    clFR.Subject__c = oldFR.Subject__c;
    
    clFR.Status__c = oldFR.Status__c;
    clFR.Miles__c = oldFR.Miles__c;
    clFR.Internal_Flight__c = oldFR.Internal_Flight__c;
    clFR.Approx_Tax__c = oldFR.Approx_Tax__c;
    clFR.Searcher_Notes__c = oldFR.Searcher_Notes__c;
    clFR.Field1__c = oldFR.Field1__c;
    insert clFR;
    System.debug('Old FRId:'+oldFR.Id);
       System.debug('New FRId:'+clFR.Id);
       
    Http http = new Http();
       HttpRequest httpreq = new HttpRequest();
       httpreq.setEndpoint('http://abcs.com');
   
      httpreq.setMethod('GET');
      httpreq.setTimeout(60000);
      String responseBody='';
      if (!Test.isRunningTest())
      { 
      HttpResponse  httpres =  http.send(httpreq);
    
      }
      else
      {
       responseBody = '200,4,48.5,-123.67';
      }
      
        PageReference pr = new PageReference('/'+  Id);
        pr.setRedirect(true);
        return pr;
  }
  
 
Pleas help me.
 
bob_buzzardbob_buzzard

The issue here is that you have carried out the insert before you attempt the callout.  If the platform allowed this it would cause the transaction to hang and block others.  Are you using the id from the inserted record in the callout?  If not, you can move the insert after the callout.

deepakMdeepakM

yes, after insert i am using the id 

bob_buzzardbob_buzzard

In that case you have to carry out the callout asynchronously - via an @future method is one way.  Do you need to use the results of the callout in your VF page?

deepakMdeepakM

hi bob

 

i did that also but getting test coverage the below is the url of post 

 http://boards.developerforce.com/t5/Apex-Code-Development/Test-coverage-issue/td-p/455291

 

thank in advance

 

bob_buzzardbob_buzzard

That's the solution I'm afraid.  You should only have to avoid the actual callout in your test code - what lines aren't getting covered?

deepakMdeepakM

this line HttpResponse httpres = http.send(httpreq);

is not coverd

bob_buzzardbob_buzzard

Is it just that line?  26% not covered seems a lot for one line.

deepakMdeepakM

yh just that line causes the issue

deepakMdeepakM

bob i also did one trick but stuck in one point below is the code:

 

 
 public static boolean isApexTest = false;
public PageReference  CloneFlightRequest()
  {
    Test_Flight_Request__c clFR = new Test_Flight_Request__c(); 
    Test_Flight_Request__c oldFR = [SELECT From__c, To__c,Outbound_del__c,Pax_del__c,Region_del__c,    
        Inbound_del__c,Outbound_Flexibility__c,Inbound_Flexibility__c,Opportunity__c,
        Budget__c,Flight_Request_Type__c,Publish_Fare__c,Searcher__c,Notes__c,Email_To__c,Email_Content__c,
        Subject__c,Status__c,Miles__c,Internal_Flight__c,Approx_Tax__c,Searcher_Notes__c,Field1__c
       FROM Test_Flight_Request__c WHERE Id = :fr.Id];

    clFR.From__c = oldFR.From__c;
    clFR.To__c = oldFR.To__c;
    clFR.Outbound_del__c = oldFR.Outbound_del__c;
    clFR.Pax_del__c = oldFR.Pax_del__c;
    clFR.Region_del__c = oldFR.Region_del__c;
    clFR.Inbound_del__c = oldFR.Inbound_del__c;
    clFR.Outbound_Flexibility__c = oldFR.Outbound_Flexibility__c;
    clFR.Inbound_Flexibility__c = oldFR.Inbound_Flexibility__c;
    clFR.Opportunity__c = oldFR.Opportunity__c;
    clFR.Budget__c = oldFR.Budget__c;
    clFR.Publish_Fare__c = oldFR.Publish_Fare__c;
    clFR.Flight_Request_Type__c = oldFR.Flight_Request_Type__c;
    clFR.Notes__c = oldFR.Notes__c;
    
    clFR.Searcher__c = oldFR.Searcher__c;
    
    clFR.Email_To__c = oldFR.Email_To__c;      
    clFR.Email_Content__c = oldFR.Email_Content__c;
    clFR.Subject__c = oldFR.Subject__c;
    
    clFR.Status__c = oldFR.Status__c;
    clFR.Miles__c = oldFR.Miles__c;
    clFR.Internal_Flight__c = oldFR.Internal_Flight__c;
    clFR.Approx_Tax__c = oldFR.Approx_Tax__c;
    clFR.Searcher_Notes__c = oldFR.Searcher_Notes__c;
    clFR.Field1__c = oldFR.Field1__c;
    insert clFR;
    System.debug('Old FRId:'+oldFR.Id);
       System.debug('New FRId:'+clFR.Id);
     
      Http h = new Http();
      HttpRequest req = CloneMethod(ID,oldFR.Id,clFR.Id);
       System.debug('Deepak:'+req);
               
        isApexTest = true;
         if(!isApexTest)
         {
              HttpResponse res = invokeWebService(h, req);  
        } 
          else
          {
           System.debug('Salesforce');
          }
          PageReference pr = new PageReference('/'+  Id);
          pr.setRedirect(true);
          return pr;
          
  }
  public static HttpRequest  CloneMethod(string fid, string oldid,string newid)
     {
       
       HttpRequest httpreq = new HttpRequest();
      // httpreq.setEndpoint('http://testsite.com/CloneFlightData?opportunityId='+fid+'&oldFlightRequestID='+oldid+'&newFlightRequestID='+newid);
       //  httpreq.setEndpoint('http://testsite.com/CloneFlightData?opportunityId='+Id+'&oldFlightRequestID='+oldFR.Id+'&newFlightRequestID='+clFR.Id);
         httpreq.setEndpoint('http://localhost:56315/ItineraryBuilder/CloneFlightData?opportunityId='+fid+'&oldFlightRequestID='+oldid+'&newFlightRequestID='+newid);
         httpreq.setMethod('GET');
       httpreq.setTimeout(60000);
        
       return httpreq;
     }
     
     
     public static HttpResponse invokeWebService(Http h, HttpRequest req)
     {
        System.debug('mahajan:'+req); 
           HttpResponse res = h.send(req);
           System.debug('Http response:'+res);
           return res;
        }

its deployed but as you see code that 

  if(!isApexTest)
         {
              HttpResponse res = invokeWebService(h, req);  
        } 
esle{} as it always render the esle part so i cant get httprespose ..
i hope you get what i mean.
bob_buzzardbob_buzzard

It will always render the else part, as you have set isApexTest to true.

deepakMdeepakM

yh i know but when i using

 

 if(isApexTest)
         {
              HttpResponse res = invokeWebService(h, req);  
        } 
agian it not deploy and gives the code coverge issue
bob_buzzardbob_buzzard

You should use Test.IsRunningTest to determine if you are executing in a unit test context.

deepakMdeepakM

you mean in test class or in main class

bob_buzzardbob_buzzard

In the main class.

deepakMdeepakM

bob i tried but now i get the error on button click system.callout again

bob_buzzardbob_buzzard

If you are getting the error that you need to commit the transaction, you need to put the callout into an @future method - the test/non-test side of things doesn't affect that.

deepakMdeepakM

Following Red lins are not covered

 

public with sharing class TestFlighRequestPage {
Test_Flight_Request__c fr;
public String Id {get; set;}
private String result;
public static boolean isApexTest = false;
public TestFlighRequestPage(ApexPages.StandardController stdController)
{
fr = (Test_Flight_Request__c)stdController.getRecord();

Id = fr.Opportunity__c;
}

public PageReference Save()
{
update fr;
PageReference pr = new PageReference('/'+ Id);
pr.setRedirect(true);
return pr;
}

public void SendItineryEmail()
{
Test_Flight_Request__c FRdata = [SELECT Email_To__c, Email_Content__c,Subject__c
FROM Test_Flight_Request__c WHERE Id = :fr.Id];

Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('http://testsite.com/GetCustomerView?opportunityId='+fr.Opportunity__c+'&flightRequestID='+fr.Id);
req.setMethod('GET');

HttpResponse res = h.send(req);
result = res.getBody();
String[] toaddress = new String[]{};
toaddress.add(FRdata.Email_To__c);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(toaddress);
string EmailSubject ='';
if(FRdata.Subject__c !=null)
{
EmailSubject = FRdata.Subject__c;
}
else
{
EmailSubject ='Flight stat';
}
mail.setSubject(EmailSubject);
string emaildata='';
if(FRdata.Email_Content__c != null)
{
emaildata = FRdata.Email_Content__c + '<br>' + result;
}
else
{
emaildata = result;
}

mail.setHtmlBody(emaildata);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}

public void TestCloneFlightRequest()
{
isApexTest = true;
CloneFlightRequest();
}


public PageReference CloneFlightRequest()
{
Test_Flight_Request__c clFR = new Test_Flight_Request__c();
Test_Flight_Request__c oldFR = [SELECT From__c, To__c,Outbound_del__c,Pax_del__c,Region_del__c,
Inbound_del__c,Outbound_Flexibility__c,Inbound_Flexibility__c,Opportunity__c,
Budget__c,Flight_Request_Type__c,Publish_Fare__c,Searcher__c,Notes__c,Email_To__c,Email_Content__c,
Subject__c,Status__c,Miles__c,Internal_Flight__c,Approx_Tax__c,Searcher_Notes__c,Field1__c
FROM Test_Flight_Request__c WHERE Id = :fr.Id];

clFR.From__c = oldFR.From__c;
clFR.To__c = oldFR.To__c;
clFR.Outbound_del__c = oldFR.Outbound_del__c;
clFR.Pax_del__c = oldFR.Pax_del__c;
clFR.Region_del__c = oldFR.Region_del__c;
clFR.Inbound_del__c = oldFR.Inbound_del__c;
clFR.Outbound_Flexibility__c = oldFR.Outbound_Flexibility__c;
clFR.Inbound_Flexibility__c = oldFR.Inbound_Flexibility__c;
clFR.Opportunity__c = oldFR.Opportunity__c;
clFR.Budget__c = oldFR.Budget__c;
clFR.Publish_Fare__c = oldFR.Publish_Fare__c;
clFR.Flight_Request_Type__c = oldFR.Flight_Request_Type__c;
clFR.Notes__c = oldFR.Notes__c;

clFR.Searcher__c = oldFR.Searcher__c;

clFR.Email_To__c = oldFR.Email_To__c;
clFR.Email_Content__c = oldFR.Email_Content__c;
clFR.Subject__c = oldFR.Subject__c;

clFR.Status__c = oldFR.Status__c;
clFR.Miles__c = oldFR.Miles__c;
clFR.Internal_Flight__c = oldFR.Internal_Flight__c;
clFR.Approx_Tax__c = oldFR.Approx_Tax__c;
clFR.Searcher_Notes__c = oldFR.Searcher_Notes__c;
clFR.Field1__c = oldFR.Field1__c;
insert clFR;
System.debug('Old FRId:'+oldFR.Id);
System.debug('New FRId:'+clFR.Id);

if(!isApexTest)
{
CloneMethod(ID,oldFR.Id,clFR.Id);
}
else
{
System.debug('Salesforce');
}
PageReference pr = new PageReference('/'+ Id);
pr.setRedirect(true);
return pr;
}

@Future(callout=true)
public static void CloneMethod(string fid, string oldid,string newid)
{
Http h = new Http();
HttpRequest httpreq = new HttpRequest();
httpreq.setEndpoint('http://testsite.com/ibb/CloneFlightData?opportunityId='+fid+'&oldFlightRequestID='+oldid+'&newFlightRequestID='+newid);
httpreq.setMethod('GET');
httpreq.setTimeout(60000);

HttpResponse res = h.send(httpreq);
}
}

 

 

Here is the Test case

 

@isTest
private class TestFlighRequestPageTestCase {

static testMethod void myUnitTest() {
Test_Flight_Request__c fr;
List<Opportunity> listOpp;
String Id ;
String result;
boolean isApexTest = true;

Opportunity opp = new Opportunity();
opp.Name = 'Test Opp';
opp.StageName = 'Ticketing';
opp.p1_First_Name__c ='A';
opp.p1_Last_Name__c ='D';
opp.p1_Gender__c = 'S';
opp.p1_First_Name__c ='S';
opp.p1_Last_Name__c ='A';
opp.p1_Gender__c = 'D';
opp.DOB_Main_Passenger__c = System.now().date();
opp.Number_of_Passengers__c = 4;
opp.CloseDate = System.now().date();
opp.Departure_Date__c = System.now().date();
opp.Origin_City__c = 'DEL';
opp.Destination_City__c= 'MUI';
opp.Return_Date__c = System.now().date();
insert opp;

fr = new Test_Flight_Request__c();
fr.Budget__c = '23';
fr.Publish_Fare__c = '35';
fr.Opportunity__c = opp.Id;
fr.From__c = opp.Origin_City__c;
fr.To__c = opp.Destination_City__c;
fr.Outbound_del__c = opp.Departure_Date__c;
fr.Pax_del__c = opp.Number_of_Passengers__c;
fr.Region_del__c = opp.Destination_Zone__c;
fr.Inbound_del__c = opp.Return_Date__c;
fr.Outbound_Flexibility__c = opp.Flexibility_From__c;
fr.Inbound_Flexibility__c = opp.Flexibility_To__c;
fr.Email_To__c ='anil@swiftsetup.com';
fr.Email_Content__c= 'Test';
fr.Subject__c ='subject test';

insert fr;



ApexPages.StandardController sc = new ApexPages.StandardController(fr);
TestFlighRequestPage sc1 = new TestFlighRequestPage(sc);
sc1.Save();
sc1.TestCloneFlightRequest();
sc1.SendItineryEmail();
update fr;




}
}

bob_buzzardbob_buzzard

The way I'd normally handle this is to only carry out the callout if not in test mode, but if it is in test mode, fake a response that the rest of the code can process.

deepakMdeepakM

i think i did same

 

using isApexTest = true

is set it to not call CloneMethod() from Test case which send request

 

Please Let me know if i m doing wrong?

 

when followed this

 

http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/

 

getting same error  "System.CalloutException: . Please commit or rollback before calling out"

bob_buzzardbob_buzzard

You shouldn't need ifApexTest=true - use the platform version to check if you are in the test context.

deepakMdeepakM

bob sorry to disturb you agian but i really stuck .i did what you said me like below code: let me know where i am wrong.as test coverage is not upto 75%.

 

public PageReference CloneFlightRequest()
{
Test_Flight_Request__c clFR = new Test_Flight_Request__c();
Test_Flight_Request__c oldFR = [SELECT From__c, To__c,Outbound_del__c,Pax_del__c,Region_del__c,
Inbound_del__c,Outbound_Flexibility__c,Inbound_Flexibility__c,Opportunity__c,
Budget__c,Flight_Request_Type__c,Publish_Fare__c,Searcher__c,Notes__c,Email_To__c,Email_Content__c,
Subject__c,Status__c,Miles__c,Internal_Flight__c,Approx_Tax__c,Searcher_Notes__c,Field1__c
FROM Test_Flight_Request__c WHERE Id = :fr.Id];

clFR.From__c = oldFR.From__c;
clFR.To__c = oldFR.To__c;
clFR.Outbound_del__c = oldFR.Outbound_del__c;
clFR.Pax_del__c = oldFR.Pax_del__c;
clFR.Region_del__c = oldFR.Region_del__c;
clFR.Inbound_del__c = oldFR.Inbound_del__c;
clFR.Outbound_Flexibility__c = oldFR.Outbound_Flexibility__c;
clFR.Inbound_Flexibility__c = oldFR.Inbound_Flexibility__c;
clFR.Opportunity__c = oldFR.Opportunity__c;
clFR.Budget__c = oldFR.Budget__c;
clFR.Publish_Fare__c = oldFR.Publish_Fare__c;
clFR.Flight_Request_Type__c = oldFR.Flight_Request_Type__c;
clFR.Notes__c = oldFR.Notes__c;

clFR.Searcher__c = oldFR.Searcher__c;

clFR.Email_To__c = oldFR.Email_To__c;
clFR.Email_Content__c = oldFR.Email_Content__c;
clFR.Subject__c = oldFR.Subject__c;

clFR.Status__c = oldFR.Status__c;
clFR.Miles__c = oldFR.Miles__c;
clFR.Internal_Flight__c = oldFR.Internal_Flight__c;
clFR.Approx_Tax__c = oldFR.Approx_Tax__c;
clFR.Searcher_Notes__c = oldFR.Searcher_Notes__c;
clFR.Field1__c = oldFR.Field1__c;
insert clFR;
if(!Test.isRunningTest()){
CloneMethod(ID,oldFR.Id,clFR.Id);
}
PageReference pr = new PageReference('/'+ Id);
pr.setRedirect(true);
return pr;
}

@Future(callout=true)
public static void CloneMethod(string fid, string oldid,string newid)
{
Http h = new Http();
HttpRequest httpreq = new HttpRequest();
httpreq.setEndpoint('http://testsite.com/CloneFlightData?opportunityId='+fid+'&oldFlightRequestID='+oldid+'&newFlightRequestID='+newid);
httpreq.setMethod('GET');
httpreq.setTimeout(60000);

HttpResponse res = h.send(httpreq);
}

 

Test CAse

 

@isTest
private class TestFlighRequestPageTestCase {

static testMethod void myUnitTest() {
Test_Flight_Request__c fr;
List<Opportunity> listOpp;
String Id ;
String result;

Opportunity opp = new Opportunity();
opp.Name = 'Test Opp';
opp.StageName = 'Ticketing';
opp.p1_First_Name__c ='A';
opp.p1_Last_Name__c ='D';
opp.p1_Gender__c = 'S';
opp.p1_First_Name__c ='S';
opp.p1_Last_Name__c ='A';
opp.p1_Gender__c = 'D';
opp.DOB_Main_Passenger__c = System.now().date();
opp.Number_of_Passengers__c = 4;
opp.CloseDate = System.now().date();
opp.Departure_Date__c = System.now().date();
opp.Origin_City__c = 'DEL';
opp.Destination_City__c= 'MUI';
opp.Return_Date__c = System.now().date();
insert opp;

fr = new Test_Flight_Request__c();
fr.Budget__c = '23';
fr.Publish_Fare__c = '35';
fr.Opportunity__c = opp.Id;
fr.From__c = opp.Origin_City__c;
fr.To__c = opp.Destination_City__c;
fr.Outbound_del__c = opp.Departure_Date__c;
fr.Pax_del__c = opp.Number_of_Passengers__c;
fr.Region_del__c = opp.Destination_Zone__c;
fr.Inbound_del__c = opp.Return_Date__c;
fr.Outbound_Flexibility__c = opp.Flexibility_From__c;
fr.Inbound_Flexibility__c = opp.Flexibility_To__c;
fr.Email_To__c ='anil@swiftsetup.com';
fr.Email_Content__c= 'Test';
fr.Subject__c ='subject test';

insert fr;



ApexPages.StandardController sc = new ApexPages.StandardController(fr);
TestFlighRequestPage sc1 = new TestFlighRequestPage(sc);
sc1.Save();
sc1.CloneFlightRequest();
sc1.SendItineryEmail();
update fr;




}
}

 

thnks in advance

 

 

the red lines are not covered

bob_buzzardbob_buzzard

You need to mark the lines that don't have coverage.

deepakMdeepakM

red lines are not covered

bob_buzzardbob_buzzard

If I were you I'd call the @future method regardless, and then just not carry out the final callout in that method.  That way you'll get the coverage for that method.

Richie DRichie D

As Bob suggests, try changing the code to:-

 

.
.
.
clFR.Searcher_Notes__c = oldFR.Searcher_Notes__c;
clFR.Field1__c = oldFR.Field1__c;
insert clFR;
//if(!Test.isRunningTest()){
CloneMethod(ID,oldFR.Id,clFR.Id);
//}
PageReference pr = new PageReference('/'+ Id);
pr.setRedirect(true);
return pr;
}

@Future(callout=true)
public static void CloneMethod(string fid, string oldid,string newid)
{
Http h = new Http();
HttpRequest httpreq = new HttpRequest();
httpreq.setEndpoint('http://itinerary.swiftsetup.com/ItineraryBuilder/CloneFlightData?opportunityId='+fid+'&oldFlightRequ...
httpreq.setMethod('GET');
httpreq.setTimeout(60000);
if(!Test.isRunningTest()){
HttpResponse res = h.send(httpreq);
}
}

 Just do the callout if you are not running a test.

 

Rich.

SForceBeWithYouSForceBeWithYou

Actually, "and it goes a little something like this... hit it!"

 

  1. Upload Static Resource text file containing response body (I'll call it 'MyStaticResponseBody')
  2. Write the test like normal with a few additions:
private static testmethod testCloneWithCallout(){
    StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
    mock.setStaticResource('MyStaticResponseBody');
    mock.setStatucCode(200); // Success
    mock.setHeader('Content-Type', 'text/plain');
    
    ////////////////////////////////////////////////////
    // Code to set up data, page, controller, etc....
    // .........................................
    ////////////////////////////////////////////////////
    
    Test.setMock(HttpCalloutMock.class, mock);
    ctrlr.clone();
    
    ////////////////////////////////
    // Assertions, etc............
    ////////////////////////////////
}

 You'll probably want a test named "testCloneSuccess" and "testCloneFailure", or some other permutation of all possible outcomes you want to test. Obviously, upload different static resources named appropriately, and build the appropriate mock in your test class.  You can use multiple mocks in one test class for different calls.

 

All in the Apex Reference documentation under "Reference > Apex Classes > HTTP (RESTful) Services Classes > HTTP Classes > Testing HTTP Callouts > Testing HTTP Callouts Using Static Resources".  If you feel like it, you can also create a class implementing the HttpCalloutMock Interface.

 

Enjoy!

 

Nathan Pepper

youtube.com/MayTheSForceBWithYou

@SForceBeWithYou

Salesforc expertSalesforc expert

Is there another way to handle this exception without using future method?