Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Maintain State in between reads

  1. #1

    Default Maintain State in between reads

    I am doing this POC and plan to use Spring batch for some response jobs via MQ via Spring integration. The response jobs will be triggered via a command message in MQ.
    Now it a a XML document which has some nodes in them with their attributes. What I need to do is do some calculation like summing up all the dollar amount number of occurrences of a particular node and write it to a footer.
    I already know that I will be using the Footer Call back but how do I aggregate those information which I have already looped through. Where would be the best place to maintain that state ..again taking care of any unforeseen multi threading issues ?

  2. #2

    Default

    Put the aggregated data in the StepExecution ExecutionContext. The ExecutionContext stores its data in a ConcurrentHashMap.

  3. #3

    Default

    I was reading about Holder objects will that be a good fit at all ? I see issues with it personally.

    How do I expose the context in my chunk ?

  4. #4

    Default

    Add StepExecution as an attribute of your ItemWriter (you can do the same with your ItemReader or ItemProcessor). Then add the following code to your ItemWriter.

    Code:
        @BeforeStep
        public void beforeStep(StepExecution stepExecution)
        {
            this.stepExecution = stepExecution;
        }
    You can get the execution context from the StepExecution.

    Code:
    stepExecution.getExecutionContext().put("aggregatedObject", myObject);
    ......
    stepExecution.getExecutionContext().get("aggregatedObject");

  5. #5

    Default

    In regards to holder objects, I really think that is what the ExecutionContext is for. There is a Step ExecutionContext and a Job ExecutionContext. Also remember that data in the ExecutionContext will be persisted to the meta data tables (if you are using them). If you want to avoid persisting the data, but still utilize the ExecutionContext, you can do something where you create a class that has transient attributes and put that in the ExecutionContext. I did something like this.

    Code:
    public class TransientExecutionContextHolder implements Serializable
    {
        private static final long serialVersionUID = 9091253786962577441L;
    
        private transient ExecutionContext executionContext = new ExecutionContext();
    
        /**
         * @return the executionContext
         */
        public ExecutionContext getExecutionContext()
        {
            return executionContext;
        }
    
    }

  6. #6

    Default

    Thanks sky. Interestingly enough the StepContext is not set in the delegates if using a org.springframework.batch.item.support.CompositeIt emProcessor
    any ideas ?

    <CODE>
    <bean id="parentProcessor" class ="org.springframework.batch.item.support.Composite ItemProcessor">
    <property name="delegates">
    <util:list>
    <ref bean="claimsItemProcessor"/>
    <ref bean="lineItemLevelProcessor"/>
    </util:list>

    </property>

    </bean>

    </CODE>

  7. #7

    Default

    Yeah, the delegates will not get registered via the annotation. What I usually end up doing is something like:

    Code:
    @BeforeStep
        public void beforeStep(StepExecution stepExecution)
        {
            this.stepExecution = stepExecution;
            this.delegate1.beforeStep(stepExecution);
            this.delegate2.beforeStep(stepExecution);
        }

  8. #8

    Default

    sorry may be I did not get it

    how do I call the beforeStep method since the delegates are mere Itemprocessors

    Here is the list that is in the CompositeItemProcessor

    Code:
    private List<ItemProcessor<Object, Object>> delegates;

  9. #9

    Default

    Code:
    public class TransientExecutionContextHolder implements Serializable
    {
        private static final long serialVersionUID = 9091253786962577441L;
    
        private transient ExecutionContext executionContext = new ExecutionContext();
    
        /**
         * @return the executionContext
         */
        public ExecutionContext getExecutionContext()
        {
            return executionContext;
        }
    
    }


    And the 'TransientExecutionContextHolder' will be a bean definition in the xml correct ?

  10. #10

    Default

    Sorry didn't catch that you were using the Spring provided CompositeItemProcessor. Normally anytime I am doing composites, I create my own ItemProcessor to do this. I think what you would need to do is have your delegates implement StepExecutionListener. And then register the listeners with the step in the config.

    Code:
           <step id="myStep"  >
                <tasklet>
                    ......................
                    <listeners>
                        <listener ref="delegateProcessor1"/>
                        <listener ref="delegateProcessor2"/>
                    </listeners>
                </tasklet>
            </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
  •