2

I have a tough scenario where a future method should be called from a batch.I came across various articles stating that it is not possible. My scenario is i need to send emails for contacts of account .Where the Account id is passed from the batch class and i have scheduled the batch.When i try callouts without future method i get error

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

Is there any way for solving this problem Formation of my class I am not using any http callouts and webservices

global class batch implements batch,schedule,Database.callouts
{
      global void execute(schedulableContext sc)
      {
         /**scheduling batch**//
      }
      global Database.queryLocator start(Database.BatchableContext BC)
      {
           /***collecting data through query and passing list to execute ***/
      }
      global  void execute(Database.BatchableContext BC,List<Service__c> s)
      {
          /***processing the input list and obtaining  list of Ids***/
          /****batchclass.emailcallout(list<id>)   emailcallout is future method***/
      }   
       finish{}
}

public class batchclass
{
     @future(callout=true)
     public static emailcalllout(list<id> ser)
     {
         /***some processs***/
        emailsend es = new emailsend();//calling another class to invoke email  sends   to contacts of particular accounts
        es.sendmail(id,list<>);//account id and list of contacts
     }
}
1
  • @max may well be onto something with his answer, could you elaborate on whats going on in your 'execute' method and also the scope size you've used, is it the default 200? Jan 23, 2014 at 11:13

1 Answer 1

7

Move your callouts before your DML statements.

In other words make sure that all update, insert and delete statements in your execute method occur after any callout statements. A quick search of "uncommitted work" will reveal that there are plenty of questions on this site that address this issue

Here's an example :

Assume you have a queue of "contacts" off accounts, each contact has a url (Url__c) and a state (State__c) . State would be set to EMAIL-PENDING just before you make your callout

This would be a problem and fire the uncommited error :

public void execute( ... )
{

    for(Sobject s : contacts)
    {
        contact.put('State__c', 'EMAIL-PENDING');
        update contact;

        // http callout (contact.Url__c)

        // send-email( contact.emailAddress )'
        contact.put('State__c', 'EMAIL-SENT');
        update contact;
    }
}

Possible solution : modify your logic so that you focus on state showing the emails actually sent ( EMAIL-SENT )

    public void execute( Database.BatchableContext BC, List<SObject> contacts )
    {

        for(Sobject s : contacts)
        {
             // http callout (contact.Url__c)

            // send-email( contact.emailAddress )'
            contact.put('State__c', 'EMAIL-SENT');
            update contact;
        }
    }

Alternative solution, move from a query locator to an iterable in your batch and use the start context to set all work as EMAIL-PENDING. This approach allows you to perform state changes / DML before you make the callout

   global Iterable<...> start(Database.BatchableContext info) {

      for(Sobject s : contacts)
        {
            contact.put('State__c', 'EMAIL-PENDING');
            update contact;
        }

        return....
    }


    public void execute( Database.BatchableContext BC, List<SObject> contacts )
    {
        for(Sobject s : contacts)
        {
            // http callout (contact.Url__c)
            // send-email( contact.emailAddress )'
        }

        for(Sobject s : contacts)
        {
            contact.put('State__c', 'EMAIL-SENT');
            update contact;
        }
    } 
2
  • 1
    Yep i think this could well be the answer here, though i was trying to fill in the gaps in the question tbh to be sure, it's worth extending your answer with some links and further explanation as to why this might be the solution, you'll certainly attract a few more up votes if you do so. Jan 23, 2014 at 11:12
  • @AndrewFawcett please see my question modification i have explained my class stucture Jan 23, 2014 at 12:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .