function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
manjirimanjiri 

Error while saving external web service response to salesforce database

Hi all,

I am new for Apex development. So please help me out. Any help will be appreciable.
Currently I am using a function in our application in which I am retrieving data from external web services and storing it in Salesforce database. I am calling this function in a ‘for’ loop because this is getting called multiple times based on the selection of checkboxes. At 1st time, this function is working properly but 2nd time, It's giving exception which is as follows:
ERROR: System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out.

Below is the function which is getting called multiple times:
WebService static void getContent(String id)
{
    String response = '';
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    String url = 'url of the web service';
    req.setEndpoint(url);
    req.setMethod('GET');
    HttpResponse res=null;
    try {
        res= h.send(req);
    } catch(System.CalloutException e) {
    System.debug('ERROR: '+ e);
}

Thanks,
Manjiri

Best Answer chosen by Admin (Salesforce Developers) 
Ron HessRon Hess
The message is misleading, you cannot perform DML (insert, update, delete) prior to a callout ( http.send() )

So, you must loop , calling external service up to 10 times, storing all the results in memory, then when you are done calling out, make your updates or inserts.

there is no commit statement that you can perform, your work is automatically committed when you request is finished.

the following will work

query
callout
query
callout
insert

callout
callout
callout
insert or update


the following will fail

callout
insert
callout  <---- fails here


All Answers

Ron HessRon Hess
The message is misleading, you cannot perform DML (insert, update, delete) prior to a callout ( http.send() )

So, you must loop , calling external service up to 10 times, storing all the results in memory, then when you are done calling out, make your updates or inserts.

there is no commit statement that you can perform, your work is automatically committed when you request is finished.

the following will work

query
callout
query
callout
insert

callout
callout
callout
insert or update


the following will fail

callout
insert
callout  <---- fails here


This was selected as the best answer
manjirimanjiri
Hi Ron,
 
Your solution has worked.
Thanks a lot !!
 
Thanks,
Manjiri
 
ritswaney007ritswaney007
hi manjri,
would you mind passing me the code you are using to invoke the external webservice?

cheers
ritesh
manjirimanjiri
Hi,

I have written following code in my apex class. I am calling tripSearch webservice of Yahoo Travel in my code.

If you have not done following step, please do that. That is neccessary to invoke external webservice.

In your salesforce account Go To
Setup-> Security Controls -> Remote Site Settings -> New Remote site ->
Add Remote Site URL as http://travel.yahooapis.com

    WebService static List<Trip> getContent(String start)  
    {
        String response = '';
        Integer count=0;

        // Instantiate a new http object
        Http h = new Http();

        List<Trip> trips = new List<Trip>();        
        
        // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
        HttpRequest req = new HttpRequest();

        // The webservice url -  Pass in the endpoint to be used using the string url
        String url = 'http://travel.yahooapis.com/TripService/V1.1/tripSearch?appid=YahooDemo&start='+start;
        req.setEndpoint(url);
        req.setMethod('GET');
        // Send the request, and return a response
        HttpResponse res = h.send(req);
        
        XmlStreamReader reader = res.getXmlStreamReader();
   
        <!-- here code for xml processing-->
        <!-- put data in trips list-->

         return trips;
}

Thanks
ehrenfossehrenfoss
One other gotcha...if your DML command is tied to a VisualForce rerender directive which has elements driven by callouts, you may see this error then too.
virtcoudvirtcoud

Is there a variant of this problem with outbound HttpRequests and sending mail from APEX i.e

 

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

 

I've seen a situation where I hit this problem when sending a couple of email messages before or after having called out via HttpRequest?   

 

Anyone else seen this? Any guidelines?

 

 

dj_saaspointdj_saaspoint

I had the same problem but couldn't see anything in the APEX API reference guide (my first port of call) to indicate that I was doing anything wrong.

 

Could salesforce document this behavior please.

virtcoudvirtcoud

Wow, just ran into this again and found my own post from last year while looking for an answer. I solved my problem the first time I hit this by doing my callout before the insert as Ron and others suggested. This time I was unable to do this and was saved by @future.

 

I added this to my callout method signature

 

@future (callout = true) public static void myMethod(String foo, String bar)

{

    //Callout here...

 Http h = new Http();
  HttpRequest req = new HttpRequest();
 try
  {
     //c

 

}

 

nwingnwing

 

According to everything I have read I have it setup correctly, but I am still getting the below error........I have an escalated case, but need this working asap.  If anyone has any other ideas......

 

As a possible issue, our network connection went down while in the midst of running/updating/testing the code......  so not sure if something got hung up there and is causing the issue, but prior to that it was running fine. 

 

Apex script unhandled exception by user/organization: *****************/****************

Failed to invoke future method 'public static void updatemethod()'

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

Class.UpdateClosestTower_cls.updatemethod: line 49, column 23 External entry point

Debug Log:

 

BRBR

If we developing a website on Force.com in which case user will create an Opportunity they charge Credit Card. Do we have to split those transactions in 2 different pages? or can be done from the single page?

 

Bhaskar

xx_joel_xxxx_joel_xx

Yes,

I'm seeing the same error.

We try a callout, if it fails send ourselves an email and then try the callout again.

Second callout fails with

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

 

Perhaps there is something about sending an email that queue's up a database operation behind the scenes?

 

Joel

 

deepakMdeepakM

Hi Ron,

 

i m facing same problem but in case i need New inserted ID in my callout , so i need to Insert record first before making Callout

 

Any suggestionns on this?

Aruna06Aruna06

I'm facing the same problem now............what should I do then

xx_joel_xxxx_joel_xx

What I did was saved up all my database operations, then after the callout I executed them all.

 

Joel Schaubert

 

Sravana SudheerSravana Sudheer

@manjiri 
Hello Manjiri,
Can you help me how you seperated dmls and callouts in your code.  i am also facing the same issue . Please see my link.
https://developer.salesforce.com/forums/?state=id#!/feedtype=SINGLE_QUESTION_DETAIL&dc=Developer_Forums&criteria=ALLQUESTIONS&id=906F0000000BKhfIAG.
Thanks,

sravan
 

Swamy PSwamy P
Hello folks, 
Actually am facing the same issue. We are sending callouts and than we are doing DML's...again we are sending callout based on the scenario. I was trying to send all records in one time but my 3rd party people are not accepting because they are accepting only one record at a time. So first iam sending all requests one by one and also getting all responses for each and every request. So atlast i wanted to insert records based on the responses. For every request am getting response...so i just wanted to store the response in onel list, after completing that callout i wanted to do DMLs. How can i achieve this?? will you suggest me?? In the mean while how you resolved your issue?? will you share your idea on my issue and your issue that how you resolved??