在Spring Batch中访问HeaderCallBack中的ExecutionContext值 [英] Accessing the ExecutionContext values in HeaderCallBack in Spring Batch

查看:117
本文介绍了在Spring Batch中访问HeaderCallBack中的ExecutionContext值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个春季批处理作业,该作业从数据库读取数据并将其写入FlatFile.我需要在FlatFile的标题中写入<总记录总数,总行数.为此,可以使用Writer中的headerCallback属性.

I'm trying to write a spring batch job which reads data from database and writes to FlatFile. I need to write the total records, total lines in the header of the FlatFile. Using the headerCallback property in Writer for that purpose.

问题陈述:

我正在处理器的 ExecutionContext 中设置值,并尝试在Writer的headerCallback中检索这些值.但是在headerCallback中将值获取为 null .

I'm setting the values in ExecutionContext in Processor and trying to retrieve the values in headerCallback of the Writer. But getting the values as null in headerCallback.

使用 ExecutionContextPromotionListener 进行了尝试,也使用SpEL将值直接注入headerCallback中.详细信息如下:

Tried using ExecutionContextPromotionListener and also by injecting the values directly into headerCallback using SpEL. Details are as below:

职位配置:

<batch:job id="fooBatchJob">
<batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="fooJdbcItemReader" writer="fooFileItemWriter" processor="fooProcessor"
                commit-interval="100">
            </batch:chunk>
        </batch:tasklet>
        <batch:listeners>
            <batch:listener ref="execContextPromotionListener"/>
        </batch:listeners>
    </batch:step>
</batch:job>

<!-- Listeners -->

<bean id="execContextPromotionListener" class="org.springframework.batch.core.listener.ExecutionContextPromotionListener">
    <property name="strict" value="TRUE"/>
    <property name="keys">
        <list>
            <value>TOTAL_RECORDS</value>
            <value>TOTAL_LINES</value>
        </list>
    </property>
</bean>

使用ItemReader中查询的值填充TOTAL_RECORDS和TOTAL_LINES的值.

The values of TOTAL_RECORDS and TOTAL_LINES are populated with the values from the query in ItemReader.

我正在处理器"中设置以下值:

public class FooProcessor implements ItemProcessor<MyObj,MyObj>, StepExecutionListener {

    private StepExecution stepExecution;

    public MyObj process(MyObj item) throws Exception {

        if(item != null && item.getRecordType().equals("HEADER")) {

            this.stepExecution.getExecutionContext().put("TOTAL_RECORDS", item.getMetaData().getTotalRecordsCount());
            this.stepExecution.getExecutionContext().put("TOTAL_LINES", item.getMetaData().getTotalLines());
            // below lines printed for debugging:
            System.out.println("TOTAL_RECORDS:"+this.stepExecution.getExecutionContext().getInt("TOTAL_RECORDS"));
            System.out.println("TOTAL_LINES:"+this.stepExecution.getExecutionContext().getInt("TOTAL_LINES"));
            return null;
        }
        return item;
    }

    @Override
    public void beforeStep(StepExecution stepExecution) {
        this.stepExecution = stepExecution;

    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }
}

现在,这是Writer配置:

<bean id="fooFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
        <property name="resource" value="file:output/result-file.asc"/>
        <property name="shouldDeleteIfExists" value="true" />
        <property name="headerCallback" ref="myHeaderFooter"/>
        <property name="footerCallback" ref="myHeaderFooter"/>
        <property name="lineAggregator">
            <bean
                class="com.domain.batch.transform.FooLineAggregator">
            </bean>
        </property>
    </bean> 

<!-- Header and Footer Callback -->
    <bean id="myHeaderFooter" class="com.domain.batch.transform.MyHeaderFooter" scope="step">
        <property name="stepExecution" value="#{stepExecution}" />
        <property name="totalRecords" value="#{jobExecutionContext['TOTAL_RECORDS']}"/>
    </bean> 

以下是MyHeaderFooter.java的列表:

public class MyHeaderFooter implements FlatFileHeaderCallback, FlatFileFooterCallback {

    private StepExecution stepExecution;
    private Integer totalRecords;

    private static final String ITEM_END_INDICATOR = "RE";
    private static final String SPACE_DELIMITER = " ";
    private static final String LINE_SEPARATOR = System.lineSeparator();

    @Override
    public void writeHeader(Writer writer) throws IOException {
        // printing out null
        System.out.println("Total records from jobExecContext : "+totalRecords); 
        ExecutionContext executionContext = stepExecution.getJobExecution().getExecutionContext();
        // printing out null
        System.out.println("Total Records :"+ executionContext.get("TOTAL_RECORDS"));
       // printing out null
        System.out.println("Total Lines:"+ executionContext.get("TOTAL_LINES"));
        // Below lines commented out for brevity
        //String header = buildHeader(...);
        //writer.write(header);
    }

    @Override
    public void writeFooter(Writer writer) throws IOException {
        String footer = "footer data....";
        writer.write(footer);
    }

public void setStepExecution(StepExecution stepExecution) {
        this.stepExecution = stepExecution;
    }

    public void setTotalRecords(Integer totalRecords) {
        this.totalRecords = totalRecords;
    }
}

不知道我在做什么配置错误.任何发现问题的线索都将有所帮助.

Not sure what i'm doing wrong with the configuration. Any clue to find out the issue would be helpful.

推荐答案

打开 fooFileItemWriter 时,将调用 writeHeader 方法.那时尚未开始读取,处理和写入.因此,您所请求的信息尚不可用.

The writeHeader method is called while opening the fooFileItemWriter. Reading, processing and writing have not started yet at that point in time. So the information you are requesting is not available yet.

请注意,如果您希望将这些信息写在页脚行中,那么它将起作用.

Note that it would work if you want to write these information in a footer line.

有一个与此类似的问题,我在这里添加以供参考:将变量传递给处理.

There is a similar question to this one, I'm adding it here for reference: Passing variables to process.

这篇关于在Spring Batch中访问HeaderCallBack中的ExecutionContext值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