【问题标题】:Error with Spring batch Classifier Composite Item WriterSpring批处理分类器复合项目编写器出错
【发布时间】:2020-05-17 14:12:17
【问题描述】:

我基本上必须为每种货币的每个 file_id 生成多个 xml 文件(即 usd、zar ect),这些交易都在 1 个 DB 表中。我是否为每种货币创建一个复合编写器,并在我的项目处理器上过滤我从数据库中读取的每种不同货币。或者我可以对每个 file_id 的每种货币使用多个步骤吗?我一直在努力寻找一个 Springbatch 解决方案。

每个文件和货币的文件名资源都不同。例如,我可以收到 file_id=1 currency=USD 需要 1 个文件 'USD20051701 和 01 文件序列'。我还可以获得 Currency ='ZAR' 的两个文件 file_id 1 和 2,它们需要是两个文件 'ZAR20051701' 和 'ZAR20051702' 01 和 02 文件序列。

我使用此链接作为其中一篇文章的指南。 https://stackoverflow.com/a/53388876/13056119

我正在获取此跟踪日志 Log File

请帮忙,我在调试日志屏幕截图时遇到了困难。我已经编写了一个分类器来写入 3 个不同的文件,每种货币,但我得到一个错误

@Bean
public ClassifierCompositeItemWriter<Settlement> classifierCompositeItemWriter
        (       ItemWriter<Settlement> ZMWItemWriter,
                ItemWriter<Settlement> USDItemWriter, 
                ItemWriter<Settlement> ZARItemWriter
    ) {
    ClassifierCompositeItemWriter<Settlement> classifierCompositeItemWriter = new ClassifierCompositeItemWriter<>();
    classifierCompositeItemWriter.setClassifier(new Classifier<Settlement, ItemWriter<? super Settlement>>() {
        
        @Override
        public ItemWriter<? super Settlement> classify(Settlement settlement) {
            
            List<SettlementHeader> settlementheader= new ArrayList<SettlementHeader>();
            SettlementHeader header = new SettlementHeader ();
            settlementheader.add(header);
            settlement.setSettlementHeader(settlementheader);
            
        if (header.getCurrency().equalsIgnoreCase("ZMW")) {
            return ZMWItemWriter;
        } 
        else if (header.getCurrency().equalsIgnoreCase("USD")) {
            return USDItemWriter;
        }
        else {
            return ZARItemWriter;}
        }
    });
    return classifierCompositeItemWriter;
}

    @Qualifier ("USDItemWriter")
    @Bean(destroyMethod="")
   public NoRootStaxEventItemWriter<Settlement> USDItemWriter() throws Exception {
    NoRootStaxEventItemWriter<Settlement> ItemWriter = new NoRootStaxEventItemWriter<>();
    FileSystemResource resource = new FileSystemResource("FileUSD1.xml");
    ItemWriter.setName("USDItemWriter");
       ItemWriter.setResource(resource);
       marshaller.setPackagesToScan("com.model");
       ItemWriter.setMarshaller(marshaller);
       ItemWriter.afterPropertiesSet();
       return ItemWriter;
   }

@Primary
@Qualifier("ZARItemWriter") 
@Bean(destroyMethod="")
   public NoRootStaxEventItemWriter<Settlement> ZARItemWriter() throws Exception {
    NoRootStaxEventItemWriter<Settlement> ItemWriter = new NoRootStaxEventItemWriter<>();
    FileSystemResource resource = new FileSystemResource("FileZAR1.xml");
    ItemWriter.setName("ZARItemWriter");
       ItemWriter.setResource(resource);
       marshaller.setPackagesToScan("com.model");
       ItemWriter.setMarshaller(marshaller);
       ItemWriter.afterPropertiesSet();
       return ItemWriter;
   }
    @Qualifier("ZMWItemWriter")
    @Bean(destroyMethod="")
   public NoRootStaxEventItemWriter<Settlement> ZMWItemWriter() throws Exception {
    NoRootStaxEventItemWriter<Settlement> ItemWriter = new NoRootStaxEventItemWriter<>();
    FileSystemResource resource = new FileSystemResource("FileZMW1.xml");
    ItemWriter.setName("ZMWItemWriter");
    ItemWriter.setResource(resource);
    marshaller.setPackagesToScan("com.model");
    ItemWriter.setMarshaller(marshaller);
    ItemWriter.afterPropertiesSet();
      return ItemWriter;
   }

【问题讨论】:

  • 嗨,你在正确的轨道上,问题是你的文件名不是动态的。我有一个关于和解的问题。它只有一个标题还是多个标题
  • @youness.bout 每个 File_Id 都有自己的 Header 和交易列表。例如,文件 1 将有 1 个标头和 100 个货币美元交易
  • 公共类 SettlementHeader { private LocalDate prcDte;私有字符串文件名;私有字符串服务;私有字符串子服务;私人 int 发件人;私有字符串运行模式;私有字符串货币;私人 int prcWndwNum;私有 int 文件 ID; filename 应该是创建的文件的名称。

标签: spring spring-batch classification itemwriter compositeitemwriter


【解决方案1】:

请检查下面的示例,看看它是否适合您。您创建一个 Map Writer 以避免每次都实例化一个新的 Writer。

一个 Writer 由 (FileId, ProcessDate, Detail Currency) 唯一标识:

String fileNameKey = item.getHeader().getFileId() + item.getHeader().getProcessDate().toString() + settlementDetail.getCurrency();

这里是作者的代码:

@Component
public class SettlementWriter implements ItemStream, ItemWriter<Settlement> {

    private final Map<String, StaxEventItemWriter<Settlement>> writers = new HashMap<>();

    private ExecutionContext executionContext;

    @Autowired
    private Marshaller marshaller;

    @Override
    public void open(ExecutionContext executionContext) throws ItemStreamException {
        this.executionContext = executionContext;
    }

    @Override
    public void update(ExecutionContext executionContext) throws ItemStreamException {
    }

    @Override
    public void close() throws ItemStreamException {
        for (StaxEventItemWriter f : writers.values()) {
            f.close();
        }
    }

    @Override
    public void write(List<? extends Settlement> items) throws Exception {
        for (Settlement item : items) {
            for (SettlementDetail det : item.getDetails()) {
                StaxEventItemWriter<Settlement> detailWriter = getFlatFileItemWriter(item, det);
                detailWriter.write(Arrays.asList(item));    
            }
        }
    }

    public StaxEventItemWriter<Settlement> getFlatFileItemWriter(Settlement item, SettlementDetail settlementDetail) {
        String fileNameKey = item.getHeader().getFileId() + item.getHeader().getFilename() + settlementDetail.getCurrency();

        StaxEventItemWriter<Settlement> itemWriter = writers.get(fileNameKey);

        if (itemWriter == null) {

            itemWriter = new StaxEventItemWriter<>();

            try {

                FileSystemResource resource = new FileSystemResource(fileNameKey+".xml");

                itemWriter.setName(fileNameKey);
                itemWriter.setResource(resource);
                marshaller.setPackagesToScan("com.model");
                itemWriter.setMarshaller(marshaller);
                itemWriter.afterPropertiesSet();

                itemWriter.open(executionContext);

            } catch (Exception e) {
                e.printStackTrace();
            }
            writers.put(fileNameKey, itemWriter);
        }
        return itemWriter;
    }
}

希望这会有所帮助。

【讨论】:

  • @Youness- 我有一个复合 StaxEvent 项目编写器,它覆盖了重复的根元素。如何将分类器和复合编写器结合起来?
  • 您的 CompositeWriter 是 Writer,请尝试在 SettlementWriter 中使用它而不是 StaxEventItemWriter
猜你喜欢
  • 2021-11-19
  • 2013-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
  • 1970-01-01
相关资源
最近更新 更多