Search code examples
springspring-batch

use value from step in job xml file configuration in spring batch


I have a spring batch job where I need to get a value from database in a step and use that value in a reader in an other step . but I m getting an error saying :

'Invalid property 'id' of bean class [org.springframework.batch.core.scope.context.StepContext]: Bean property 'id' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?'

here I will put only the relevant part of my files to be clear , if need extra infos I can add it , thanks

xml config file:

    <bean id="setter" class="fat.IdSetter" scope="step">
             <property name="id" value="#{stepExecutionContext([id])}"></property>
         </bean>

        <bean id="reader"
            class="org.springframework.batch.item.database.JdbcCursorItemReader" >
            <property name="dataSource" ref="dataSource" />
            <property name="sql" value="SELECT * FROM  TABLE WHERE ID = ?" />
            <property name="rowMapper">
                <bean class="fat.RowMapper"></bean>
            </property>
            <property name="preparedStatementSetter" ref="setter"></property>
        </bean>
<batch:job id="job">

       <batch:step id="getId" next="loopStep">
         <batch:tasklet ref="getId"></batch:tasklet>
       </batch:step>

       <batch:step id="loopStep">
            <batch:tasklet>
                <batch:chunk reader="reader" processor="processor"
                    writer="xmlWriter" commit-interval="1000">
                </batch:chunk>
                <batch:listeners>
                    <batch:listener ref="footerCallBack"></batch:listener>
                    <batch:listener ref="headerCallBack"></batch:listener>
                </batch:listeners>
            </batch:tasklet>
        </batch:step>
    </batch:job>

<bean id="getId" class="fat.GetId" >
      <property name="restCall" ref="restCall"></property>
    </bean>

the tasklet where I get the value of id :

public class GetId implements Tasklet {

@Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

       // here I call my web service to get data  and put it in a Long variable named id 

        chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put("id",
                        id);

        return RepeatStatus.FINISHED;
    }


}

the prepared statement setter for id class:

public class IdSetter implements PreparedStatementSetter {

    private Long id;
    @Override
    public void setValues(PreparedStatement ps) throws SQLException {

        ps.setLong(1 , id);
    }

    public Long getId() {
        return id;
    }


    public void setId(Long id) {
        this.id = id;
    }



}

I think the error because it didn t find the id parameter in the stepExecutionContext , any help is appreciated.


Solution

  • Your tasklet GetId puts the id in the job execution context. So your reader can get it from there as follows:

    <bean id="reader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step" >
            <property name="dataSource" ref="dataSource" />
            <property name="sql" value="SELECT * FROM  TABLE WHERE ID = #{jobExecutionContext[id]}" />
            <property name="rowMapper">
                <bean class="fat.RowMapper"></bean>
            </property>
            <!-- <property name="preparedStatementSetter" ref="setter"></property> --> // This is not needed
    </bean>
    

    Note that the reader should step scoped. With that, you don't need the bean named setter.

    Another option is to pass the id as a job parameter and use it in the reader (See example here).