0

I've implemented ResourceAware in my domain object to set resource name when using MultiResourceItemReader. I'm successfully able to retrieve the resource name in Processor. However, I'm not able to access the resource name in FlatFileItemWriter since I don't have access to the domain object, after classifying using ClassifierCompositeItemWriter. Any help would be much appreciated.

Configuration

 stepBuilderFactory.get("enrichmentStep")
.<RecordType, RecordType>chunk(1)
.reader(multiResourceItemReader())
.processor(processor())
.writer(compositeWriter())
.stream(type0Writer())
.stream(type1Writer())
.stream(type2Writer())

Writer

public ClassifierCompositeItemWriter compositeWriter() throws Exception {
  ClassifierCompositeItemWriter<RecordType> writer = new ClassifierCompositeItemWriter<>();
  SubclassClassifier classifier = new SubclassClassifier<>();
  Map typeMap = new HashMap<>();
  typeMap.put(RecordType0.class, type0Writer());
  typeMap.put(RecordType1.class, type1Writer());
  typeMap.put(RecordType2.class, type2Writer());
  classifier.setTypeMap(typeMap);
  writer.setClassifier(classifier);
  return writer;
}

@Bean
public FlatFileItemWriter<RecordType0> type0Writer() throws Exception{
  FlatFileItemWriter<RecordType0> writer = new FlatFileItemWriter<>();
  writer.setResource( new FileSystemResource("")); //To get the resource value from domain object here
  writer.setAppendAllowed(true);
  writer.setLineAggregator(new DelimitedLineAggregator<RecordType0>() {{
  setDelimiter("#");
  setFieldExtractor(new BeanWrapperFieldExtractor<RecordType0>() {{
  setNames(new String[] { "RecordType", "BatchID", "SubBatchID"});}});}});
   return  writer;
}
pulikuttie
  • 35
  • 5
  • `writer.setResource( new FileSystemResource("")); //To get the resource value from domain object here`: This line of code is executed at configuration time. Here you are configuring an `ItemWriter` bean in a Spring application context. The job and step have not started yet and no items are read at this point. Why do you need the resource from the item here? Since you pass the input resources to the job (I guess a job parameter) you should be able pass them around as needed to step-scoped beans. Can you explain what are you trying to achieve without referring to Spring Batch? – Mahmoud Ben Hassine Mar 15 '21 at 08:48
  • I need to have the output file names to be the same as the input files. The input resources are set in `MultiResourceItemReader` from a folder. I'm trying to figure out a way to pass these file names to the Writer. Since there are multiple multi-format files as input, Classifier is sending it to the appropriate `FlatFileItemWriter` where I'm setting the output resource. – pulikuttie Mar 15 '21 at 14:11
  • Do these resources need to be dynamically determined? I mean since you know in which file an item should be written upfront, why don't you create 3 writers preconfigured with resources like `records-type0.csv`, `record-type1.csv`, `records-type2.csv` and pass them to the composite writer? If you do need to determine file names dynamically based on the array of files you pass to the `MultiResourcesItemReader`, then you would need a step that determines output file names and pass them to your chunk-oriented step through the execution context. – Mahmoud Ben Hassine Mar 16 '21 at 10:43
  • I tried passing the filename dynamically, but there were many complex logic involved it making it work, as I'm also using a `SingleItemPeekableItemReader`. Finally, I created a `MultiResourcePartitioner` and called the `SyncTaskExecutor()` and accessed the values using `@Value("#{stepExecutionContext[fileName]}")` by declaring the Bean as `@StepScope`. I understand there is no point in using a Partitioner for a synchronous batch process, but this is the simplest solution I could come up with. – pulikuttie Apr 07 '21 at 08:38

0 Answers0