Announcement Announcement Module
Collapse
No announcement yet.
Forward value from Step to Step Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Forward value from Step to Step

    Hi all,

    I'm new in Spring Batch and I'm wondering how it is possible to forward some values from a Step to another one.
    I think it's possible using the execution context but is it the only (and/or the best) way to do it ?
    For example, I'm doing a job that gets some data from a DB as a list of complex objects. Then I'm parsing this list, doing some transformation on my objects before calling writing them in another table.
    I'd like to divide this process in different steps, so, how can I forward my list of objects from a step to a second on ?

    Thanks in advance for answering me,
    Bye.
    Last edited by Zico; Apr 6th, 2009, 12:04 PM.

  • #2
    Zico,

    From what I understand from your example, you can do all the work in a single step by specifying an itemProcessor:

    Code:
    <beans:bean id="myStep" parent="simpleStep">
        <beans:property name="itemReader" ref="myItemReader"/>
        <beans:property name="itemProcessor" ref="myItemProcessor"/>
        <beans:property name="itemWriter" ref="myItemWriter"/>
    </beans:bean>
    Now, to answer directly your question, you can promote values from step-to-step by declaring a promotion listener:

    Code:
    <beans:bean id="promotionListener" class="org.springframework.batch.core.listener.ExecutionContextPromotionListener">
        <beans:property name="keys">
            <beans:list>
                 <beans:value>key1</beans:value>
    	<beans:value>key2</beans:value>
            </beans:list>
        </beans:property>
    </beans:bean>
    Where key1 and key2 are keys to value in the executionContext.

    Then, add the above promotionListener to the listeners property of the step that you want to promote from:

    Code:
    <beans:property name="listeners">
        <beans:list>
            <beans:ref bean="promotionListener"/>
        </beans:list>
    </beans:property>
    Good luck!

    - Gino

    Comment


    • #3
      The way to do this is indeed to store your list in the ExecutionContext. The catch is that there are two ExecutionContexts: one at the step level and one at the job level. The Step ExecutionContext lives only as long as the step while the Job ExecutionContext lives through the whole job. On the other hand, the Step ExecutionContext is updated every time the step commits a chunk while the Job ExecutionContext is updated only at the end of each step.

      So, the consequence of all this is that if you want to pass data from one step to the next, you will have to put it in your Step ExecutionContext while the step is executing. This way it will be stored properly while the step is on-going in case your step fails. To make the data available to the next step, you will have to "promote" the data to the Job ExecutionContext after the step has finished. Lucky for you, Spring Batch comes with a ExecutionContextPromotionListener to do just that. Just configure it with the keys to promote and register it as a listener on your step, and you'll be set.

      Comment


      • #4
        Is it possible to pass the Job Parameters from the Job to ItemReader/ItemWriters

        Comment


        • #5
          You can use a BeforeStep method on any class to get the JobParameters and then store them locally (be sure to register the class as a listener in the config):

          Code:
          @BeforeStep
          public void beforeStep(StepExecution stepExecution) {
              this.jobParameters = stepExecution.getJobParameters();
          }
          Or more usefully, you can use late binding to inject a parameter into your reader or writer:
          Code:
          <bean id="flatFileItemReader" scope="step"
                class="org.springframework.batch.item.file.FlatFileItemReader">
              <property name="resource" value="#{jobParameters[input.file.name]}" />
          </bean>
          Last edited by DHGarrette; Apr 6th, 2009, 01:30 PM.

          Comment


          • #6
            For late-binding, have a look at this doc: http://static.springsource.org/sprin...l#late-binding

            Comment


            • #7
              Thanks Dan and Cerrog for the response.

              I have set of files which will be feed from a directory/batch job as well as same format file will be manually provided by the user. If the user has given the file, there may be problem with data/format which I need to report to the user via the SimpleFormController - error object. If there are no errors, I have to provide a success message.

              Will I be able to leverage the Spring Batch for these type files. If so, what is right approach/model for process via the user interface.

              Your help on this is much appreciated

              Comment


              • #8
                Ok thanks a lot for all these answers.
                I've checked for using the job execution and the beforeStep/afterStep methodes and it could be useful.
                But now, actually, my needs have changes a bit (thanks to the customer :P)
                I receive a list of complex objects with another list inside.
                How can I make this kind of process:

                1) Read and iterate on this list "L1"
                3) For each one of the "L1" elements, i'd like to execute this kind of step

                3.1) BeforeStep: call to a service
                3.2) Step process:

                - read and iterate on the list "L2" contained in the "L1" elements (reader)
                - transformation of the object (processor)
                - call to a service for writing it (writer)
                3.3) AfterStep: call to a service
                This is similar to a concept of job/step/sub-step I think. Is there a way of implementing this ? I had a look on the "RepeatTemplate" interface but I have to admit that I did not really understood how it works.
                Anyone could help me please ? Thans a lot.

                Comment


                • #9
                  You can't really have a "sub-step". You should simply put a loop in your writer. So the ItemReader reads items from L1. Then ItemWriter is something like:
                  Code:
                  public void write(L1Item l1item) {
                      for(L2Item l2item : l1Item.getL2()) {
                           //transform l2item
                           //write l2item
                      }
                  }
                  You can use @BeforeWrite and @AfterWrite listeners to call the services since these are called before and after the writer is called as opposed to the entire step

                  Comment

                  Working...
                  X