+ Start a Discussion
SivarajanSivarajan 

Batch Apex jobs processing - dynamic manner, is it possible?

Hi,

 

I am having a custom button which calls visual force page(having controller calling batch apex class) which should 1st give me a message let say 'kTerritories are currently being assigned. Please wait'. But then I want the control on same page with the message showing dynamic value of how many batch job processes are done (values fetching from AsyncApexJob object). Like say, 10 processes completed, 20 processes completed , etc as per status in Apex Jobs queue.

 

I am not getting that value. Please assist me on how can I get that value to be shown to the user who clicks that button.

 

Also, just want to know if this can be really possible to show the dynamic processing of batches at runtime because from Apex document it says that:-

 

=============== 

ID batchprocessid = Database.executeBatch(reassign);
AsyncApexJob aaj = [SELECT Id, Status, JobItemsProcessed, TotalJobItems, NumberOfErrors
FROM AsyncApexJob WHERE ID =: batchprocessid ];

===============

 

which, as per my knowledge means that the values of all these fields will be obtained once all batches are processed. Correct me if I am wrong.

 

Please see below the vf page and the controller class(having batch apex logic too):-

 

 

VisualForce Page:-

 

<apex:page controller="BatchApexTerritoryAssignmentBulk" tabStyle="Territory__c" action="{!navigate}" >
    <apex:sectionHeader title="Assigning Territories" />
     
    <apex:pageBlock >
   
       <apex:image url="{!$Resource.BusyImage}" /> &nbsp;&nbsp;
       Territories are being assigned to Leads, Accounts and Opportunities.
       Please wait for the process to get complete .....
       <apex:form >
       <apex:outputText value="Number of batch jobs processed : {!no_jobs_processed}" id="process_counter"/>
       <apex:actionPoller action="{!jobProcessing}"  rerender="process_counter" interval="30"/>
      
      
       </apex:form>

       
    </apex:pageBlock>
   
   
   
</apex:page>

 

 

Controller Class:-

 

