PDA

View Full Version : Scope 'step' is not active for the current thread



adrianshum
Feb 21st, 2008, 05:46 AM
Dear all,

Today I have checked-out and try the trunk version.
However when I run my own testing code snippet (by Junit testcase), it throws exception


org.springframework.batch.io.exception.BatchCritic alException: org.springframework.beans.factory.BeanCreationExce ption: 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


Similar code has been working when I am using 1.0m4

I just wonder if I did anything wrong.

I am using JUnit4 + related unit test utils in Spring 2.5; JDK 5

snippets of codes I am using:
Here is my app context (sample1-job.xml):


<!-- 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);
}
}


I should have correctly registered the StepScope by creating the corresponding bean in app context, and my tasklet's scope is set to "step", with <aop:scoped-proxy /> already.
Exception is thrown during jobLauncher.run(job,jobParam);


2008-02-21 19:26:01,645 INFO [org.springframework.batch.execution.launch.SimpleJ obLauncher] - <Job: [SimpleJob: [name=job]] failed with the following parameters: [{KEY=1}{}{}]>
org.springframework.batch.io.exception.BatchCritic alException: org.springframework.beans.factory.BeanCreationExce ption: 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.T askletStep.execute(TaskletStep.java:134)
at org.springframework.batch.execution.job.simple.Sim pleJob.execute(SimpleJob.java:88)
at org.springframework.batch.execution.launch.SimpleJ obLauncher$1.run(SimpleJobLauncher.java:85)
at org.springframework.core.task.SyncTaskExecutor.exe cute(SyncTaskExecutor.java:49)
at org.springframework.batch.execution.launch.SimpleJ obLauncher.run(SimpleJobLauncher.java:80)
at foo.sample.TradeMatchBatchTests.testLaunchJob(Trad eMatchBatchTests.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.test.context.junit4.SpringTest Method.invoke(SpringTestMethod.java:198)
at org.springframework.test.context.junit4.SpringMeth odRoadie.runTestMethod(SpringMethodRoadie.java:274 )
at org.springframework.test.context.junit4.SpringMeth odRoadie$2.run(SpringMethodRoadie.java:207)
at org.springframework.test.context.junit4.SpringMeth odRoadie.runBeforesThenTestThenAfters(SpringMethod Roadie.java:254)
at org.springframework.test.context.junit4.SpringMeth odRoadie.runWithRepetitions(SpringMethodRoadie.jav a:234)
at org.springframework.test.context.junit4.SpringMeth odRoadie.runTest(SpringMethodRoadie.java:204)
at org.springframework.test.context.junit4.SpringMeth odRoadie.run(SpringMethodRoadie.java:146)
at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.invokeTestMethod(SpringJUnit4ClassRu nner.java:151)
at org.junit.internal.runners.JUnit4ClassRunner.runMe thods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run (JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotec ted(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtecte d(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(J Unit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestR eference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecutio n.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.main(RemoteTestRunner.java:196)
Caused by: org.springframework.beans.factory.BeanCreationExce ption: 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.Abstract BeanFactory.getBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:170)
at org.springframework.aop.target.SimpleBeanTargetSou rce.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.Cglib2AopProxy$D ynamicAdvisedInterceptor.getTarget(Cglib2AopProxy. java:662)
at org.springframework.aop.framework.Cglib2AopProxy$D ynamicAdvisedInterceptor.intercept(Cglib2AopProxy. java:612)
at foo.sample.TradeMatchTasklet$$EnhancerByCGLIB$$f5e 84820.execute(<generated>)
at org.springframework.batch.execution.step.tasklet.T askletStep$1.doInIteration(TaskletStep.java:124)
at org.springframework.batch.repeat.support.RepeatTem plate.getNextResult(RepeatTemplate.java:324)
at org.springframework.batch.repeat.support.RepeatTem plate.executeInternal(RepeatTemplate.java:201)
at org.springframework.batch.repeat.support.RepeatTem plate.iterate(RepeatTemplate.java:131)
at org.springframework.batch.execution.step.tasklet.T askletStep.execute(TaskletStep.java:122)
... 28 more
Caused by: java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.batch.execution.scope.StepScop e.getContext(StepScope.java:127)
at org.springframework.batch.execution.scope.StepScop e.get(StepScope.java:68)
at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:285)
... 38 more



What may cause such problem?

unit tests in the sample project is running fine

Dave Syer
Feb 22nd, 2008, 01:58 AM
Looks like a bug in the TaskletStep to me - it isn't creating the step context. If you put it in JIRA you can track the progress.

dkaminsky
Feb 23rd, 2008, 10:42 AM
I've posted a fixed version of TaskletStep to the JIRA - hopefully this will make it into the M5 release.

kai_77
Mar 1st, 2010, 04:46 AM
Dear all,

Here is the error that I get:

org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'lazyBindingProxy.positionPagingItemReader': 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


This is the bean definition:

<bean id="positionPagingItemReader" scope="step"
class="ch.ofwi.matcher.services.business.tdmatcher.v1.imp l.jobs.matcher.MatcherRequestCompanyPagingReader">
<property name="sqlMapClient" ref="matcherMapClient" />
<property name="queryId" value="tdmatcher.getPagedMatcherCompany" />
<property name="pageSize" value="1000" />
<property name="matcherRequestKey" value="#{jobParameters[matcher.request.key]}" />
</bean>

Here is where the bean is referenced:

<batch:step id="matchRecords" >
<batch:tasklet allow-start-if-complete="true"
transaction-manager="matcherTransactionManager">
<batch:chunk reader="positionPagingItemReader"
processor="fuzzyProcessor" writer="matcherRequestPositionUpdater"
commit-interval="5"></batch:chunk>
<batch:listeners>
<batch:listener ref="matcherStepListener"/>
</batch:listeners>
</batch:tasklet>
</batch:step>

<batch:job id="csvWriterJob" >
<batch:step id="writeCSVFile">
<batch:tasklet allow-start-if-complete="true">
<batch:chunk reader="positionPagingItemReader"
writer="csvWriter" commit-interval="1000"/>
</batch:tasklet>
</batch:step>
<batch:listeners>
<batch:listener class="ch.ofwi.matcher.services.business.tdmatcher.v1.imp l.jobs.exportcsv.ExportCSVJobExecutionListener"/>
</batch:listeners>
</batch:job>

And here is the code of the bean with name 'positionPagingItemReader':


package ch.ofwi.matcher.services.business.tdmatcher.v1.imp l.jobs.matcher;

import java.util.HashMap;
import java.util.Map;

import jptools.logger.Logger;

import org.springframework.batch.item.database.IbatisPagi ngItemReader;

import ch.ofwi.matcher.dataaccess.dto.MatcherRequestCompa ny;


public class MatcherRequestCompanyPagingReader extends
IbatisPagingItemReader<MatcherRequestCompany>
{
private static final Logger log = Logger.getLogger(MatcherRequestCompanyPagingReader .class);


/**
* Sets the matcherRequestKey
* @param matcherRequestKey The matcherRequestKey to set
*/
public void setMatcherRequestKey(Long matcherRequestKey)
{
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("matcrequ_key", matcherRequestKey);
setParameterValues(parameters);
log.debug("Setting MatcherRequestKey=" + matcherRequestKey);
}
}



I use spring-2.5.6 with spring-batch-2.0.3 in a JDK6.

It all seems to work fine in my local environment, the error does only ocurr when I deploy the app to Geronimo AS.
What could be the problem here and how could it be solved?

Any help would be very much appreciated.

Thx

Kai

kai_77
Mar 3rd, 2010, 02:58 AM
Hi all,

the good news is that there is a workaround for this issue. Instead of scope="step" I instantiate the relevant beans in scope="prototype". The point is that the step parameters then cannot be set by late binding anymore. But the clue is to use the StepExecutionListener interface which has a call back method beforeStep(StepExecution). And the StepExecution object has access to the JobParameters.

Here is the change in the configuration:

<bean id="positionPagingItemReader" scope="prototype"
class="ch.ofwi.matcher.services.business.tdmatcher.v1.imp l.jobs.matcher.MatcherRequestCompanyPagingReader">
<property name="sqlMapClient" ref="matcherMapClient" />
<property name="queryId" value="tdmatcher.getPagedMatcherCompany" />
<property name="pageSize" value="1000" />
<!-- NO LATE BINDING <property name="matcherRequestKey" value="#{jobParameters[matcher.request.key]}" /> -->
</bean>

And here are the changes in the bean class:

public class MatcherRequestCompanyPagingReader extends
IbatisPagingItemReader<MatcherRequestCompany> implements StepExecutionListener
{
private static final Logger log = Logger.getLogger(MatcherRequestCompanyPagingReader .class);

// /**
// * OLD
// */
// public void setMatcherRequestKey(Long matcherRequestKey)
// {
// Map<String, Object> parameters = new HashMap<String, Object>();
// parameters.put("matcrequ_key", matcherRequestKey);
// setParameterValues(parameters);
// log.debug("Setting MatcherRequestKey=" + matcherRequestKey);
// }

/**
* NEW
*/
@Override
public void beforeStep(StepExecution stepexecution)
{
long matcherRequestKey = stepexecution.getJobParameters().getLong(JobParam. JOB_PARAM_MATCHEREQUEST_KEY);
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("matcrequ_key", matcherRequestKey);
setParameterValues(parameters);
log.debug("Setting MatcherRequestKey=" + matcherRequestKey);
}

/**
* @see org.springframework.batch.core.StepExecutionListen er#afterStep(org.springframework.batch.core.StepEx ecution)
*/
@Override
public ExitStatus afterStep(StepExecution stepexecution)
{
return null;
}
}

Have fun,

Kai