Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically choose a spring-batch reader at runtime

I have a spring-batch job that converts various bank statements into my app. There is a different reader for each bank statement type and only one writer for all of them. The job is very simple - read, process and write:

<batch:job id="importer" restartable="true">
    <batch:step id="import">
        <batch:tasklet>
            <batch:chunk reader="reader" writer="writer" processor="processor" commit-interval="10" />
        </batch:tasklet>
    </batch:step>
</batch:job>

Now, I would like the end user to provide a statement file as well as bank information and then choose a corresponding spring-batch reader at runtime for this job to run. Ideally it would be great if I could read-ahead in a first step and tried to "guess" the bank form statement format first. But I digress.

Is it possible to inject a reader into a job prior to running it? Or is there a better way to achieve my goal?

like image 424
Mike Minicki Avatar asked Apr 19 '26 05:04

Mike Minicki


2 Answers

You can set the reader from an input parameter/or a propeties file:

<batch:chunk reader="#{jobParameters['reader.beanId']}" writer="writer" processor="processor" commit-interval="10" />

Also you could consider late binding of job and step attributes, here is the link from spring-batch step-scope

like image 163
Radu Ghiorma Avatar answered Apr 20 '26 19:04

Radu Ghiorma


the problem is, that (File) Itemreaders are constructed before the step starts, meaning the file will be opened before the step starts too


did you try to move the reader transformation and mapping logic to a processor ? you can use a PassThroughLineMapper for this

<bean id="dumbItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    <property name="resource" value="#{jobParameters['input.file']}" />
    <property name="lineMapper">
        <bean class="org.springframework.batch.item.file.mapping.PassThroughLineMapper" />
    </property>
    <property name="strict" value="true" /><!-- optional -->
</bean>

another very clean solution might work with an extra pre-step to find out the needed reader type:

  • create one step who checks the type (either read first line with a classic step configuration, or use a tasklet step)
  • use programmatic flow decision and
  • a step configuration for each reader type
  • each reader step scoped
like image 23
Michael Pralow Avatar answered Apr 20 '26 17:04

Michael Pralow