function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
GerhardNewman2GerhardNewman2 

Too many callouts: 2 (error with batch apex)

I don't understand why I get this error when the limit for callouts is normally 10 per transaction.

 

I am calling the following code with 1 record as a test.  The createObject() method will make 2 callouts.

 

global class S3Batchable implements Database.Batchable<CF_Purchase_Order__c>, Database.AllowsCallouts { List<CF_Purchase_Order__c> orders; global S3Batchable(List<CF_Purchase_Order__c> o){ orders = o.clone(); } global Iterable<CF_Purchase_Order__c> start(Database.batchableContext BC){ return orders; } global void execute(Database.BatchableContext BC, CF_Purchase_Order__c[] scope){ List<CF_Purchase_Order__c> ordersToUpdate = new List<CF_Purchase_Order__c>(); VF_SiteUploadController controller; boolean result; for(CF_Purchase_Order__c order : scope){ controller = new VF_SiteUploadController(order.id); controller.body = Blob.valueof(order.Script__c); controller.fileName = order.Partner__r.Final_Cut_Filename__c+'_'+order.SPON__c+'_Script.txt'; controller.fileSize = controller.body.size(); controller.bucketName='FCSinbound'; result = controller.createObject(); if(result){ order.CFNotes__c = controller.fileDownloadURL; ordersToUpdate.add(order); } } update ordersToUpdate; } global void finish(Database.BatchableContext BC){ Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.setToAddresses(new String[] {'gnewman@spotzer.com'}); mail.setReplyTo('batch@acme.com'); mail.setSenderDisplayName('Batch Processing'); mail.setSubject('Batch Process Completed'); mail.setPlainTextBody('Batch Process has completed'); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); } public static testMethod void testBatch() { List<CF_Purchase_Order__c> myTestOrders = [select id from CF_Purchase_Order__c limit 5]; S3Batchable scriptBatch = new S3Batchable(myTestOrders); ID batchprocessid = Database.executeBatch(scriptBatch); } }

 

Best Answer chosen by Admin (Salesforce Developers) 
aalbertaalbert
In Batch Apex, there is a maximum of 1 callout for each "execute()" invocation.

All Answers

paul-lmipaul-lmi
they probably don't allow callouts at all with batch apex, similar to how it wasn't (or still isn't?) supported with triggers.
GerhardNewman2GerhardNewman2

Yes it is supported, because the Apex guide for Winter 10 says:

 

Using Callouts in Batch Apex To use a callout in batch Apex, you must specify Database.AllowsCallouts in the class definition. For example: global class SearchAndReplace implements Database.Batchable<Sobject>, Database.AllowsCallouts{ }

 

So given that it is supported, why doesn't it work?

aalbertaalbert
In Batch Apex, there is a maximum of 1 callout for each "execute()" invocation.
This was selected as the best answer
GerhardNewman2GerhardNewman2

That's pretty strange to have a lower limit in batch, and a limit of 1 seems way too low.   Is that documented?   

 

I will attempt to reduce the callout(s) to 1 and see if that solves it.   Thanks.

GerhardNewman2GerhardNewman2
By reducing my callouts to 1 in the execute method and having a scope of 1, I am now able to achieve what I wanted.  Thanks!
Chirag MehtaChirag Mehta

How did you get rid of two call outs from one execute?

Did you create two batch apex classes or updated web service defintion to perform two task on single call. Or is there any wise suggestion?

Please advise!

GerhardNewman2GerhardNewman2

Sorry for the slow reply Chirag.  In this case I created multiple batch apex classes.  Each class doing a single callout.

 

A rough example:

 

A class would poll an S3 directory for files.  (1 callout). 

If files found then {

   schedule batch apex job 1 passing multiple files (this job would copy a single file per invokation into another S3 directory) (1 callout)

   schedule batch apex job 2 passing multiple files (this job would delete the original file from S3) (1 callout)

}

Chirag MehtaChirag Mehta
ok. thanks!
jason.wanjason.wan

@GerhardNewman2 ,   was there any sample code you could post how this was done. Sounds like you needed 3 classes.  I'm trying to do something similar with callouts and running into limits for Batch and nonbatch methods.  2 and 10, respectively.

hemmhemm

 


aalbert wrote:
In Batch Apex, there is a maximum of 1 callout for each "execute()" invocation.

It seems this limit is also on the finish() method.  Would that be by design or a bug?  Seems the finish method should allow for more if cleaning up at the end of a long batch run integrating with another system.

 

TerryLuschenTerryLuschen

Another thing I found with Batch Apex and callouts is that you must use Iterable as the return value for the Start method.   Using the Database.QueryLocator as the return for the start method did not work for me.