You need to sign in to do that
Don't have an account?
Batch Apex Error: Batchable Instance Is Too Big
I have a batch class that collects values from the contact custom field YTD_GDC_Total__c and totals them at the account level and then inserts to totals into the associated custom account field. I have an example of the code below showing one field being summed/totaled.
I've begun adding additional fields (beyond what is shown in the code below) and, finally, after I added the last two fields, I'm now getting Batchable Instance Is Too Big error.
I found this threadwhich I think may describe the cause of my error: "..(having a) global variable which was keeping instances of lists of records that were created in each execution of the method 'execute' " - I think I'm keeping too many map collections in memory. Any thoughts on how to resolve or does anyone know if a more efficient code pattern to summarize contact field @ the account level (without using aggregate queries)?
Thanks in advance!
CODE:
global class BatchAccntSummary implements Database.Batchable<sObject>, Database.Stateful
{
public String query = 'SELECT Id, Name, AccountId, Account.RecordTypeId, Account.Name, YTD_GDC_Total__c ' +
'FROM Contact WHERE Account.RecordTypeId = \'012500000009WdF\' ' +
'AND (YTD_GDC_Total__c > 0.00)';
global Map<Id, Account> branchesToUpt = new Map<Id, Account>();
global Boolean uniqueFirm = true;
global Boolean addMapToList;
global Integer counter = 0;
global Map<Id, Decimal> branch_total_YTD_GDC;
global Decimal total_YTD_GDC_Cont;
global Decimal currbranch_total_YTD_GDC;
/*
* OBJECTIVE: Method used to initialize all the variables once.
*/
global void initVars()
{
branchesToUpt = new Map<Id, Account>();
uniqueFirm = true;
counter = 0;
// YTD GDC TOTAL
branch_total_YTD_GDC = new Map<Id, Decimal>();
total_YTD_GDC_Cont = 0.00;
currbranch_total_YTD_GDC = 0.00;
}
/*
* OBJECTIVE: Start method of the Batchable interface
*/
global database.querylocator start(Database.BatchableContext BC)
{
initVars();
return Database.getQueryLocator(query);
}
/*
* OBJECTIVE: Utility method needed to handle null values.
*/
global Decimal formatDecimal(Decimal valToFormat)
{
Decimal processedValue = 0.00;
if (valToFormat != null)
processedValue = valToFormat;
else
processedValue = 0.00;
return processedValue;
}
/*
* OBJECTIVE: Execute method of the Batchable interface
*/
global void execute(Database.BatchableContext BC, List<sObject> scope)
{
Account currAccnt;
for (sObject s : scope) {
addMapToList = false;
uniqueFirm = true;
Contact c = (Contact)s;
total_YTD_GDC_Cont = formatDecimal(c.YTD_GDC_Total__c);
System.debug('Processing contact: ' + c.Name);
// DEBUG Stuff
System.debug('######## Size of branch_total_YTD_GDC _Map: ' + branch_total_YTD_GDC.size());
// Check if the map already contains the firm id
if (branch_total_YTD_GDC.containsKey(c.AccountId)) {
uniqueFirm = false;
}
// If the map does not contain the firm id
if (uniqueFirm) {
System.debug('###### Size of m: ' + branch_total_YTD_GDC.size());
branch_total_YTD_GDC.put(c.AccountId, total_YTD_GDC_Cont);
currAccnt = new Account(Id = c.AccountId, Branch_Total_YTD_GDC__c = branch_total_YTD_GDC.get(c.AccountId));
System.debug('Adding account: ' + c.Account.Name + ' w/ sales: ' + branch_total_YTD_GDC.get(c.AccountId) +
', contact person: ' + c.Name);
}
// If the map does contain the firm id
else if (!uniqueFirm) {
if (branch_total_YTD_GDC.containsKey(c.AccountId)) {
currbranch_total_YTD_GDC = branch_total_YTD_GDC.get(c.AccountId);
branch_total_YTD_GDC.put(c.AccountId,(total_YTD_GDC_Cont + currbranch_total_YTD_GDC));
currAccnt = new Account(Id=c.AccountId,Branch_Total_YTD_GDC__c = branch_total_YTD_GDC.get(c.AccountId));
System.debug('Account: ' + c.Account.Name + ' w/ sales: ' + branch_total_YTD_GDC.get(c.AccountId) +
', contact person: ' + c.Name);
}
}
if (currAccnt != null)
branchesToUpt.put(c.AccountId, currAccnt);
}
update branchesToUpt.values();
branchesToUpt.clear();
}
/*
* OBJECTIVE: Batch finish Method.
*/
global void finish(Database.BatchableContext BC)
{
}
}
Hi,
Is there any specific reason that you are using Database.Stateful in your batch class definition ? I don't see you are processing any sort of aggregation in the finish method. You can take off Database.Stateful and use a lower number in optional scope parameter when executing the batch job..for eg Database.executeBatch(new BatchAccntSummary(), <some lower number like 100,200>)
All Answers
Hi,
Is there any specific reason that you are using Database.Stateful in your batch class definition ? I don't see you are processing any sort of aggregation in the finish method. You can take off Database.Stateful and use a lower number in optional scope parameter when executing the batch job..for eg Database.executeBatch(new BatchAccntSummary(), <some lower number like 100,200>)
Magicforce9 thank you for your response! I had the same thought as you, but because we're summing in the execute method we need to maintain state . I tried taking out Database.Stateful but it wouldn't sum anymore. However I did reduce the scope number and that is working, so thanks!
One final question: do you know if there are any forum that I could search to see if there are other code solutions...just for my own knowledge?
I'm glad lowering the number worked. You can post your question on http://salesforce.stackexchange.com for others opinions.