我正在尝试编写一个春季批处理作业,该作业从数据库中读取数据并写入FlatFile。
我需要在FlatFile的标题中写入total records, total lines
为此,可以使用Writer中的headerCallback属性。

问题陈述:

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

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

作业配置:

<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的值。

我在处理器中设置值,如下所示:

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;
    }
}


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

最佳答案

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

请注意,如果您想在页脚行中写这些信息,它将起作用。

有一个与此类似的问题,我在这里添加以供参考:Passing variables to process

08-07 04:17