当达到下一步骤的条件时,如何不确定地返回上一步 [英] How to return indefinetely to previous Step when condition of a following Step is reached Spring Batch

查看:86
本文介绍了当达到下一步骤的条件时,如何不确定地返回上一步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Hello Spring Batch community! I have an input flat file with a header and a body. header is 1 line (naturally..) and 5 parameters. Body can reach up to 1 million records with 12 parameters each.

输入文件:

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
.
.   
.

我需要将此文件写入具有特定格式且具有以下特定结构的.txt文件中:

I need to write this into a .txt file with certain format, and in this specific structure:

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

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

What I did was... create a stepHeader and a stepBody . Each of them with their own reader, processor (business formatter) and writer.

该工作只有两个简单步骤.

The job will have only this 2 simple steps.

@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();
}

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

The header i read is configured with MaxItemCount=1, and mapped it to CabeceraFacturacion:

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

我以这种方式读取它的主体,跳过第一行,然后将其映射到DetalleFacturacion:

The body i read it this way, skipping first line, and mapped it to DetalleFacturacion:

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

我的步骤:

@Bean
public Step stepHeader() throws Exception {
    return stepBuilderFactory.get("stepHeader")
            .<CabeceraFacturacion, CabeceraFacturacion> chunk(17)
            .faultTolerant()
            .listener(new ChunkListener())
            .reader(readerCabecera())
            .writer(writerCabeceraFact())
            .allowStartIfComplete(true)
            .build();
}


@Bean
public Step stepBody() {
    return stepBuilderFactory.get("stepBody")
            .<DetalleFacturacion, DetalleFacturacion> chunk(17)
            .chunk(17)
            .faultTolerant()
            .listener(new ChunkListener())
            .reader(readerDetalleFacturacion())
            .writer(writerDetalleFact())
            .listener(new StepExecutionListener() {

                @Override
                public ExitStatus afterStep(StepExecution stepExecution) {
                    if(stepExecution.getWriteCount()==17) {

                        return new ExitStatus("BACK TO STEPHEADER");                    
                    };

//                      if(stepExecution.getReadCount()<17) {
//                          return new ExitStatus("END");                   

//                      }

                    return null;
                }

                @Override
                public void beforeStep(StepExecution stepExecution) {


                }


            })
            .allowStartIfComplete(true)
            .build();
}

1)在文件结束之前,我不知道如何无限期地返回到StepHeader.在那儿我尝试了usind stepExecution.getWriteCount(17)..但我不确定这是怎么回事.

1) I don't know how to achieve going back to the StepHeader indefinetely until the file ends. There i tried usind the stepExecution.getWriteCount(17).. but i'm not sure this is the way.

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

2) i don´t know how to read 17 different records every time it loops ( i managed to make it loop but it would write the same first 17 records over and over again until i manually stopped the job. I now know that loops are not recommended in Spring Batch processes.

3)如果有人对实现我的目标的其他方法有任何想法,将非常欢迎.

3) if anyone has any idea on another way to achieve my goal, it will be most welcome.

4)是否有一种方法可以使决策程序始终处于聆听状态",并在满足某些条件的情况下发送打印标题或正文的命令?

4) Is there a way to make a decider that's "hearing" all the time, and sends the order to print header or body if certain condition is satisfied?

到目前为止,我获得的最大成就是阅读&只写一次标题...,然后在下一步中阅读&写17行身体.

Up until now, the max i achieved is to read & write only one time the header... and in the next step read & write 17 lines of the body.

谢谢大家! 干杯!

推荐答案

不确定我是否正确理解了您的问题,但这就是您想要实现的目标

Not Sure if i understood your question correctly, But this what you want to achive

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

Step 1 : Read header from file

第2步:读取文件,处理数据并写入某些文件,直到出现某种情况A

Step 2 : Read file ,process data and write to some file Until some condition A

步骤3:在条件A下,转到步骤1

Step 3 : On Condition A Go to Step 1

可以有多个选项来配置它.我能想到的是通过增加流量决策的额外步骤..下面是示例配置.

There can be multiple options to configure this. the one i can think is by adding additional step for flow decision .. below is sample configuration.

注意,我尚未对此进行测试,您可能需要进行一些修改

Note I have not tested this, you might have to do some modifications

@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 


}

这篇关于当达到下一步骤的条件时,如何不确定地返回上一步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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