+ Start a Discussion
Michael MMichael M 

Error when trying to send http callout: System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

Why am I getting this error (error is on the bold line of code below)-- 
System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

public  class S3Controller {
    
    public static void UploadDocToS3Server(string recordId)
    {
        UploadDocument(recordId);
    }
    
    @future(callout=true)
    public static void UploadDocument(string recordId)
    {
        //S3 Key 
        String key = '123'; 
        //S3 Secret Key 
        String secret = '123/123/123';
        String bucket = '123'; 
        String host = 's3-us-east-1.amazonaws.com';
        String method = 'PUT';
        ProfilityCallout service=new ProfilityCallout(key,secret,bucket,method,host);
            ProfilityCallout.UploadDocuments(recordId,key,secret,bucket,method,host);
    
    }

}

public class ProfilityCallout {
 
   
    public  string awsKey {get;set;}
    public   string awsSecret {get;set;}
    public   string bucketName {get;set;}
    public   string methodName {get;set;}
    public static  string hostName {get;set;}
    public  static string statusCode {get;set;}
    public static string bucketNameStatic {get;set;}
    public static string methodNameStatic {get;set;}
    public static string hostNameStatic {get;set;}
    
    public static string awsKeyStatic {get;set;}
    public  static string awsSecretStatic {get;set;}
    
    public  ProfilityCallout(string key, string secret, string bucket, string method, string host){
        awsKey=key;
        awsSecret=secret;
        bucketName=bucket;
        methodName=method;
        hostName=host;
        bucketNameStatic = bucket;
        methodNameStatic = method;
        hostNameStatic = host;
    }
    
    public  string ContentType(string fileType) {
        switch on fileType.toLowerCase()
        {
            when 'docx'
            {
                return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
            }
            when 'csv'
            {
                return 'application/vnd.ms-excel';
            }
            when 'wav'
            { 
                return 'audio/wav';
            }
            when 'wmv'
            {
                return 'video/x-ms-wmv';
            }
            when 'mp3'
            {
                return 'audio/mpeg';
            }
            when 'mp4'
            {
                return 'video/mp4';
            }
            when 'png'
            {
                return 'image/png';
                
            }
            when 'pdf'
            {
                return 'application/pdf';
                
            }
            when else {
                return 'image/jpeg';
            }
        }
    }
    
    public  string CreateAuthHeader(String contentType,
                                   String filename, String formattedDateString,string fileExtension){
                                       string auth;
                                       String stringToSign = this.methodName+'\n\n'+contentType+'\n'+formattedDateString+'\n/'+this.bucketName+'/'+filename.toLowerCase()+ '.'+fileExtension.toLowerCase();
                                       Blob mac = Crypto.generateMac('HMACSHA1', blob.valueof(stringToSign),blob.valueof(this.awsSecret));
                                       String sig = EncodingUtil.base64Encode(mac);
                                       auth = 'AWS' + ' ' + this.awsKey + ':' + sig;
                                       return auth;
                                   }
    
  //  @future(callout=true)
    public static void UploadDocuments(string recordId,string key, string secret, string bucket, string method, string host){
        
        bucketNameStatic = bucket;
        methodNameStatic = method;
        hostNameStatic = host;
        awsKeyStatic=key;
        awsSecretStatic=secret;
            
      //  if(awsSecret.isBlank(this.awsSecret) || string.isBlank(this.awsKey) || string.isBlank(this.bucketName) || string.isBlank(this.hostName))
      //  {
         //   throw new BaseException('Set AWS credential');
      //  }
        List<ContentDocumentLink> links=[SELECT ContentDocumentId,LinkedEntityId FROM ContentDocumentLink where LinkedEntityId=:recordId];
        Set<Id> ids=new Set<Id>();
        for(ContentDocumentLink link:links)
        {
            ids.add(link.ContentDocumentId);
        }
        List<ContentVersion> versions=[SELECT VersionData,Title,ContentDocumentId,FileExtension FROM ContentVersion WHERE ContentDocumentId = :ids AND IsLatest = true];
        
        for(ContentVersion attach:versions) {
         //   try
         //   {
                //File Content
                String attachmentBody = EncodingUtil.base64Encode(attach.VersionData);
                String formattedDateString = Datetime.now().formatGMT('EEE, dd MMM yyyy HH:mm:ss z');
                
                String filename = attach.Title;
       //////FIX LATER         string contentType=ContentType(attach.FileExtension);
         /////       system.debug('contentType:'+contentType);
                
                string fileUrl='https://' + bucketNameStatic + '.' + hostNameStatic + '/' + filename.toLowerCase().remove(' ')+ '.'+attach.FileExtension.toLowerCase();
                HttpRequest req = new HttpRequest();
                req.setMethod(methodNameStatic);
                req.setEndpoint('callout:Seek/'+ filename.toLowerCase()+ '.'+attach.FileExtension.toLowerCase());
                req.setHeader('Host', bucketNameStatic + '.' + hostNameStatic);
                req.setHeader('Content-Length', String.valueOf(attachmentBody.length()));
                req.setHeader('Content-Encoding', 'UTF-8');
         /////       req.setHeader('Content-type', contentType);
                req.setHeader('Connection', 'keep-alive');
                req.setHeader('Date', formattedDateString);
                req.setHeader('ACL', 'public-read');
                Blob pdfBlob = EncodingUtil.base64Decode(attachmentBody);
                req.setBodyAsBlob(pdfBlob);
                   
       //////FIX LATER          req.setHeader('Authorization',CreateAuthHeader(contentType, filename, formattedDateString,attach.FileExtension));
                
                Http http = new Http();
                HTTPResponse res = http.send(req);
               statusCode = string.valueof(res.getStatusCode());
                if (res.getStatusCode() == 200 || res.getStatusCode()==201) {
                     Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
                        message.setSubject('Profility S3 PUT succesful!');
                        message.setPlainTextBody('Profility S3 PUT succesful!');
                        message.setToAddresses( new String[] { '123@123.org' } );
                        Messaging.sendEmail( new Messaging.SingleEmailMessage[] { message } ); 
                 
                }
            
         //   catch(Exception ex)
         else   {
                
                     Messaging.SingleEmailMessage message2 = new Messaging.SingleEmailMessage();
                        message2.setSubject('issue with Profility callout');
                        message2.setPlainTextBody('issue with Profility callout '+statusCode );
                        message2.setToAddresses( new String[] { '123@123.org' } );
                        Messaging.sendEmail( new Messaging.SingleEmailMessage[] { message2 } ); 
            //   throw new BaseException(ex);
            }
        }
    }
}
Best Answer chosen by Michael M
VinayVinay (Salesforce Developers) 
Hi Michael,

