[SalesForce] Heap Storage Limit exception while creating attachment

I have a custom object Call2_vod__c which is detail to Account.

It has a Signature_vod__c field that is in encoded base64 format.

Now for one Account, I can create an attachment from any of the calls associated with it (Account:Call2_vod__c=1:many).

I am getting a limit exception with my below code. Can someone please help me?

Apex Class:`
global class Account_chk {
WebService static void method1(Id i) {
List a= new List();
List p=new List ();
List exist=new List ();
exist=[select ParentId,id from Attachment];

Map existMap = new Map();
Map signMap = new Map();

for (Attachment att : exist) {
existMap.put(att.ParentId, att);
}

for (Call2_vod__c call: [select Name,Id,Signature_vod__c,Signature_Date_vod__c,Account_vod__c from Call2_vod__c where Signature_Date_vod__c !=Null and Account_vod__c not in :existMap.keySet()])
{

  Attachment record = new Attachment(Name = Call.Id ,ParentId = call.Account_vod__c , Body = EncodingUtil.base64Decode(call.Signature_vod__c), ContentType = 'image/jpeg');
   if (record.parentId !=Null && existMap.get(record.ParentId).Id == null) {
    p.add(record);

}

}
try { insert(p);
} catch(System.DMLException e){
  System.debug('The following exception has occurred: ' + e.getMessage());
  }

}
}`

Please find the error currently I am facing with the code:

Failed to execute 'send' on 'XMLHttpRequest':Failed to load 'https://cs18.salesforce.com/services/Soap/package/Account_chk'

Best Answer

You are querying too many unneeded records and creating Attachments for them which is why you are hitting the heap limit. Try make the 2 changes listed below

1: Restrict your query

Changing the SOQL to have extra where conditions will mean you are querying less records which means less fields that are base64 encoded. The SOQL below is looking at the Account_vod__c fields which will mean you query less records.

[select Name,Id,Signature_vod__c,Signature_Date_vod__c,Account_vod__c 
    from  Call2_vod__c 
    where Signature_Date_vod__c !=Null and Account_vod__c in :existMap.keySet()]

The extra check for Account_vod__c in :existMap.keySet() will stop you querying the records you are not interested in.

2: Change the for loop

Because you do your SOQL and store the results in a it means that ALL records will be on the heap. Try changing your for loop to the format shown below. This will avoid the heap issues are you are not storing all the results to a list:

for (Call2_vod__c call : [select ... from ... where ...]) {
    //
}

Doing number 2 will probably fix your issue but having the SOQL returning so many records is wrong and will cause problems as the number of Call2_vod__c records grow. For example: you will hit another limit if that query returns more than 10,000 records

Related Topic