Search code examples
spring-batch

FlatFileItemWriter write header only in case when data is present


have a task to write header to file only if some data exist, other words if reader return nothing file created by writer should be empty.

Unfortunately FlatFileItemWriter implementation, in version 3.0.7, has only private access fields and methods and nested class that store all info about writing process, so I cannot just take and overwrite write() method. I need to copy-paste almost all content of FlatFileItemWriter to add small piece of new functionality.

Any idea how to achieve this more elegantly in Spring Batch?


Solution

  • So, finally found a less-more elegant solution.

    The solution is to use LineAggregators, and seems in the current implementation of FlatFileItemWriter this is only one approach that you can use safer when inheriting this class.

    I use a separate line aggregator only for a header, but the solution can be extended to use multiple aggregators.

    Also in my case header is just predefined string, thus I use PassThroughLineAggregator by default that just return my string to FlatFileItemWriter.

    public class FlatFileItemWriterWithHeaderOnData extends FlatFileItemWriter {
    
        private LineAggregator lineAggregator;
        private LineAggregator headerLineAggregator = new PassThroughLineAggregator();
    
        private boolean applyHeaderAggregator = true;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            Assert.notNull(headerLineAggregator, "A HeaderLineAggregator must be provided.");
            super.afterPropertiesSet();
        }
    
        @Override
        public void setLineAggregator(LineAggregator lineAggregator) {
            this.lineAggregator = lineAggregator;
            super.setLineAggregator(lineAggregator);
        }
    
        public void setHeaderLineAggregator(LineAggregator headerLineAggregator) {
            this.headerLineAggregator = headerLineAggregator;
        }
    
        @Override
        public void write(List items) throws Exception {
            if(applyHeaderAggregator){
                LineAggregator initialLineAggregator = lineAggregator;
                super.setLineAggregator(headerLineAggregator);
                super.write(getHeaderItems());
                super.setLineAggregator(initialLineAggregator);
                applyHeaderAggregator = false;
            }
    
            super.write(items);
        }
    
        private List<String> getHeaderItems() throws ItemStreamException {
            // your actual implementation goes here
            return Arrays.asList("Id,Name,Details");
        }
    }
    

    PS. This solution assumed that if method write() called then some data exist.