Wednesday 19 February 2014

Spring Quartz Batch Example - CSV File Reader

In this Spring Quartz Batch Example - CSV File Reader, we will show you how to read items from CSV file.




Project Structure:


Create a simple Maven Project and import it to eclipse, now add required dependencies.








Below is the Content for JobLauncherDetails.java 



package com.mahesh.quartz;

import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;

import org.quartz.JobExecutionContext;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.configuration.JobLocator;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class JobLauncherDetails extends QuartzJobBean {

    static final String JOB_NAME = "jobName";

    private JobLocator jobLocator;

    private JobLauncher jobLauncher;

    public void setJobLocator(JobLocator jobLocator) {
        this.jobLocator = jobLocator;
    }

    public void setJobLauncher(JobLauncher jobLauncher) {
        this.jobLauncher = jobLauncher;
    }

    @SuppressWarnings("unchecked")
    protected void executeInternal(JobExecutionContext context) {

        Map<String, Object> jobDataMap = context.getMergedJobDataMap();

        String jobName = (String) jobDataMap.get(JOB_NAME);

        JobParameters jobParameters = getJobParametersFromJobMap(jobDataMap);
       
        try {
            jobLauncher.run(jobLocator.getJob(jobName), jobParameters);
        } catch (JobExecutionException e) {
            e.printStackTrace();
        }
    }

    //get params from jobDataAsMap property, job-quartz.xml
    private JobParameters getJobParametersFromJobMap(Map<String, Object> jobDataMap) {

        JobParametersBuilder builder = new JobParametersBuilder();

        for (Entry<String, Object> entry : jobDataMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof String && !key.equals(JOB_NAME)) {
                builder.addString(key, (String) value);
            } else if (value instanceof Float || value instanceof Double) {
                builder.addDouble(key, ((Number) value).doubleValue());
            } else if (value instanceof Integer || value instanceof Long) {
                builder.addLong(key, ((Number) value).longValue());
            } else if (value instanceof Date) {
                builder.addDate(key, (Date) value);
            } else {
                // JobDataMap contains values which are not job parameters
                // (ignoring)
            }
        }

        //need unique job parameter to rerun the same job
        builder.addDate("run date", new Date());
       
        return builder.toJobParameters();

    }

}


Below is the Content for CustomWriter.java


package com.mahesh.writers;

import java.util.List;

import org.springframework.batch.item.ItemWriter;

import com.mahesh.model.Report;

public class CustomWriter implements ItemWriter<Report> {

    @Override
    public void write(List<? extends Report> items) throws Exception {

        System.out.println("writer..." + items.size());       
        for(Report item : items){
            System.out.println(item);
        }

    }

}


Below is the Content for Report.java


package com.mahesh.model;

public class Report {

    private int id;
    private String Impressions;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getImpressions() {
        return Impressions;
    }

    public void setImpressions(String impressions) {
        Impressions = impressions;
    }

    @Override
    public String toString() {
        return "Report [id=" + id + ", Impressions=" + Impressions + "]";
    }

}


Below is the Content for job-quartz.xml


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:batch="http://www.springframework.org/schema/batch"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/batch
        http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    ">

    <!-- spring batch context -->
    <bean id="jobRepository"
        class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
        <property name="transactionManager" ref="transactionManager" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

    <bean id="jobLauncher"
        class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository" />
    </bean>

    <!-- Must set this -->
    <bean
        class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
        <property name="jobRegistry" ref="jobRegistry" />
    </bean>

    <bean id="jobRegistry"
        class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
    <!-- spring batch context -->

    <bean id="report" class="com.mahesh.model.Report" scope="prototype" />

    <bean id="customWriter" class="com.mahesh.writers.CustomWriter" />

    <batch:job id="reportJob">
        <batch:step id="step1">
            <batch:tasklet>
                <batch:chunk reader="cvsFileItemReader" writer="customWriter"
                    commit-interval="10">
                </batch:chunk>
            </batch:tasklet>
        </batch:step>
    </batch:job>

    <bean id="cvsFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">

        <!-- Read a csv file -->
        <property name="resource" value="classpath:cvs/input/report.csv" />

        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer">
                    <bean
                        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                        <property name="names" value="id,impressions" />
                    </bean>
                </property>
                <property name="fieldSetMapper">
                    <bean
                        class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
                        <property name="prototypeBeanName" value="report" />
                    </bean>
                </property>
            </bean>
        </property>

    </bean>

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
                <property name="jobDetail" ref="jobDetail" />
                <property name="cronExpression" value="*/5 * * * * ?" />
            </bean>
        </property>
    </bean>

    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" value="com.mahesh.quartz.JobLauncherDetails" />
        <property name="group" value="quartz-batch" />
        <property name="jobDataAsMap">
            <map>
                <entry key="jobName" value="reportJob" />
                <entry key="jobLocator" value-ref="jobRegistry" />
                <entry key="jobLauncher" value-ref="jobLauncher" />
                <entry key="param1" value="mahesh1" />
                <entry key="param2" value="mahesh2" />
            </map>
        </property>
    </bean>

</beans>

Below is the Content for report.csv


1,"200,245"
2,"500,555"
3,"900,975"

Below is the Content for App.java



package com.mahesh;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
   
    public static void main(String[] args) {

        String springConfig = "spring/batch/jobs/job-quartz.xml";

        ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);

    }
}

OutPut:


INFO: Starting beans in phase 2147483647
20 Feb, 2014 1:15:51 PM org.springframework.scheduling.quartz.SchedulerFactoryBean startScheduler
INFO: Starting Quartz Scheduler now
20 Feb, 2014 1:15:55 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=reportJob]] launched with the following parameters: [{param1=mahesh1, param2=mahesh2, run date=1392882355014}]
20 Feb, 2014 1:15:55 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
writer...3
Report [id=1, Impressions=200,245]
Report [id=2, Impressions=500,555]
Report [id=3, Impressions=900,975]


1 comment:

  1. can you publish an article related to " spring batch " ,if you publish that it is great full for me

    ReplyDelete