global class BatchApexTerritoryAssignmentBulk implements Database.Batchable<SObject>
{
  public String query;
  public Static Id batchId;
  public Integer no_jobs_processed{get;set;}
 
  public String lead1 = 'Lead';
  public String acc = 'Account';
  public String opp = 'Opportunity';
 
  public void navigate()
  {
  BatchApexTerritoryAssignmentBulk.BatchApexMethod(lead1);
 
  } 
  /*
  public  Integer getno_jobs_processed()
  {
  AsyncApexJob aaj;
 
  if(batchId != null)
  {
  aaj =  [select Id,JobItemsProcessed from AsyncApexJob where Id =: batchId];
  no_jobs_processed = aaj.JobItemsProcessed;
  }
  else
  no_jobs_processed = 25;
 
  return  no_jobs_processed;
  } 
   */
 
  public void jobProcessing()
  {
  AsyncApexJob aaj;
 
  if(batchId != null)
  {
  aaj =  [select Id,JobItemsProcessed from AsyncApexJob where Id =: batchId];
  no_jobs_processed = aaj.JobItemsProcessed;
  }
   
  }
 
 
 

 

 
 /* public void navigate()
 {
    System.debug('Inside navigate');
   
    BatchApexTerritoryAssignmentBulk.BatchApexMethod(lead1);
   
   // no_jobs_processed = BatchApexTerritoryAssignmentBulk.batchJobStatus_Processes();
   
  //  BatchApexTerritoryAssignmentBulk.BatchApexMethod(acc);
  //  BatchApexTerritoryAssignmentBulk.BatchApexMethod(opp);
   
    //PageReference pageRef = new PageReference('/a0G?fcf=00BT0000002dwWH');
    //pageRef.setRedirect(true);  
    //return pageRef;
 }  
 */
 

 
 

 global database.Querylocator start(Database.batchableContext bc)
 {
   //Integer cont;
  
   try
   {
   /*if(query == null)
   cont = 1;
   else
   cont = 0;
   if(cont == 0) */
   return Database.getQueryLocator(query);
  /* else
   return null;*/
   }
   catch(Exception e)
   {
   System.debug('Exception'+e);
   }
   return null;
 }

 global void execute(Database.BatchableContext BC, List<SObject> sobjList)
 {
  //batchId= BC.getJobId();
  System.debug('Batch Id'+batchId);
 // System.debug('Job Items processed'+BC.getJobItemsProcessed());
  //System.debug('Total Job Items '+BC.getTotalJobItems());
 

 
  System.Debug('DATABASE.BATACHABLE CONTEXT' + BC);
  System.Debug('SOBJECT LIST SIZE PASSED AS QUERY : ' + sobjList.size());
  TerritoryAssignmentBulk tabObj = new TerritoryAssignmentBulk();
  List<Lead> leadList = new List<Lead>();
  Map<Id,Account> accMap = new Map<Id,Account>();
  List<Opportunity> oppList = new List<Opportunity>();
  
  try
  {
  for(sobject s : sobjList)
  {
   if(s.getsObjectType() == Lead.sObjectType)
   {
    Lead l = (Lead)s;
    if(!l.isConverted)
    {
     leadList.add(l);
    }
   }
  }
  System.Debug('LEAD LIST SIZE : ' + leadList.size());
 
  if(leadList.size()!=0)
  {
   tabObj.runRules(null, null, leadList, false);//The method that needs to be called, for lead all others will be null and boolean false
   update leadList;
     
  }

 
 
  //batchJobStatus_Processes();
  //System.debug('No.of jobs processed'+no_jobs_processed);

 

  /*for(sobject s : sobjList)
  {
   if(s.getsObjectType() == Account.sObjectType)
   {
    Account a = (Account)s;
    accMap.put(a.id,a);
   }
  }
  if(accMap.size()!=0)
  {
   tabObj.runRules(oppList, accMap, leadList, false);//The method that needs to be called, for lead all others will be null and boolean false
   update accMap.values();
  } */
  }
  catch(Exception e)
   {
   System.debug('Exception'+e);
   }
 
 }


 global void finish(Database.BatchableContext BC)
 {
  AsyncApexJob a = [Select Id, Status, NumberOfErrors, JobItemsProcessed,TotalJobItems, CreatedBy.Email
  from AsyncApexJob where Id =:BC.getJobId()];
 
  // Send an email to the Apex job's submitter notifying of job completion.
  Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
  String[] toAddresses = new String[] {a.CreatedBy.Email};
  mail.setToAddresses(toAddresses);
  mail.setSubject('Batch Apex for Territory Assignment Bulk : ' + a.Status);
  mail.setPlainTextBody('The batch Apex job processed ' + a.TotalJobItems +
  ' batches with '+ a.NumberOfErrors + ' failures.');
  Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
 
 }

 webservice static String BatchApexMethod(String objectType)
 {
  BatchApexTerritoryAssignmentBulk leadBulk = new BatchApexTerritoryAssignmentBulk();
  BatchApexTerritoryAssignmentBulk accBulk = new BatchApexTerritoryAssignmentBulk();

  try
  {
 
  if(objectType == 'Lead')

   leadBulk.query = 'Select Id, Name, Company, Keep_in_Territory__c, LastName, Status, isConverted, Segment__c, Sub_Segment__c, Postalcode, Potential_Revenue__c From Lead where isConverted = false';
  
   System.Debug('QUERY' + leadBulk.query);
  
  Id leadProcessId = Database.executeBatch(leadBulk);
 
  batchId = leadProcessId;
 
 

  /*if(objectType == 'Account')

   accBulk.query = 'Select Id, Name From Account';
  
  Id accountProcessId = Database.executeBatch(accBulk); */
 
  return '';
  }
  catch(Exception e)
   {
   System.debug('Exception'+e);
   }
   return '';
 
 } 
 
 public static testMethod void BatchApexTerritoryAssignmentBulkTestMethod()
 {
  String objType = 'Lead';
  User usr=[select id,Name from User where Name = 'Vimal Desai'];
  List<Lead> leadlist = new List<Lead>();
  for(integer i = 0; i<200; i++)
  {
   Lead l = new lead(Company='TCS' + 'i',LastName='David',Status='New');
   leadlist.add(l);
  }
  insert leadlist;
 
  Test.StartTest();
 
  BatchApexTerritoryAssignmentBulk batchinstance = new BatchApexTerritoryAssignmentBulk ();
  batchinstance.query = 'Select Id, Name, Company, Keep_in_Territory__c, LastName, Status, isConverted, Segment__c, Sub_Segment__c, Postalcode, Potential_Revenue__c From Lead where isConverted = false LIMIT 200';
  BatchApexMethod(objType);
  ID batchprocessid = Database.executeBatch(batchinstance);
 
  Test.StopTest();
 
 }
 
 
 
 
 
 
 //public void batchJobStatus_Processes()
 //{
 //AsyncApexJob aaj;
 
 //aaj =  [select Id,JobItemsProcessed from AsyncApexJob where Id =: batchId];
 //no_jobs_processed = aaj.JobItemsProcessed;
 
 //}
 
 
 
 
}

 

 

 

 

 

 

David VPDavid VP

This is possible (I've seen similar things in action with Batch Apex).

I don't have access to the code but it will most likely be a combination of some javascript (see the setTimeOut() function) together with an <apex:actionFunction /> and some ajax rerender VF components.