Calling future method from Batch

  • I have a requirement where a future method need to be called from batch apex ,I came across various articles stating that a future method could not be called from the batch. Is there any alternate solutions for that?

  • UPDATED ANSWER

    (not batch but...).

    I was investigating the ScheduledDispatcher: https://gist.github.com/gbutt/11151983

    And lo and behold this works:

    global class ScheduledDispatcher Implements Schedulable{
    
        public Interface IScheduleDispached{
            void execute(SchedulableContext sc);
        }
    
        global void execute(SchedulableContext sc){
            Type targetType = Type.forName('{HANDLERNAME');
            if(targetType != null){
                IScheduleDispached obj = (IScheduleDispached)targetType.newInstance();
                obj.execute(sc);
            }
        }
    
    
    }
    
    public class {HANDLERNAME} implements ScheduledDispatcher.IScheduleDispached {
    
      public void execute(SchedulableContext sc)
        {
    
            //Call your Future Method Here
    
        } 
    
    }
    

    If you still need to do it from within the batch context you can do as previously suggested:

    public static method1(){
    
       method2();
    
    }
    
    @future
    public static method2(){
    
    }
    

    call method1 from the batch and method2 from elsewhere

    This is a major limitation because we may not directly be calling the class from the Batch class, but a trigger may fire which would call a future method.

    Which is why you need to check for that condition. Also, during the batch, any future methods that need to be ran should be directly called

    It sounds like he needs the functionality from that trigger (including the asynchronous part), for example - if he is doing anything with Setup objects and Non-Setup objects he will not be able to make the call synchronously.

  • This is a problem: Future methods cannot be called from Batch processes. In my experience, it's best to test for this before running triggered future methods:

    public void runContactUpdates(list<Contact> triggernew)
    {
        if (System.isFuture() || System.isBatch())
             runContactUpdatesNow(triggernew);
        else
            runContactUpdatesFuture((new map<Id, Contact>(triggernew)).keyset());
    }
    
    @Future
    public void runContactUpdatesFuture(set<Id> conids)
    {
    
        runContactUpdatesNow([select Id, Name from Contact where Id in :conids]);
    }
    
    public void runContactUpdatesNow(list<Contact> triggernew)
    {
        //do updates to contacts. Maybe update to database
    }
    

    My real scenario is Im using batch process to collect a bunch of accounts and i have scheduled that batch with batch size 1.Then I need future callout to send emails for the contacts of the account asynchronously.When i try this without @future im getting error like "you have uncommited works"

    I don't understand why you would need @future to just send emails. If you post your code, we may be able to help.

  • The general solution to this and other async problems (i.e. unlimited future calls) was proposed with code samples by Dan Appleman at Dreamforce 13.

    The code can be found at http://advancedapex.com/dreamforce13/

    The essence of the solution is to use a custom object to store all async requests and then have a scheduled class launch a batch job to process each async request one-by-one, restarting the scheduled job in the finish() method if there are new async requests created since the batch was started.

    this pattern has been updated in V3 of the book to use Queueables

    The video link you had shared is not showing in youtube , it says `Video is unavailable and video is private`

  • In case anyone is looking for a better solution, I may have one. While @Future cannot be called from a batch class, a webservice can. A webservice can also call an @future method. So have your batch class call an apex webservice that in turn calls your @future method.

    There is one trick here. To call your webservice from the batch class, you need a session Id. Don't call Userinfo.getsessionid from a scheduled batch class. You won't get a result. Instead, call Userinfo.getsessionId from your scheduleable class and pass the id into your batch class as a parameter. Now you have everything you need to call @Future from a batch.

    as of winter 19; UserInfo.getSessionId() will return a value for batchable transactions

  • A future method can be invoked from the Finish method of batch apex, of course it will not allow from the Execute method. I did test it for one of my requirements and future call is invoking from the Finish method with out any issues

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM