java FlatFileItemWriter -写入程序必须先打开,然后才能写入

35g0bw71  于 2023-01-11  发布在  Java
关注(0)|答案(3)|浏览(339)

我有一个SpringBatch作业,我跳过所有重复的项目写入平面文件。
但是,只要存在重复项,FlatFileItemWriter就会抛出以下错误:
Writer must be open before it can be written to
下面是编写器和SkipListener配置-

@Bean(name = "duplicateItemWriter")
    public FlatFileItemWriter<InventoryFileItem> dupItemWriter(){

        return new FlatFileItemWriterBuilder<InventoryFileItem>()
                .name("duplicateItemWriter")
                .resource(new FileSystemResource("duplicateItem.txt"))
                .lineAggregator(new PassThroughLineAggregator<>())
                .append(true)
                .shouldDeleteIfExists(true)
                .build();
    }

public class StepSkipListener implements SkipListener<InventoryFileItem, InventoryItem> {

    private FlatFileItemWriter<InventoryFileItem> skippedItemsWriter;
    
    public StepSkipListener(FlatFileItemWriter<InventoryFileItem> skippedItemsWriter) {
        this.skippedItemsWriter = skippedItemsWriter;
    }
    @Override
    public void onSkipInProcess(InventoryFileItem item, Throwable t) {
        System.out.println(item.getBibNum() + " Process - " + t.getMessage());
        
        try {
            skippedItemsWriter.write(Collections.singletonList(item));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

整个作业的定义如下,我使用的是SkipListener中的duplicateItemWriter。

@Bean(name = "fileLoadJob")
    @Autowired
    public Job fileLoadJob(JobBuilderFactory jobs, StepBuilderFactory steps,
            FlatFileItemReader<inventoryFileItem> fileItemReader,
            CompositeItemProcessor compositeItemProcessor,
            @Qualifier(value = "itemWriter") ItemWriter<InventoryItem> itemWriter,
            StepSkipListener skipListener) {

        return jobs.get("libraryFileLoadJob")
                .start(steps.get("step").<InventoryFileItem, InventoryItem>chunk(chunkSize)
                        .reader(FileItemReader)
                        .processor(compositeItemProcessor)
                        .writer(itemWriter)
                        .faultTolerant()
                        .skip(Exception.class)
                        .skipLimit(Integer.parseInt(skipLimit))
                        .listener(skipListener)
                        .build())
                .build();
    }

我也试过将所有数据写入FlatFileItemWriter --效果不太好。但是如果写入DB,就没有问题了。
我使用的Spring-Batch版本是-4.3.3,我也提到了以下线程:

gk7wooem

gk7wooem1#

这只是一个严重的疏忽,我忽略了FlatFileItemWriter需要一个流。我有点失望提出这个问题,但我张贴的答案,以防万一它帮助别人。
解决方案非常简单,只需向作业定义添加一个stream(dupItemWriter)
FlatfileItemWriter with Compositewriter example

@Bean(name = "fileLoadJob")
    @Autowired
    public Job fileLoadJob(JobBuilderFactory jobs, StepBuilderFactory steps,
            FlatFileItemReader<inventoryFileItem> fileItemReader,
            CompositeItemProcessor compositeItemProcessor,
            @Qualifier(value = "itemWriter") ItemWriter<InventoryItem> itemWriter,
@Qualifier(value = "duplicateItemWriter")FlatFileItemWriter<InventoryFileItem> dupItemWriter,
            StepSkipListener skipListener) {

        return jobs.get("libraryFileLoadJob")
                .start(steps.get("step").<InventoryFileItem, InventoryItem>chunk(chunkSize)
                        .reader(FileItemReader)
                        .processor(compositeItemProcessor)
                        .writer(itemWriter)
                        .faultTolerant()
                        .skip(Exception.class)
                        .skipLimit(Integer.parseInt(skipLimit))
                        .listener(skipListener)
                        .stream(dupItemWriter)
                        .build())
                .build();
    }
u59ebvdq

u59ebvdq2#

包含.stream(dupItemWriter)不是绝对必要的,您也可以调用编写器的.open()方法。
在我的例子中,我创建的是动态/编程的ItemWriter,因此将它们添加到流中是不可行的。

.stream(writer-1)
.stream(writer-2)
.stream(writer-N)

相反,我自己调用了.open()方法:

FlatFileItemWriter<OutputContact> itemWriter = new FlatFileItemWriter<>();
itemWriter.setResource(outPutResource);
itemWriter.setAppendAllowed(true);
itemWriter.setLineAggregator(lineAggregator);
itemWriter.setHeaderCallback(writer -> writer.write("ACCT,MEMBER,SOURCE"));
itemWriter.open(new ExecutionContext());
oalqel3c

oalqel3c3#

我遇到了同样的问题,我通过继承FlatFileItemWriter创建了两个编写器。在我添加@StepScope注解之前,这是可以工作的。但是在添加@StepScope注解之后,第一个编写器抛出了一个异常,并显示“Writer必须打开才能写入”错误消息。但是第二个编写器工作起来没有任何问题。我通过调用方法open(new ExecutionContext())解决了这个问题;但是我还是不明白为什么第二个有效而第一个不行。

相关问题