Salesforce error when calling api web service

Hi, I get the following error when calling the add () function. You have uncommitted work pending. Please commit or rollback before calling out

I call getItems () to populate the drop down list and then the add function to insert the selected item from the drop down list

  public PageReference add() { insert technology; return null; } public List<SelectOption> getItems() { List<SelectOption> options = new List<SelectOption>(); List<Technology__c> AddedT=[SELECT Name FROM Technology__c]; HttpRequest req = new HttpRequest(); req.setMethod('GET'); req.setEndpoint('http://submit.toolsberry.com/sfdc/technologies'); Http http = new Http(); HTTPResponse res = http.send(req); String response=res.getBody(); XmlStreamReader reader = new XmlStreamReader(response); List<String> AllTech = new List<String>(); while(reader.hasNext()) { if (reader.getEventType() == XmlTag.START_ELEMENT) { if ('string' == reader.getLocalName()) { while(reader.hasNext()) { if (reader.getEventType() == XmlTag.END_ELEMENT) { break; } else if (reader.getEventType() == XmlTag.CHARACTERS) { String tname = reader.getText(); AllTech.add(tname); } reader.next(); } } } reader.next(); } } 
+4
source share
1 answer

This is because you need to do all your DML AFTER you finish with any callouts, not before. Therefore, any insert / update / upsert or delete statements should follow any http.send(req); calls http.send(req); .

** It looks like your list is re-populated after calling the add () method, because your list is in the getter method **

This depends on the thread and must be performed in sequence for each thread. So, for example, when a user clicks a button using an action method, all DML statements in this call must follow any callouts that occur in the same thread. The same goes for an Apex trigger or batch.

Having getter / setter somewhere updating the data might somehow cause this. For instance:

 public String someProperty { get { return [SELECT Name FROM CustomObject__c WHERE Id = :this.someId]; } set(String s) { CustomObject__c c = [SELECT Name FROM CustomObject__C WHERE Id = :this.someId] c.Name = s; update c; } } 

Also, never put a leader in a getter. Always put a leader in an explicit method that does this once and only once. Getters will fire several times, and callouts have severe restrictions in Apex.

+7
source

Source: https://habr.com/ru/post/1398076/


All Articles