This error will occur anytime DML is performed before a callout in the same transaction.  Check below references.

https://help.salesforce.com/articleView?id=000326129&mode=1&type=1
https://help.salesforce.com/articleView?id=000328873&type=1&mode=1

Similar errors
https://salesforce.stackexchange.com/questions/115434/how-to-solve-callout-error-you-have-uncommitted-work-pending-please-commit-or

Hope above information was helpful.

Please mark as Best Answer so that it can help others in the future.

Thanks,

All Answers

VinayVinay (Salesforce Developers) 
Hi Michael,

This error will occur anytime DML is performed before a callout in the same transaction.  Check below references.

https://help.salesforce.com/articleView?id=000326129&mode=1&type=1
https://help.salesforce.com/articleView?id=000328873&type=1&mode=1

Similar errors
https://salesforce.stackexchange.com/questions/115434/how-to-solve-callout-error-you-have-uncommitted-work-pending-please-commit-or

Hope above information was helpful.

Please mark as Best Answer so that it can help others in the future.

Thanks,
This was selected as the best answer
Michael MMichael M
Hi Vinay,

I am not doing any DML in my code... is there something else it can be?
VinayVinay (Salesforce Developers) 
May be debug logs can help you to narrow down the issue.

Thanks,
CM Pandey 7CM Pandey 7
I was getting the same error, however, I decided to update the account before the callout, as I needed to concatenate some values, I followed this strategy, below is a simple example:
 
public static void updateAccount(Id recordId, String City, String PostalCode, String Country, String Street, String State_Province, String AddressType, String Complement, String Neighborhood, String Number_Address){ String Number_Address_nm = Number_Address.replaceAll('[^0-9]', ''); String PostalCode_nm = PostalCode.replaceAll('[^0-9]', ''); String acId = [SELECT Id FROM Account WHERE Id =: recordId LIMIT 1].Id; Account ct = new Account(); ct.Id = acId; ct.BillingCity = City; ct.BillingCountry = Country; ct.BillingPostalCode = PostalCode_nm; ct.BillingState = State_Province; ct.BillingStreet = AddressType + ' ' + Street + ' Nº: ' + Number_Address_nm + ' ' + Complement + ' BAIRRO: ' + Neighborhood ; update ct; } @future(callout=true) public static void Call_API(Id recordId, String City, String PostalCode, String Country, String Street, String State_Province, String AddressType, String Complement, String Neighborhood, String Number_Address){ ChangeAddressAPI.CallChangeAddressAPI(recordId, City, PostalCode, Country, Street, State_Province, AddressType, Complement, Neighborhood, Number_Address); } }



Here are my few sites links, look how it is...
Play free games online without downloading I know the link should not post here but I need your review, hope you don't mind...Sorry..
Giancarlo BaileyGiancarlo Bailey
Thanks a lot for the explanation.
Giancarlo BaileyGiancarlo Bailey
I also had a similar problem when I tried to open certain sites that are related to gambling and casinos. Now I start playing online casinos more often. On the site https://pokiesman.com/free-pokies/buffalo-gold/ I learned about the Buffalo Gold slot machine. The Buffalo Gold slot machine is one of the most successful recent releases of Aristocrat and I've always wanted to try to play it.