7

My requirement is getting latitude longitude from google map for that i wrote trigger and used @future callouts. now i need to run batch class to update contact records but contacts not updating showing error:

First error: Update failed. First exception on row 0 with id 00328000001hmXdAAI; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Geolocation: execution of AfterUpdate
caused by: System.AsyncException: Future method cannot be called from a future or batch apex class

4
  • Your explanation could stand to be expanded on. How does your batch class end up calling an @future method? Is it the same @future method that is grabbing the lat/long from Google?
    – Derek F
    Dec 11, 2015 at 14:44
  • Is that possible to redesign you application to avoid execution batch/future methods from future methods? because last is impossible Please, post your code -- probably there is a workaround
    – kurunve
    Dec 11, 2015 at 14:44
  • Hi user123, welcome to SFSE! Please take the time to visit the Help center and read How do I ask a good question. The more details you provide, particularly code you've written, the more likely it is that someone will respond to your question with an answer you'll find helpful.
    – crmprogdev
    Dec 11, 2015 at 14:47
  • 1
    Can you show your code? You could potentially be causing the trigger to fire off from your future method which in turn would call the future method again.
    – dphil
    Dec 11, 2015 at 17:41

2 Answers 2

22

The error is straightforward. To work around it, you need to detect when you're already in an @future or batch context, and then simply not call your @future method(s).

Dan Appleman has a pretty good pattern for this, which he presented at one of his sessions at Dreamforce this year. Defensive Apex Programming

Slides 8-10 are the relevant ones here. For the benefit of others, the defensive @future call pattern looks like this

public void defensiveFutureCall{
    if(System.isFuture() || System.isBatch()){
        regularSyncCall();
    } else {
        if(Limits.getFutureCalls() < Limits.getLimitFutureCalls()){
            doFutureCall();
        } else {
            // Do some explicit notification so that you know your @future call was denied
        }
    }
}

@future
public void doFutureCall(){
    regularSyncCall();
}

public void regularSyncCall(){
    // Put the code, that you'd otherwise put in your @future method, in here
}
1
0

This is a governor limit provided by salesforce that you cannot call another future method from batch/future method. But, you can always call a batch process from another batch process.

Thanks

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