当达到以下步骤的条件时,如何无条件地返回到前一步骤Spring Batch

时间:2018-03-01 17:45:48

标签: java spring spring-batch jobs

Hello Spring Batch社区!我有一个带有标题和正文的输入平面文件。标题是1行(自然..)和5个参数。 Body最多可以达到100万条记录,每条记录有12个参数。

输入文件:

java.time

我需要将其写入具有特定格式的.txt文件中,并且在此特定结构中:

01.01.2017|SUBDCOBR|12:21:23|01/12/2016|31/12/2016
01.01.2017|12345678231234|0002342434|BORGIA RUBEN|27-32548987-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,01
01.01.2017|12345673201234|2342434|ALVAREZ ESTHER|27-32533987-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,02
01.01.2017|12345673201234|0002342434|LOPEZ LUCRECIA|27-32553387-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,12
01.01.2017|12345672301234|0002342434|SILVA JESUS|27-32558657-9|NC|A|2062-
00010443|142,12|30/08/2017|142,12
.
.   
.

我所做的是......创建一个stepHeader和一个stepBody。他们每个人都有自己的读者,处理器(业务格式化器)和写作者。

这项工作只有两个简单的步骤。

HEADER (8 customed lines, using data from HEADER input)
TITLE OF COLUMNS (1 line)
DETAILS (17 records from the body)
line break
SAME HEADER
SAME TITLE OF COLUMNS
DETAILS (next 17 records from the body)
line break
...
...  
...
REPEAT until end of file

我读取的标题配置为MaxItemCount = 1,并将其映射到CabeceraFacturacion:

@Bean
public Job job() throws Exception {
        return jobBuilderFactory.get("job")
                .incrementer(new RunIdIncrementer())
                .listener(new JobListener())
                .start(stepHeader())
                .next(stepBody())
                .on("BACK TO STEPHEADER").to(stepHeader())
                .on("END").end().build()
                .build();
}

我用这种方式读取它,跳过第一行,并将其映射到DetalleFacturacion:

    @Bean
    public FlatFileItemReader<CabeceraFacturacion> readerCabecera() throws Exception{

    FlatFileItemReader<CabeceraFacturacion> reader = new FlatFileItemReader<>();

    reader.setLinesToSkip(0);
    reader.setMaxItemCount(1);
    reader.setResource(new ClassPathResource("/inputFiles/input.txt"));

    DefaultLineMapper<CabeceraFacturacion> cabeceraLineMapper = new DefaultLineMapper<>();

    DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer("|"); // en el default, la coma es el separador
    tokenizer.setNames(new String[] {"printDate", "reportIdentifier", "tituloReporte", "fechaDesde", "fechaHasta"});

    cabeceraLineMapper.setLineTokenizer(tokenizer);
    cabeceraLineMapper.setFieldSetMapper(new CabeceraFieldSetMapper());
    cabeceraLineMapper.afterPropertiesSet();

    reader.setLineMapper(cabeceraLineMapper);

    return reader;
}

我的步骤:

@Bean
    public FlatFileItemReader<DetalleFacturacion> readerDetalleFacturacion(){

    FlatFileItemReader<DetalleFacturacion> reader = new FlatFileItemReader<>();

    reader.setLinesToSkip(1);
    //reader.setMaxItemCount(17);
    reader.setResource(new ClassPathResource("/inputFiles/input.txt"));

    DefaultLineMapper<DetalleFacturacion> detalleLineMapper = new DefaultLineMapper<>();

    DelimitedLineTokenizer tokenizerDet = new DelimitedLineTokenizer("|"); // en el default, la coma es el separador
    tokenizerDet.setNames(new String[] {"fechaEmision", "tipoDocumento", "letra", "nroComprobante",  
                                "nroCliente", "razonSocial", "cuit", "montoNetoGP", "montoNetoG3",
                                "montoExento", "impuestos", "montoTotal"});



    detalleLineMapper.setLineTokenizer(tokenizerDet);
    detalleLineMapper.setFieldSetMapper(new DetalleFieldSetMapper());
    detalleLineMapper.afterPropertiesSet();
    reader.setLineMapper(detalleLineMapper);


    return reader;
}   

1)我不知道如何在文件结束前无限制地返回StepHeader。在那里我尝试使用stepExecution.getWriteCount(17)..但我不确定这是不是。

2)我不知道每次循环时如何读取17条不同的记录(我设法让它循环但是它会一遍又一遍地写出相同的前17条记录,直到我手动停止工作。我现在知道了在Spring Batch进程中不建议使用该循环。

3)如果有人对另一种方式有任何想法来实现我的目标,那将是非常受欢迎的。

4)有没有办法让决策者一直“听到”,并在满足某些条件的情况下发送订单打印标题或正文?

到目前为止,我所达到的最大值是阅读&amp;只写一次标题...并在下一步阅读&amp;写17行身体。

谢谢大家! 干杯!!

1 个答案:

答案 0 :(得分:0)

如果我理解你的问题不确定,但这就是你想要实现的目标

第1步:从文件中读取标题

步骤2:读取文件,处理数据并写入某个文件直到某些条件A

步骤3:在条件A上转到步骤1

可以有多个选项来配置它。我能想到的是为流量决策添加额外的步骤..下面是样本配置。

注意我没有对此进行过测试,您可能需要进行一些修改

@Bean
    public Job conditionalJob(JobBuilderFactory jobs, Step conditionalStep1, Step conditionalStep2, Step conditionalStep3, Step conditionalStep4, Step conditionalStep5) throws Exception {
        return jobs.get("conditionalJob")
                .incrementer(new RunIdIncrementer())
                .flow(flowDesider).on("HEADER").to(step1).next("flowDesider")
                .from(flowDesider).on("BODAY").to(step2).next("flowDesider")
                .from(flowDesider).on("*").stop()
                .end()
                .build();
    }



public class flowDesider implements Tasklet{

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public RepeatStatus execute(StepContribution contribution,
        ChunkContext chunkContext) throws Exception {
    logger.info("flowDesider");

    //put your flow logic header 
            //you can use step excequation to pass infomrtion from one step to onother      
    if(codition1)
        return status as HEADER
    if (condition2)
        return status as Body
    if condition3
        return status as complited 


}