Results 1 to 9 of 9

Thread: Forward value from Step to Step

Hybrid View

  1. #1
    Join Date
    Feb 2009
    Location
    Paris
    Posts
    30

    Default 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 at 11:04 AM.

  2. #2
    Join Date
    Feb 2009
    Location
    Montreal, Qc, Canada
    Posts
    23

    Post

    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

  3. #3
    Join Date
    Feb 2008
    Posts
    488

    Default

    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.

  4. #4
    Join Date
    Apr 2009
    Posts
    13

    Default

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

  5. #5
    Join Date
    Feb 2008
    Posts
    488

    Default

    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 at 12:30 PM.

  6. #6
    Join Date
    Feb 2009
    Location
    Montreal, Qc, Canada
    Posts
    23

    Default

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

  7. #7
    Join Date
    Apr 2009
    Posts
    13

    Default

    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

  8. #8
    Join Date
    Feb 2009
    Location
    Paris
    Posts
    30

    Default

    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.

  9. #9
    Join Date
    Feb 2008
    Posts
    488

    Default

    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •