7

My requirements are that I have to create a class that creates 400 to 600 records on a custom object once a button is clicked. I figure the best approach is to create a static webservice method that is called by a javascript button. I have done that before. The problem is I need to design this in such a way that scales well. Since I will be creating child records, the number of records I will increase over time. I've been reading and it looks like "Batchable interface" might be the way to approach this. But it looks like it is something than needs to be scheduled in advance rather than executing on user action.

So I'm just looking for advice as to how to build this out in such a way that is scalable but it needs to be a user pressing the button to initiate this action and not a scheduled job. Any input is welcome, thanks!

  • 1
    You can kick-off the batchable from your static webservice method (i.e. in response to your user's action) by just calling Database.executeBatch. – Keith C Nov 26 '14 at 18:48
  • Why the -1 on my answer? This is a best practice approach rather than using Javascript and an API call from a button. – techbusinessman Nov 26 '14 at 18:56
  • @techbusinessman that wasn't me. I quite liked your answer. I'm looking at all possibilities – user988 Nov 26 '14 at 19:00
  • @techbusinessman Wasn't me either. – Keith C Nov 26 '14 at 19:06
5

I would highly suggest creating an intermediary visualforce page where you explain to the user what is going to happen (maybe displaying the record that will be created etc). On that page would be another "Confirm" button. This would then allow you to use a Controller to take your inputs needed for the creation of the child records. You can then bulk process as needed,

3
+25

First off, I think Keith C's comment is the simplest solution - call Database.executeBatch() from the webservice or controller. No scheduling required.

But ...

if you anticipate adding more async actions into your org, it might be time to invest in the Dan Appleman Async Apex Pattern as described here and here

The outline of the pattern (in the context of your question):

  1. Button is clicked
  2. Button invokes code in controller (need not be web service, could be normal controller extension)
  3. Controller inserts Async_Request__c object with type__c = masscreate and params__c = customObjId (see pattern details)
  4. The continuously running scheduled Apex / repeating batch class looks for unprocessed Async_Request__c objects. The batch execute() dispatches on type__c to your class that does the mass create for the relevant customObjId using either a batch class (if the list exceeds # of DML per transaction or directly via insert if not)

Note that Appleman's 2nd edition of his Advanced Apex book was written somewhat after the Dreamforce 13 presentation and has some updated thoughts on the pattern worth reading.

0

How about a different approach which allows you to also give feedback to the users regarding the progress and any errors ?

I would propose implementing a Visualforce with polling mechanism by utilizing the action poller

In your visualforce page you add a tag

            <apex:actionPoller action="{!myPoll}"
                reRender="counter,myStatus"
                interval="5" rendered="{!isFinished == false }"/>

and in your controller you need a method myPoll which checks the termination criteria and implements your logic

public void myPoll(){

        if([criteria to continue creating records]))
        {
            createRecords();
        }
        else 
        {
            isFinished = true;
            system.debug('Stop polling...');
        }   
}

this way you can display any errors that come up to your users.

Documentation states that doing DML is not best practice, however I have used it to implement complex scenarios processing several Ks of records including DML with no issues.

I am not saying it's the best solution, but it definitely worths considering.

0

What I would do is - create a button, call a controller method (class global, method type webservice) and then execute an apex batch from there to ensure scalability. Something like -

Button Code

{!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")}
//Calling Class and Method
var batchId = sforce.apex.execute("Batch_ExecutionController", "executeBatchForCreationOfObjects", {});
window.alert('Please check logs');

Controller Code

global with sharing class Batch_ExecutionController { 
//This method is to get the view mode   
    webservice static ID executeBatchForCreationOfObjects() {             
         Id batchProcessId;                 
         //Calling Constructor for Batch Execution       
         MyBatch dc = new MyBatch();   
         batchProcessId = Database.executeBatch(dc,20);         
          return batchProcessId;   
    }
}

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.