Thursday, July 6, 2017

Batch Apex Job Progress Bar

We can display the progress of Batch Apex job on UI to user. Apex allows you to query the job status by query AsyncApexJob  object and getting all details about running job like status, JobItemsProcessed, NumberOfErrors, TotalJobItems etc. By using apex, we can manipulate the result and display the progress bar for batch job.

Suppose you already have Apex Batch class written. Here for example "RecordTypeAccessFinder" is batch class is already present.

Below is VF page and Apex class Code:
public class BatchJobProgressBarController {
private Id batchClassId;
final public String NOT_START = 'not_started';
final public String PROCESSING = 'processing';
final public String FINISHED = 'finished';
public String batchStatus {get;set;}
public Id batchId {get;set;}
public String message {get;set;}
public Integer errornum {get;set;}
public BatchJobProgressBarController (){
//here specify the Apex batch class name for which you want to display progress bar
batchClassId = [Select Name, Id From ApexClass Where Name = 'RecordTypeAccessFinder' Limit 1][0].id;
batchStatus = NOT_START;
batchId = null;
message = '';
errornum =0;
}
public boolean getShowProgressBar() {
if(batchStatus == PROCESSING )
return true;
return false;
}
//this method will fetch apex jobs and will update status,JobItemsProcessed,NumberOfErrors,TotalJobItems
public BatchJob[] getJobs() {
List<AsyncApexJob> apexJobs =
[Select TotalJobItems, Status, NumberOfErrors, ExtendedStatus, JobItemsProcessed, Id, JobType, ApexClassId, CreatedDate From AsyncApexJob Where ApexClassId =: batchClassId Order by CreatedDate DESC];
if(apexJobs.size() == 0) {
return new List<BatchJob>();
}
List<BatchJob> jobs = new List<BatchJob>();
for(AsyncApexJob job : apexJobs) {
if(job.id != batchId)
continue;
BatchJob bj = new BatchJob();
bj.isCompleted = false;
if(job.ApexClassId == batchClassId) {
bj.Job_Type = 'Process 1';
}
bj.aj = job;
// NOT START YET
if(job.jobItemsProcessed == 0) {
bj.Percent= 0;
jobs.add(bj);
continue;
}
Decimal d = job.jobItemsProcessed;
d = d.divide(job.TotalJobItems, 2)*100;
bj.Percent= d.intValue();
// PROCESSING
if(bj.Percent != 100){
jobs.add(bj);
continue;
}
// FINISED
if(job.ApexClassId == batchClassId) {
batchStatus = FINISHED;
}
errornum += job.NumberOfErrors;
bj.isCompleted = true;
jobs.add(bj);
}
return jobs;
}
public PageReference StartBactJob() {
//execute RecordTypeAccessFinder batch
if(!test.isRunningTest()){
string selectedObject='Account';
RecordTypeAccessFinder acc=new RecordTypeAccessFinder(selectedObject);
batchId=database.executebatch(acc,10);
system.debug('************batchid:'+batchid);
}
batchStatus = PROCESSING;
return null;
}
public PageReference updateProgress() {
if(batchStatus == FINISHED) {
message = 'COMPLETED';
}
return null;
}
public class BatchJob{
public AsyncApexJob aj {get;set;}
public Integer Percent {get;set;}
public String Job_Type {get;set;}
public Boolean isCompleted {get;set;}
public BatchJob(){}
}
}
<apex:page controller="BatchJobProgressBarController">
<style>
.prog-bar {
height: 14px;
margin: 3px;
padding: 0px;
padding-right:3px;
background: #FFA037;
text-align:right;
font-size:12px;
font-weight:bold;
color:#333333;
}
.prog-bar-done {
height: 14px;
margin: 3px;
padding: 0px;
padding-right:3px;
background: #C9DDEC;
}
.prog-border {
width: 209px;
background: #fff;
border: 1px solid silver;
margin: 0px;
padding: 0px;
}
</style>
<apex:form id="f1">
<apex:pageBlock >
<apex:pageblockButtons location="top">
<apex:commandButton value="Start batch Job" action="{!StartBactJob}" rerender="f1" status="actionstatus"/>
<apex:actionPoller rerender="f1" interval="5" action="{!updateProgress}" status="counterstatus"/>
</apex:pageblockButtons>
<apex:pageblockSection columns="1">
<apex:pageBlockTable id="prog" value="{!Jobs}" var="item">
<apex:column headerValue="{!$ObjectType.AsyncApexJob.fields.Status.label}" >
<apex:outputText value="{!item.aj.status}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<apex:image url="/img/loading.gif" id="progressbar_img1" rendered="{!ShowProgressBar}" style="visibility: {!IF(item.isCompleted,'hidden','visible')}"/>
</apex:column>
<apex:column headerValue="Progress (%)">
<div class="prog-border" >
<apex:outputPanel layout="block" styleClass="{!if(item.Percent>=100,'prog-bar-done','prog-bar')}" style="width: {!item.Percent*2}px;">
<apex:outputText value="{!item.Percent}" rendered="{!if(item.Percent!=100,true,false)}" />
</apex:outputPanel>
</div>
</apex:column>
</apex:pageBlockTable>
</apex:pageblockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

No comments:

Post a Comment