+ Start a Discussion
Sravana SudheerSravana Sudheer 

System. Dml exception: You have uncommitted work pending,please commit before calling out

Hello All,
I am doing an api callout to an 3rd party website and i am writing an schedule class for that. while executing that scheduled calss i am getting the above error saying that you have some uncommitted work pending,please commit before rolling out. I have googled a lot about this and seems like we cannot callout after performing an Dml operations,

But in my code i am not able to seperate Dml and callout. Even i added @future annotation before the method which i used for Callout. It is retrieving the details of the first record after that when going to the second callout it is giving that error.

Basically it is following the unstructured format like doing a callout first and doing DML after that and again going for the callout- Which seems like not a best practice. So any suggestions in code will be a huge help.
@future(callout=true)
    public static void processAllOpenRequisition(){
        bulkify  = true;
       u = [SELECT Username_Broadbean__c,Password_Broadbean__c From USER WHERE id =:UserInfo.getUserId()];
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint('https://api.adcourier.com/hybrid/hybrid.cgi');
        req.setHeader('Content-Type', 'text/xml');
        requisitionRecMap = new Map<id, Recruiting_Activities__c>([SELECT  Time_now__c,Time_From__c FROM Recruiting_Activities__c WHERE EL_Status__c <> 'Closed' AND REcordtype.Name=:'Requisition' ]);
        system.debug('hellooooo'+requisitionRecMap);
          readObject(requisitionRecMap.keySet()); --> Here calling the another method for XML
           req.setBody(xmlData); 
            Http http = new Http();
            req.setTimeout(60000);
             if(!test.isrunningtest()){
                HttpResponse res = http.send(req);
                resbody = res.getBody();
                System.debug('*****'+res.getBody()); // Here you will get the response
             } 
       
            parseTest(); --> It is the method for parsing the data, here we are doing DML operations.
    }
    
    
 public static void readObject(Set<Id> recids){ 
   for(Recruiting_Activities__c ra:[SELECT  Time_now__c,Time_From__c,Req_ID__c  FROM Recruiting_Activities__c where Id IN:recids]){
       JobReference=ra.Req_ID__c;
       xmlData+='<?xml version="1.0" encoding="utf-8" ?>'
                +'<AdCourierAPI>'
                +'<Method>RetrieveApplications</Method>'
                +'<APIKey>3012861772</APIKey>'
                +'<Account>'
                    +'<UserName>'+u.Username_Broadbean__c+'</UserName>'
                    +'<Password>'+u.Password_Broadbean__c+'</Password>'
                +'</Account>'
                +'<Options>'
                    +'<Filter>'
                        +'<JobReference>'+JobReference+'</JobReference>'
                        +'<Times>'
                            +'<TimeFrom>ra.Time_From__c</TimeFrom>'
                            +'<TimeTo>2020-12-24T06:15:00Z</TimeTo>'
                        +'</Times>'
                        +'<Id></Id>'
                        +'<Rank>All</Rank>'
                    +'</Filter>'
                    +'<BodyFormat EncodingType="None" />'
                    +'<EmbedDocuments EncodingType="Base64">true</EmbedDocuments>'
                   +'<XMLFormat EncodingType="Base64">BGT</XMLFormat>'
                    +'<IncludeAddress>false</IncludeAddress>'
                +'</Options>'
            +'</AdCourierAPI>';
       system.debug('--------'+xmlData);
   }     
    
 }

 
Anupam RastogiAnupam Rastogi
Hi Sravana,

Please share the triggering code that is executing this future method.

Thanks
AR
Sravana SudheerSravana Sudheer
@Anupam Rastogi Thank you for responding.
Actually we are executing the logic from processAllOpenRequisition() method. And Parsetest() is the method which we are using to parse the response and inserting the DMLS.  So basically what am i doing is i am just calling processAllOpenRequisition()  method from schedule class and by checking the debugs it is giving me this error.
Thank you,
Sravan
Anupam RastogiAnupam Rastogi
Okay, then please share the code for parseTest().

And are you getting this error while testing or live integration?
Sravana SudheerSravana Sudheer

@Anupam Rastogi

