0

I have two sets of 250k records I need to update in production. I am trying to figure out the best way to attack it. I need to hit a webservice that has a future callout, and then take the data to update records.

I originally wrote some Batch APEX and was getting back a limits error: "Future method cannot be called from a future or batch method". As you can see in this article, Batch Apex does, in fact, not support future callouts: http://help.geopointe.com/customer/portal/articles/1767162-future-method-cannot-be-called-from-a-future-or-batch-method

I then did some research and included a Queueable class but am still getting a limits exception: "Too many future calls: 51". This to me means that the Queable method might allow Batch to happen on Future but I need to handle it differently, or I am writing the code wrong. I tried manipulating my code so that the webservice would only get hit once with a list of data but I found that I would have to majorly change the rest of my code to get this to work.

My last resort would be to give our Principal Software Developer a CSV and ask him to try and run it along with his webservice. But I am not sure if he can even do this.

Could anyone tell me if it is possible at all to do Batchable on future calls? Or am I spinning my wheels?

global class BatchableEncryptedEmailBackfill implements Database.Batchable<sObject>,Database.AllowsCallouts,Database.Stateful{

global final String Query;
global final String Entity;
global final String Field;
global final String Value;
global static List<Lead> changedLeads;

global Database.QueryLocator start(Database.BatchableContext BC){
    String query = 'SELECT Id, Web_Id_NatFund__c FROM Lead WHERE pi__url__c != NULL AND Encrypted_Email_String__c = NULL';
    return Database.getQueryLocator(query);
}  

global void execute(Database.BatchableContext BC, List<Lead> listLead){
    System.enqueueJob(new QueueClass(new Map<Id, Lead>(listLead).keySet()));
    /*for(Lead l: listLead) {
        if(l.Web_Id_NatFund__c != NULL) {
            String val = l.id + ',' + l.Web_Id_NatFund__c;
            ConsoleApplicationLinkController.getShortenedLinkBACKFILL(val);
        }
    }*/
}

global void finish(Database.BatchableContext BC){
    system.debug('got into finish:' + BC);
}
public class QueueClass implements Queueable {
    Set<Id> recordids;
    public QueueClass(Set<Id> recordIds) {
        this.recordIds = recordIds;
    }
public void execute(QueueableContext context) {
    for(Lead l: [SELECT Id, Web_Id_NatFund__c FROM Lead WHERE pi__url__c != NULL AND Encrypted_Email_String__c = NULL]) {
        if(l.Web_Id_NatFund__c != NULL) {
            String val = l.id + ',' + l.Web_Id_NatFund__c; 
            ConsoleApplicationLinkController.getShortenedLinkLT(val); //webservice
        }
     }
}
}
2

You can't call asynchronous code from code that's already asynchronous.

Can you just not have the problem in the first place? ;) Is there a version of the function that does what you need but it's not marked @future? Worst case - create a clone of that @future function without annotation (and make the future version call this new function so there's no code duplication).

Then a normal batch shouldn't have any problems, no need to drag Queuable into this.

Alternatively - just prepare a snippet of code that does what you need (copy-paste pieces of start() & execute()) and works on 10K records or less (SELECT ... LIMIT 10000; you might have to pick a lower value if there are side effects of Lead update). You'll have to run it from Developer Console 25 times. It's a boring task - but if it's an one-off data fix making a whole batch class & providing unit tests for it is an overkill.

  • all great suggestions. When I call the cloned version of the future method, I am able to get into it BUT I just realized that if I do a batch of records that have a webservice call out, and then DML that handles the webservice data, it will loop through again creating DML to happen before the webesrvice. It'll be: webservice-> dml -> webservice -> DML....Which will error out. So now I have to handle this... – Olivia Oct 10 '17 at 23:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.