Issue Details (XML | Word | Printable)

Key: BATCH-380
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Blocker Blocker
Assignee: Dave Syer
Reporter: Adrian Shum
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Spring Batch

Step Scope problem in TaskletStep

Created: 22/Feb/08 03:51 AM   Updated: 07/Aug/08 10:06 AM
Component/s: Core
Affects Version/s: 1.0.0.m4
Fix Version/s: 1.0.0.m5

Time Tracking:
Original Estimate: 0.12d
Original Estimate - 0.12d
Remaining Estimate: 0.12d
Remaining Estimate - 0.12d
Time Spent: Not Specified
Remaining Estimate - 0.12d

File Attachments: 1. Java Source File TaskletStep.java (6 kB)
2. Text File TaskletStep.patch (2 kB)
3. Zip Archive temp.zip (3 kB)

Environment: JDK5, Junit4.4, Eclipse 3.3 + m2Eclipse, maven 2.7


 Description  « Hide
snippet of app context config:
    <!-- stuffs that copied from simple-container-definition.xml -->

    <bean id="job" parent="simpleJob">
        <property name="steps">
            <list>
                <bean id="step1" parent="taskletStep">
                    <property name="tasklet">
                        <bean id="tradeTasklet"
                                class="foo.sample.TradeMatchTasklet"
                                scope="step">
                            <aop:scoped-proxy />
                            <property name="status" value="9"/>
                        </bean>
                    </property>
                </bean>
            </list>
        </property>
    </bean>


My Unit test:
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration
@Transactional
@ContextConfiguration(locations={"/mysample/sample1-job.xml"})
public class TradeMatchBatchTests {

    @Resource
    JobLauncher jobLauncher;

    @Resource
    private Job job;

    @Resource
    MapJobRegistry jobConfigurationRegistry;

    @Test
    public void testLaunchJob() throws Exception {
        Map<String, String> strParam = new HashMap<String, String>();
        strParam.put("KEY", "1");
        JobParameters jobParam = new JobParameters(strParam, new HashMap(), new HashMap());

        JobExecution x = jobLauncher.run(job, jobParam);
    }
}


Once it is run, following exception is thrown:


2008-02-21 19:26:01,645 INFO [org.springframework.batch.execution.launch.SimpleJobLauncher] - <Job: [SimpleJob: [name=job]] failed with the following parameters: [{KEY=1}{}{}]>
org.springframework.batch.io.exception.BatchCriticalException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.tradeTasklet': 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.batch.execution.step.tasklet.TaskletStep.execute(TaskletStep.java:134)
at org.springframework.batch.execution.job.simple.SimpleJob.execute(SimpleJob.java:88)
at org.springframework.batch.execution.launch.SimpleJobLauncher$1.run(SimpleJobLauncher.java:85)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
at org.springframework.batch.execution.launch.SimpleJobLauncher.run(SimpleJobLauncher.java:80)
at foo.sample.TradeMatchBatchTests.testLaunchJob(TradeMatchBatchTests.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:198)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:274)
at org.springframework.test.context.junit4.SpringMethodRoadie$2.run(SpringMethodRoadie.java:207)
at org.springframework.test.context.junit4.SpringMethodRoadie.runBeforesThenTestThenAfters(SpringMethodRoadie.java:254)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:234)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:204)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:146)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:151)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.tradeTasklet': 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.getBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.getTarget(Cglib2AopProxy.java:662)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:612)
at foo.sample.TradeMatchTasklet$$EnhancerByCGLIB$$f5e84820.execute(<generated>)
at org.springframework.batch.execution.step.tasklet.TaskletStep$1.doInIteration(TaskletStep.java:124)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:324)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:201)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:131)
at org.springframework.batch.execution.step.tasklet.TaskletStep.execute(TaskletStep.java:122)
... 28 more
Caused by: java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.batch.execution.scope.StepScope.getContext(StepScope.java:127)
at org.springframework.batch.execution.scope.StepScope.get(StepScope.java:68)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:285)
... 38 more

 All   Comments   Work Log   Change History   FishEye   Builds      Sort Order: Ascending order - Click to sort in descending order
Adrian Shum added a comment - 22/Feb/08 03:59 AM
Contains sample unit test, dummy tasklet and app context config I used.

Adrian Shum added a comment - 22/Feb/08 04:00 AM
I forgot to mention, problem exists in trunk version, which I exported on Feb 21.

Douglas C. Kaminsky added a comment - 22/Feb/08 08:26 PM
Sorry this is isn't a patch, but this updated version of TaskletStep properly sets and closes the step scope context with the synchronization manager.

Douglas C. Kaminsky added a comment - 22/Feb/08 08:28 PM
As a side note, I did not implement any ItemStream registration in the attached file --- shouldn't the Tasklet step still register any member item streams even though they are not required? They would need to be accessed via reflection (or by changing the Tasklet contract to include a getter that returns all member item streams)

Lucas Ward added a comment - 23/Feb/08 11:50 AM
Doug, can you attach this as a patch? It makes it much easier to identifying the changes before applying, in case any change causes additional impacts.

Dave Syer added a comment - 25/Feb/08 06:49 AM
I'm not sure the TaskletStep should need to do anything with a StreamManager (and if it does that's another issue - this one is about step scope). Maybe a Tasklet could do that if it needed to?

Douglas C. Kaminsky added a comment - 25/Feb/08 01:00 PM
patch version attached - sorry ;)

Dave Syer added a comment - 26/Feb/08 01:57 AM
Sorry, Doug. Can you update your patch for the package refactoring that Lucas did at the weekend?

Dave Syer added a comment - 26/Feb/08 10:26 AM
Added step context to TaskletStep. Never mind about the patch.

Dave Syer added a comment - 07/Aug/08 10:06 AM
Assume closed as resolved and released