sure. While doing callout i am getting this error in my sandbox.it will go live in next Month.
public class APIRETRIVE{
    public  String resUrl{set;get;}
    public static String parsedData { get; set; }
    public  Boolean sucess{set;get;}
    public  static String emailId='', jobRefId='',applicantName='',ChannelName='',mobileNum='', encryptedResume='',ApplicationTime='';
    public static ID candidateID;
    public static boolean isAttachment=false;
  public static String TimeTo;
public static PageReference parseTest(){
        DOM.Document doc = new DOM.Document();      
          try {
          System.debug('&&&&='+resbody);
            doc.load(resbody);    
            DOM.XMLNode root = doc.getRootElement();
            String newData=parseNodes(root);
            System.debug('!!after parse='+newData);
          } catch (System.XMLException e) {  // invalid XML
            System.debug('!!eroor='+e.getMessage());
          }
          return null;
    }
   private static String parseNodes(DOM.XMLNode node) {
    String result = '\n';
          System.debug('node type='+node.getNodeType());
          if (node.getNodeType() == DOM.XMLNodeType.COMMENT) {
            return 'Comment (' +  node.getText() + ')';
          }
          if (node.getNodeType() == DOM.XMLNodeType.TEXT) {
            return 'Text (' + node.getText() + ')';
          }
          if (node.getNodeType() == DOM.XMLNodeType.ELEMENT) {
            result += 'Element: ' + node.getName();
            System.debug('\\\\\\\\result='+result);
if (node.getText().trim() != '') {
              result += ', text=' + node.getText().trim();
             System.debug('//////result='+result);
}
            DOM.XMLNode prevNode=node;
           System.debug('node name='+node.getName());
          if (node.getName() == 'Email') {
                emailId=node.getText().trim();
            system.debug('sssssssss'+emailId);
            }
           if (node.getName() == 'JobReference') {
                jobRefId=node.getText().trim();
            }
            if (node.getName() == 'Name') {
                applicantName=node.getText().trim();
            }
           if (node.getName() == 'ApplicationTime') {
               ApplicationTime=node.getText().trim();
           system.debug('sravanaaaaaa'+ApplicationTime);
            }
            if (node.getName() == 'ChannelName') {
                ChannelName=node.getText().trim();
             System.debug('%%%channelName='+ChannelName);
 } if (node.getAttributeCount() > 0) { 
                for (Integer i = 0; i< node.getAttributeCount(); i++ ) {
                    result += ', attribute #' + i + ':' + node.getAttributeKeyAt(i) + '=' + node.getAttributeValue(node.getAttributeKeyAt(i), node.getAttributeKeyNsAt(i));
                    System.debug('Reading attachement===='+node.getAttributeValue(node.getAttributeKeyAt(i), node.getAttributeKeyNsAt(i)));

                    if(node.getAttributeValue(node.getAttributeKeyAt(i), node.getAttributeKeyNsAt(i))=='Attachment'){
                        System.debug('trueeeeeee');
                                               // System.debug('atttt data=='+node.getText());
                        isAttachment=true;
                       System.debug('isatt'+isAttachment);  
                    } 
                    System.debug('---------result='+result);
                }  
            }
          System.debug('node name='+node.getName());
            System.debug('issssss='+isAttachment);
            if (node.getName() == 'Doc' &&  isAttachment) {
                isAttachment=false;
                System.debug('encrypteResume=='+encryptedResume.length());
                encryptedResume=node.getText().trim();
                System.debug('pppppppppppphhhh==='+encryptedResume);
            }
           for (Dom.XMLNode child: node.getChildElements()) {
              result += parseNodes(child);
              system.debug('++++++'+result);
             }
       System.debug('%%%email Id='+emailId+' , jonRefId='+jobRefId+', resume len=='+encryptedResume.length());
        if(emailId!='' && jobRefId!='' && encryptedResume.length()!=0){
 System.debug('pppppppppp--'+encryptedResume);
     list<Recruiting_Activities__c> recrutingDetails1 = [select Id,Candidate__r.Name, Candidate__r.Email from Recruiting_Activities__c  where Candidate__r.Email=:emailId and Requisition__c=:rev.id];
    list <Recruiting_Activities__c> recrutingDetails2=[select Candidate__r.Email From Recruiting_Activities__c where RecordType.Name = 'Associate to req' And requisition__c=:rev.id and Recruiting_Activities__c.candidate__r.Email=:emailId];
             list <Contact> ListCandCont= [select id,Name from Contact where Email=:emailId]; 
              system.debug('-------'+ListCandCont);
              System.debug('!##='+recrutingDetails1.size());
                System.debug('!##='+recrutingDetails2.size());
                if(ListCandCont.size()>0)
                    candidateID = ListCandCont[0].Id;
           // Contact c = new Contact();
                if(recrutingDetails1.size()!=0){
                 some action;   
                }
                else{
                    if(ListCandCont.size()!=0){
                   System.debug('!##=second scenario');
                        Schema.DescribeSObjectResult cfrSchema = Schema.SObjectType.Recruiting_Activities__c; 
                        Map<String,Schema.RecordTypeInfo> recruitingRecordTypeInfo = cfrSchema.getRecordTypeInfosByName();
                         Id rtId1 = recruitingRecordTypeInfo.get('Associate to Req').getRecordTypeId(); 
                    Contact candId=[select ID from Contact where Email=:emailId];
                    candidateID = candId.Id;
                         System.debug('candId=='+candId.ID);
          Recruiting_Activities__c newAsr=new Recruiting_Activities__c (Job_Title__c='DBA',Candidate__c=candId.id,Requisition__c=rev.id,Candidate_Source__c=ChannelName,recordtypeid= recruitingRecordTypeInfo.get('Associate to Req').getRecordTypeId());
                             system.debug('-------'+ newAsr);
                                Database.SaveResult[] saveDatarec;
                            try{
                                 saveDatarec=Database.insert(new Recruiting_Activities__c[]{newAsr}, false);
                               system.debug(''+saveDatarec);
                              }catch(Exception e){ 
                                for(Database.SaveResult queryInfo:saveDatarec){
                                    if(queryInfo.isSuccess()){
                                        System.debug('Success='+queryInfo.isSuccess());
                                    } else{
                                        Database.Error err=queryInfo.getErrors()[0];
                                        System.debug('err='+err.getMessage());
                                    }
                                }
                             }   
                          }
                  else{    
                         System.debug('!##=Third scenario email='+emailId);
                         Contact newContact=new Contact(Phone='9999999999',Email=emailId,LastName=applicantName, AccountId='001e000000QTcY1',Type__c='AGS',CurrencyIsoCode='USD');
                           Database.SaveResult[] saveData=Database.insert(new Contact[]{newContact}, false);
                            system.debug('!###'+saveData);
                            
                            for(Database.SaveResult queryInfo:saveData){
                                if(queryInfo.isSuccess()){
                                   candidateID = queryInfo.ID;
                                    System.debug('$$Success='+queryInfo.isSuccess()+' id=='+queryInfo.ID);
                               } else{
                                    Database.Error err=queryInfo.getErrors()[0];
                                    System.debug('err='+err.getMessage());
                                }
                            }
                             Schema.DescribeSObjectResult cfrSchema = Schema.SObjectType.Recruiting_Activities__c; 
                            Map<String,Schema.RecordTypeInfo> recruitingRecordTypeInfo = cfrSchema.getRecordTypeInfosByName();
                            system.debug('***'+recruitingRecordTypeInfo);
                            
                             Id rtId1 = recruitingRecordTypeInfo.get('Associate to Req').getRecordTypeId(); 
                             System.debug('candId===='+candidateID);
   Recruiting_Activities__c newAsr=new Recruiting_Activities__c (Job_Title__c='DBA',Candidate__c=candidateID,Requisition__c=rev.id, Candidate_Source__c=ChannelName,recordtypeid= recruitingRecordTypeInfo.get('Associate to Req').getRecordTypeId());
                                        system.debug('-------'+ newAsr);
                                        Database.SaveResult[] saveDatarec=Database.insert(new Recruiting_Activities__c[]{newAsr}, false);
                                        system.debug(''+saveDatarec);
                                        
                                        for(Database.SaveResult queryInfo:saveDatarec){
                                            if(queryInfo.isSuccess()){
                                                System.debug('Success='+queryInfo.isSuccess());
                                            } else{
                                                Database.Error err=queryInfo.getErrors()[0];
                                                System.debug('err='+err.getMessage());
                                            }
                                        }
                                }//third Scenarios ENDS here
                       } 
                        List<Attachment> ListAttch= new List<Attachment>([SELECT Id FROM Attachment WHERE ParentId =: candidateID  ]);  
                        if(ListAttch.size()>0)
                            delete ListAttch;
                        // Contact cand1=[select ID from Contact where Email=:emailId];
                           Attachment attachment = new attachment();
                        Blob b = EncodingUtil.base64Decode(encryptedResume);
                       attachment.ParentId =candidateID   ;  
                        attachment.Name = 'Candidate attachment';  
                        attachment.Body =b; 
                        
                        insert(attachment);
                
               emailId='';
               jobRefId='';
               encryptedResume='';
               }
            
            return result;
          }
          return '';  //should never reach here 
    }

 
Sravana SudheerSravana Sudheer
@Anupam Rastogi Sorry for a bit meessy code on the top, i will share here the code for Parse Test()
public static PageReference parseTest(){
        DOM.Document doc = new DOM.Document();      
          try {
        System.debug('&&&&='+resbody);
            doc.load(resbody);    
            DOM.XMLNode root = doc.getRootElement();
            String newData=parseNodes(root);
            System.debug('!!after parse='+newData);
          } catch (System.XMLException e) {  // invalid XML
            System.debug('!!eroor='+e.getMessage());
          }
          return null;
}

