Using Client-Side Looping to Work within Salesforce.com Governor Limits

October 22, 2008 Appirio

Repeat after me. The governor is our friend. It stops us from doing things we really shouldn’t be doing, so in a way the governor makes us a better person. At least as far as SaaS development goes.

As you may already be too familar, Salesforce.com imposes limitations to ensure that their customers do not monopolize resources since they share a multi-tenant environment. These limits are called governors and are detailed in the Understanding Execution Governors and Limits section of the Apex Language Reference. If a script exceeds one of these limits, the associated governor issues a runtime exception and code execution is halted.
I am about to guide you through a simple example of using client-side looping in VisualForce to execute server-side Apex code that would otherwise have been unacceptable based on the governor limits.

Modifying your Apex

There are a number of situations when a solution like this might be helpful, but consider this situation; you want to move 10 million records from Source_Object__c to Target_Object__c via Apex. You would hit the governor limits on number of records retrieved via SOQL and the number of records processed via DML, just to name just a few.
Assuming there isn’t already an autonumber field on Source_Object__c that could help us keep track of our progress processing the records, we’ll first need to add a checkbox field to Source_Object__c called Processed__c.

We can then use that field in our SOQL query to ignore records already processed, and likewise set it to true as we process records. You would then need to modify your method with a few lines of code similar to what is in red below.


global class BatchProcessDemo {
webservice static void processItems() {
Integer queryLimit = (Limits.getLimitQueryRows() – Limits.getQueryRows()) / 2;
for (ListsourceItemList :[select Id, Color, Weight
from Source_Object__c
where Processed__c = false
limit :queryLimit ]) {
List itemsToInsert = new List();
for (Source_Object__c sourceItem : sourceItemList) {
sourceItem.Processed__c = true;
Target_Object__c targetItem = new Target_Object__c();
targetItem.Color__c = sourceItem.Color__c;
targetItem.Weight__c = sourceItem.Weight__c;
targetItem.Source_Object__c = sourceItem.Id;
if (Limits.getDMLRows() + itemsToInsert.size() + 1 >= Limits.getLimitDMLRows()) {
insert itemsToInsert;
}
itemsToInsert.add(targetItem);
}
update sourceItemList;
insert itemsToInsert;
}
}
}

Creating the Visualforce Page

As mentioned in a previous post by Frank and Kyle, make sure you have Development Mode enabled and then redirect your browser to http://server.salesforce.com/apex/BatchDemo to create your page. Click on Page Editor in the bottom left of the browser to open the Visualforce Editor. Add the following code between the tags to setup our form:









You’ll notice we use standard HTML input fields rather than Apex input fields since there is no VisualForce controller required. The fields will only be used on the client side via Javascript to batch our calls to Apex.
Add a

tag immediately after the tag to display progress during the batch processing.

After the

tag, add a button to allow us to kick off the processing.



Next, we’ll need to define the batchProcess() method by adding the following code after the first tag.

Click Save. Now you can click the Start button on your VisualForce page to perform the job in batches.

Previous Article
Learning Apex: Display Multi-Object Data in Tables Easily with Apex Dummy Classes

Will Supinski Creating tables in Visualforce is easy. Provide a list of Objects to display and define vario...

Next Article
Google Apps Auth Backend for Django

Tim Garthwaite Google loves Python. In fact, Google’s original web spider, which crawls the web to create i...