+ Start a Discussion
DharmendraDharmendra 

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

Hi all,
I've tried alot of solutions for this issue but when I install the package then I received an email with exception info as below:
System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out.

Please find below my code:
global class PostInstallClass implements InstallHandler {
  global void onInstall(InstallContext context) {
      User u = GetUserById(context.installerId());
      try
      {
          if(!Test.isRunningTest())          UpdatePackageInstallationInfo(context.installerId(), u.Email);
      }
      catch(Exception e)
      {
          SendMessage(new String[]{'abc@xyz.com'},'Package failed to install/upgrade','Failed to install/upgraed package. ' + u.Email + ' tried to install/upgraed the package but failed because. Error Details: ' + e);
      }     
  }
    
    public User GetUserById(ID id)
    {
        User u = [Select Id, Email from User where Id =:id];
        return u;
    }
    
    @future(callout=true)
    public static void UpdatePackageInstallationInfo(String organizationId, String userEmail)
    {        
        String url = 'http://demoapi.sunapplabs.com/api/salesforce/updateinstallpackage?organizationid='+organizationId;
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(url);
        req.setMethod('GET');
        HttpResponse responseResult = h.send(req);
        if(responseResult.getBody() == 'true')
        {            
            SendMessage(new String[]{userEmail, 'abc@xyz.com'},'Package install successful','Thanks for installing the package. Response result : '+responseResult);
        }
        else
        {
            SendMessage(new String[]{'abc@xyz.com'},'Package failed to install/upgrade','Failed to install/upgraed package. ' + userEmail + ' tried to install/upgraed the package but failed because of failure from MyAPI response. Response result : '+responseResult);
        }
    }
    public static void SendMessage(String[] toAddresses, String subject, String message)
    {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(toAddresses);
        mail.setReplyTo('abc@xyz.com');
        mail.setSenderDisplayName('My Package Support');
        mail.setSubject(subject);
        mail.setPlainTextBody(message);
        Messaging.sendEmail(new Messaging.Email[] { mail }); 
    }
  }



 
Shashikant SharmaShashikant Sharma
You are sneding an email just after the Http Callout. You can not make a DML statement or send email after after you make callout. Please remove the send message once and check if it works or not.
DharmendraDharmendra
Hi Shashikant,

Thanks for reply,

I'm receiving the email which is sent via exception part of the code, which is occurring after HttpRequest method.
Also, I've created in the send mail and Http callout code in different methods.

If this issue is occurring because of the reason you mentioned then is there any way to implement the above senario i.e. to send email after Http callout. Please suggest.

Thanks
DharmendraDharmendra

Hi Shashikant,

I've removed the send email part and tried again and now its working fine. Thanks for help.

Also, if its possible to include send email part then please suggest.

Thanks
Dharmendra
Gupta.VishalGupta.Vishal
Hi Dharmendra , 

Callouts and DMLs have to be asynchronous , you can not perform DML or send email  after callouts ,
try to send your Exception Email in a future method . 
 
@future
    public static void SendMessage(String[] toAddresses, String subject, String message)
    {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(toAddresses);
        mail.setReplyTo('abc@xyz.com');
        mail.setSenderDisplayName('My Package Support');
        mail.setSubject(subject);
        mail.setPlainTextBody(message);
        Messaging.sendEmail(new Messaging.Email[] { mail }); 
    }
  }


 
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??
HARI KRISHNAHARI KRISHNA
Hi Padayappa,
Before making a callout ensure you do not have any insert/update/delete DML statements. Try to make the callout in a separate context say @future.
bk sbk s
Hi Padayappa,
 You can make use of system.isFuture() method to find if you are in synchronous or asynchronous context and decide what can be done.
If you are in synchoronous mode , you can choose to perform DML in @future and vice versa. Worst case you can break transactions by page reference (GET redirect)