 private static string parseNodes(DOM.XMLNode node) {
          String result = '\n';
          System.debug('node name='+node.getName());
          if (node.getName() == 'Email') {
                emailId=node.getText().trim();
            system.debug('sssssssss'+emailId);
            }
          if (node.getName() == 'JobReference') {
                jobRefId=node.getText().trim();
          }
                           
            for (Dom.XMLNode child: node.getChildElements()) {
              result += parseNodes(child);
              system.debug('++++++'+result);
            }
           System.debug('%%%email Id='+emailId+' , jobRefId='+jobRefId+');
            if(emailId!='' && jobRefId!=''){
              list <Contact> ListCandCont= [select id,Name from Contact where Email=:emailId]; 
                if(ListCandCont.size()>0)
                    candidateID = ListCandCont[0].Id;
     
                    if(ListCandCont.size()!=0){
                        Schema.DescribeSObjectResult cfrSchema = Schema.SObjectType.Recruiting_Activities__c; 
                        Map<String,Schema.RecordTypeInfo> recruitingRecordTypeInfo = cfrSchema.getRecordTypeInfosByName();
                         Id rtId1 = recruitingRecordTypeInfo.get('Associate to Req').getRecordTypeId(); 
                    Contact candId=[select ID from Contact where Email=:emailId];
                    candidateID = candId.Id;
                         System.debug('candId=='+candId.ID);
     Recruiting_Activities__c newAsr=new Recruiting_Activities__c (Candidate__c=candId.id,Requisition__c=rev.id,Candidate_Source__c=ChannelName);
     system.debug('-------'+ newAsr);
     Database.SaveResult[] saveDatarec;
      saveDatarec=Database.insert(new Recruiting_Activities__c[]{newAsr}, false);
    }
  }
}
Sravana SudheerSravana Sudheer
@Ron Hess
can you please help me with this issue and let me know  where i am doing wrong!
Sravana SudheerSravana Sudheer

@goabhigo 
HEllo Abhi can you share your experience on how your issue gets resolved!
Thanks,

Sravan

ishchopraishchopra
Hey,

How did you resolve the issue?
Sravana SudheerSravana Sudheer
@ishchopra
I completely took off DML's in the callout by adding  values to the list  and then performing DML in the parsetest method in my code above.
ishchopraishchopra
Hey Man,

Here is my code.. i am totally new to apex.. can you tell me what should i do
 
global class EmailReports implements Schedulable 

{
        global void execute(SchedulableContext sc)
        {
               CallSchedule.EmailReports();
              
       }

   }
 
public class CallSchedule {
            
        @future(callout=true)
        public static void EmailReports()
        {

        String ReportID;
        String EvntName;
        
        List<string> reportids = new List<string>{'00OM0000000GzioMAC'};  // reports to send
        List<string> EventName = new List<string>{'EAGC+2016','LNGCAN+2017','CEE+2017','GASASIA+2016','Gastech+2017','GIS+2017'};  // Event Value to be passed runtime 
          
       
       
        if (EventName.size() >0)
        {
        
        for (integer i=0 ; i < 5 ; i++)
        {
        
        ReportID = reportids[0];
        EvntName = EventName[i]; 
          
                           
        ApexPages.PageReference report = new ApexPages.PageReference('/'+ ReportID + '?pv0=' + EvntName +'&csv=1');
              
        Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment();
        attachment.setFileName('report.csv');
        attachment.setBody(Blob.valueof(report.getContent().toString()));
        //attachment.setBody(Blob.valueof(report1.getContent().toString()));
        attachment.setContentType('text/csv');
        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
        message.setFileAttachments(new Messaging.EmailFileAttachment[] { attachment } );
        message.setSubject('Report For' + EventName );
        message.setPlainTextBody('The report is attached.');
        message.setToAddresses( new String[] { 'skh@gmail.com' } );
        Messaging.sendEmail( new Messaging.SingleEmailMessage[] { message } );
       
        }
        }   
     }