调用Web服务API时出现Salesforce错误

时间:2012-02-23 16:41:10

标签: salesforce apex-code visualforce

当我调用函数add()时出现以下错误 You have uncommitted work pending. Please commit or rollback before calling out

我调用getItems()填充下拉列表,然后调用add函数从下拉列表中插入所选项目

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

1 个答案:

答案 0 :(得分:7)

这是因为你需要在完成任何标注之后完成所有DML,而不是之前。因此,任何insert / update / upsert或delete语句都必须关注任何http.send(req);次调用。

**看起来你的列表在调用add()方法后会重新填充,因为你的列表存在于getter方法中**

这是特定于线程的,必须按照任何给定线程的顺序出现。因此,例如,当用户单击带有操作方法的按钮时,该调用中的所有DML语句都必须遵循在同一线程中发生的任何调用。对于触发器或批处理Apex也是如此。

在某处以某种方式更新数据的getter / setter会导致这种情况。例如:

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

另外,永远不要在getter中添加标注。始终将callout放在一个只执行一次的显式方法中。 Getter将被多次解雇,并且标注在Apex中有严格的限制。