Spring Batch empty file using FlatFileItemReader xML

1.8k views Asked by At

I'm trying to validate if an input file is empty or has data. I'm working with spring batch thru XML beans config, my actual config is like:

<!-- READERS -->
    <bean id="mgbfItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
        <property name="strict" value="false" />
        <!-- Read a file -->
        <property name="resource" value="file:///fichtemcomp/datent/#{processDataClass.fileName}" />
        <property name="linesToSkip" value="10" />
        <property name="encoding" value="UTF-8" />

        <!-- Mapper -->
        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <!-- split it -->
                <property name="lineTokenizer">
                    <bean
                        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                        <property name="delimiter" value="|" />
                        <!-- Valores del layout -->
                        <property name="names" value="name,secondName,lastName" />
                    </bean>
                </property>

                <!-- Wrapper -->
                <property name="fieldSetMapper">
                    <bean class="com.bbva.mgbf.batch.listeners.ScholarItemReader">
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
    <!-- END READERS -->

In my class Scholar ItemReader, I have something like:

@Override
    public Map<String, Object> mapFieldSet(FieldSet fieldSet) throws BindException {
        LOGGER.info("Reading all items \t {}", fieldSet);
        LOGGER.info("FieldCount \t {}", fieldSet.getFieldCount());

        Map<String, Object> dataIn = new HashMap<>(65);
        if (fieldSet.getFieldCount() > 0 && !fieldSet.readString(0).trim().isEmpty()) {
            LOGGER.info("in if ");

            for (int i = 0; i < 65; i++) {
                String key = "" + i;
                String value = fieldSet.readString(i);
                dataIn.put(key, value);
            }
        }else{
            dataIn.put("empty", "emptyFile");
        }
        return dataIn;
}

But it never entered in the "else " declaration, it just ends the process.

Anyone knows if there are another way to validate if file is empty or not?

2

There are 2 answers

0
Mahmoud Ben Hassine On BEST ANSWER

fieldSetMapper is called when the reader has already read a line, so trying to check if the file is empty in the mapper is too late in the process.

I'm trying to validate if an input file is empty or has data

I would use a pre-validation tasklet step that checks if the file is empty or not.

0
Himadri Pant On

I handled it with a custom NoWorkFoundStepExecutionListener added to the step which has the FlatFileItemReader.

Below is the custom listener:

@Component
public class CustomNoWorkFoundStepExecutionListener implements StepExecutionListener {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        final var totalItemsReadInStep = stepExecution.getReadCount();
        if (totalItemsReadInStep == 0) {
            logger.error("Data flat file is empty.");
            stepExecution.setExitStatus(ExitStatus.FAILED);
            return ExitStatus.FAILED;
        }
        logger.info("Total items read from data flat file → [{}]", totalItemsReadInStep);
        return null;
    }
}

Below is the configuration of step with item reader, processor, writer and the above custom listener:

@Bean
public Step dataInputStep(JobRepository jobRepository,
                                    DataSourceTransactionManager transactionManager,
                                    FlatFileItemReader<DataRecord> dataReader,
                                    ItemProcessor<DataRecord, DataEntity> dataRecordProcessor,
                                    RepositoryItemWriter<DataEntity> dataRepositoryItemWriter,
                                    CustomNoWorkFoundStepExecutionListener listener) {
    return new StepBuilder("dataInputStep", jobRepository)
            .<DataRecord, DataEntity>chunk(10, transactionManager)
            .reader(dataReader)
            .processor(dataRecordProcessor)
            .writer(dataRepositoryItemWriter)
            .listener(listener)
            .build();
}