2

I have an Apex class that is a controller for a Visualforce page. The VF page has a commandButton that calls a function in the controller that executes a batch process that processes some data, then executes another batch to process some more data before terminating. The chain continues until all the data is processed. I would use queueables, but I need to make a callout during each link of the chain, and queueables can't make a callout and a new queueable, only one or the other.

I want the VF page to show the progress of this process, but the controller doesn't know the ID of the current batch job, only the first one that it started. How can this be done? Do I have to create some kind of custom object to store state, and do a DML Update call at each link of the chain? That seems a little clunky, but the controller would be able to access that data with a DML call.

  • There are lots of good reasons to use DML to record batch job progress, notably to log interesting things to aid in after-the-fact-diagnosis – cropredy Nov 30 '15 at 21:48
  • think this is a repeat of this question.. salesforce.stackexchange.com/questions/83812/… – Benjamin Pirih Nov 30 '15 at 21:58
  • 1
    @BenjaminPirih: I am not just executing one batch job, as in that post. It is a chain of batch jobs, therefor I can not simply use the Id of the one executed by the button. This is a different problem. – Neo Nov 30 '15 at 22:12
  • Seems like you could create some sort of ChildJob object whose ParentId or Ultimate Parent would track previous job ids. – Adrian Larson Nov 30 '15 at 22:23
2

Store the Id of the job you ran, and then you can query the AsyncApexJob table to see progress.

Here is a snippet

This code assumes there will be an object the ID of the jobs*

Batchable Class:

//Only showing the area that needs to change
global void finish(Database.BatchableContext BC) {
   string jobId = database.executeBatch(nextBatch);

   object__c myObject = new object__c();
   myObject.JobId__c = jobId;
   upsert myObject;

}

Page:

<apex:page controller="myCont" action="{!getJobs}">

<apex:form id="theForm">

<apex:pageMessages />

<apex:repeat value="{!theJobs}" var="job">
  <!-- Add all needed fields and make this pretty, maybe a table -->
    <apex:outputText value="{!job.Id}" /> -- <apex:outputText value="{!job.status}" />
  <br/>

</apex:repeat>

</apex:form>

</apex:page>

Class:

public without sharing myCont() { 
  public List<AsyncApexJob> theJobs {get;set;

public void getJobs() {
        Set<String> jobIds = new Set<String>();

        For (object__c obj : [select JobId__c from Object__c]) { 
          jobIds.add(ob.JobID__c);
         }


        theJobs = [SELECT Id, Status FROM AsyncApexJob where Id in :jobIds];
}

}

| improve this answer | |
  • I am not trying to track a single batch job. I am trying to track the progress of a chain of batch jobs. The ID will only tell me about the first link in the chain (the first batch job). Each link has its own ID. – Neo Nov 30 '15 at 22:16
  • Neo, what do you mean by a "chain" of batch jobs? Is it each individual batch? Because, if by "chain" you mean that a job "launches" another job then at that point you can get the id of the newly launched and track it appropriately. Perhaps even storing that Id in the DB. – Sebastian Kessel Nov 30 '15 at 22:23
  • Sebastian, I mean that each job launches another job. The job that is executing the new job can indeed grab the ID of the new one, but then the old job that now has the new ID will promptly terminate. – Neo Nov 30 '15 at 22:31
  • Ok. I have code for that too. I'll update the code in a few minutes. Do you want to track EVERY step or just the last one? (the sample code above will address the latter) – Sebastian Kessel Nov 30 '15 at 22:36
  • I'd prefer to track every link, but it might be enough to track how many links have already completed. – Neo Nov 30 '15 at 22:44

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.