Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement A Spring Batch Progress Bar - Get total row count on Job Execution

I have a batch job which reads from a database using HibernateCursorItemReader, processes the results using a custom processor then commits to another database.

What I would like to show is how many items have been processed against total items to process.

I have tried implementing a custom JobExecutionListener with @beforeJob to get the row count from the first table which can then be compared against the Job Execution commits periodically.

Is there a better way than using a Job Execution Listener. is it possible to get the total row count for the table on the first read, setting a value on the HibernateCursorItemReader during initialization or something similar?

Job

<batch:job id="SomeLongJob" job-repository="jobRepository" restartable="true">      
    <batch:listeners>
        <batch:listener ref="batchJobExecutionListener" />
    </batch:listeners>  
    <batch:step id="first1">
        <tasklet transaction-manager="hibernateTransactionManager">
            <chunk reader="hibernateItemReader"
                   processor="batchCustomProcessor"
                   writer="hibernateItemWriter"
                   skip-limit="0"
                   commit-interval="10">
            </chunk>
        </tasklet>
    </batch:step>
</batch:job>

Reader

<bean id="hibernateItemReader"
    class="org.springframework.batch.item.database.HibernateCursorItemReader">
    <property name="queryString" value="from MyTable" />
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
like image 568
clD Avatar asked Oct 20 '22 21:10

clD


1 Answers

Before Job Starts get total items to process i.e. rows

BatchJobExecutionListener.class

public void beforeJob(JobExecution jobExecution) {      
    
    int total = yourDao.getTotalRows();
    jobExecution.getExecutionContext().put("jobComplete", total);
    
}

During job execution retrieve total items and compare to read count

JobWrapper.class

...
private JobExecution jobE;
...

public Long getProgress() {

    double jobComplete = (Double) jobE.getExecutionContext()
                            .get("jobComplete");
    double reads = 0;       
    for (StepExecution step : jobE.getStepExecutions()) {
        reads = reads + step.getReadCount();
    }
    return Math.round(reads / jobComplete * 100);
}
like image 71
clD Avatar answered Oct 29 '22 06:10

clD