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
}
}
Best Answer
Move your callouts before your DML statements.
In other words make sure that all
update
,insert
anddelete
statements in yourexecute
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 issueHere'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 calloutThis would be a problem and fire the
uncommited
error :Possible solution : modify your logic so that you focus on state showing the emails actually sent ( EMAIL-SENT )
Alternative solution, move from a
query locator
to aniterable
in your batch and use thestart
context to set all work as EMAIL-PENDING. This approach allows you to perform state changes / DML before you make the callout