Announcement Announcement Module
Collapse
No announcement yet.
Getting step context in processor for partitioned step Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting step context in processor for partitioned step

    I'm developing a Spring Batch job that processes multiple input files in parallel using a MultiResourcePartitioner. In the ItemProcessor I need to get the number of records in the current input file. I get the current file name from the step context and read the number of lines in the file. But I'm getting exceptions when accessing the step context from the processor threads:

    Code:
    2013-05-15 11:44:35,210 ERROR [org.springframework.batch.core.step.AbstractStep] <taskExecutor-3> - Encountered an error executing the step
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.processor': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:341)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
        at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
        at $Proxy14.process(Unknown Source)
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:125)
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:291)
        at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:190)
        at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74)
        at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
        at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
        at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
        at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
        at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
        at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
        at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
        at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:120)
        at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:118)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
        at java.util.concurrent.FutureTask.run(FutureTask.java:166)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)
    Caused by: java.lang.IllegalStateException: No context holder available for step scope
        at org.springframework.batch.core.scope.StepScope.getContext(StepScope.java:197)
        at org.springframework.batch.core.scope.StepScope.get(StepScope.java:139)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:327)
        ... 24 more
    Is there a way to get data from the step contextthe processor of a partitioned job?

    Here is the relevant config:
    Code:
    <batch:job id="acct">
        <batch:step id="init" parent="abstractStep" next="processStep">
            <batch:tasklet ref="fileDeleteTasklet" />
        </batch:step>
        <batch:step id="processStep">
            <batch:partition step="processInput" partitioner="partitioner">
                <batch:handler grid-size="2" task-executor="taskExecutor" />
            </batch:partition>
        </batch:step>
    </batch:job>
    
    <batch:step id="processInput">
        <batch:tasklet>
            <batch:chunk reader="reader" processor="processor" writer="writer" commit-interval="3">
                <batch:streams>
                    <batch:stream ref="reader"/>
                    <batch:stream ref="flatFileItemWriter"/>
                </batch:streams>
            </batch:chunk>
        </batch:tasklet>
    </batch:step>
    
    <bean id="partitioner" class="org.springframework.batch.core.partition.support.MultiResourcePartitioner" scope="step">
        <property name="keyName" value="fileName"/>
        <property name="resources" value="file:#{jobParameters['inputFilePattern']}"/>
    </bean>
    
    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="5"/>
        <property name="maxPoolSize" value="5"/>
    </bean>
    
    <bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
        <property name="resource" value="#{stepExecutionContext[fileName]}" /> 
        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer">
                    <bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
                        <property name="names" value="recordType,reserved,aCode,bCode,acctNumber,idType,cCode" />
                        <property name="columns" value="1,2,3-6,7-9,10-15,16,17-19" />
                        <property name="strict" value="false" />
                    </bean>
                </property>
                <property name="fieldSetMapper">
                    <bean class="com.example.batch.acct.AcctInputFieldSetMapper" />
                </property>
            </bean>
        </property>
    </bean>
    
    <bean id="processor" class="com.example.batch.acct.AcctProcessor" scope="step">
        <property name="soapClient"  ref="soapClient" />
        <property name="maxNumIds"   value="${batch.soap.numberOfIds}" />
        <aop:scoped-proxy />
    </bean>

  • #2
    1. What are you trying to do with the <aop:scoped-proxy/> config in your processor?
    2. Where are you actually attempting to inject the StepContext into the processor?

    Comment


    • #3
      1. I'm not actually using <aop:scoped-proxy/>. That was a copy & paste from an earlier attempt to address the error message (consider using a scoped proxy). Sorry about the misdirection.
      2. I didn't think I had to explicitly inject the StepContext into the processor if I used scope="step" on the bean. Could you point me to an example of injecting StepContext ? Thanks.

      Comment


      • #4
        The ItemProcessor interface does not expose a way to access the StepContext so you need to inject it yourself. To do that:
        Code:
        <bean id="itemProcessor" class="com.myApp.MyItemProcessor" scope="step">
            <property name="stepContext" value="#{stepExecutionContext}"/>
        </bean>
        Assuming your processor class has an exposed property named stepContext.

        Comment


        • #5
          That works, thanks. I was a bit confused about the difference between StepContext and StepExecutionContext but I get it now.

          Comment


          • #6
            Hi,

            Could you post your full spring context since i'm interested to see if you have any specific aop or special configurations.

            I have this bean

            <bean id="abstractStagingWriter" class="lu.scoteqint.messaging.hedging.global.write r.AbstractStagingWriter" scope="prototype" abstract="true">
            <property name="stepExecution" value="#{stepExecutionContext}"/>
            <property name="hedgingStagingDataSource" ref="hedgingStagingDataSource"/>
            </bean>

            using these imports from spring 2.2.2

            <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:util="http://www.springframework.org/schema/util"
            xmlns:batch="http://www.springframework.org/schema/batch"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schem...ring-beans.xsd
            http://www.springframework.org/schema/util
            http://www.springframework.org/schem...pring-util.xsd
            http://www.springframework.org/schema/batch
            http://www.springframework.org/schema/batch/spring-batch.xsd"
            default-lazy-init="false">

            but i keep getting this error

            Caused by: org.springframework.expression.spel.SpelEvaluation Exception: EL1008Epos 0): Field or property 'stepExecutionContext' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpr essionContext'
            at org.springframework.expression.spel.ast.PropertyOr FieldReference.readProperty(PropertyOrFieldReferen ce.java:208)
            at org.springframework.expression.spel.ast.PropertyOr FieldReference.getValueInternal(PropertyOrFieldRef erence.java:72)
            at org.springframework.expression.spel.ast.SpelNodeIm pl.getValue(SpelNodeImpl.java:93)
            at org.springframework.expression.spel.standard.SpelE xpression.getValue(SpelExpression.java:88)
            at org.springframework.context.expression.StandardBea nExpressionResolver.evaluate(StandardBeanExpressio nResolver.java:139)

            Comment

            Working...
            X