Hi,
Within a tasklet, I need to spawn off many threads. These threads need access to the context, specifically so I can do late binding on readers.
My readers are like so: (10 of these with slightly different tables they access)
My tasklet is like so:Code:<bean id="myReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" lazy-init="true" init-method="doOpen" scope="step" autowire="byName" > <property name="dataSource" ref="dataSource" /> <property name="sql"> <value> SELECT * FROM my_table WHERE column = '#{jobParameters[foobar]}' </value> </property> <property name="rowMapper"> <bean class="com.foo.bar.rowmapper" /> </property> </bean>
Code:<bean id="myTasklet" class="myTaskletClass" autowire="byName" scope="step" lazy-init="true"> <references to all of the readers I want to read> </bean>
What my tasklet is trying to do...
And within that thread I am trying to do...Code:for (ItemReader r : itemReaderList) { Thread t = new MyWOrkerThread( r ); t.start() }
IF I don't need the context, this works fine. I take the scope="step" off the reader, and each thread can do it's own reading.Code:while ( ( record = itemReader.read() ) != null ) { doWork( record ); }
IF I single thread this, I can use scope="step" on my reader, get the context, and it will work fine.
But if I want to combine both these concepts (scope = step so it replaces parameters, and multithreading) it blows up. The error I get ends up something like...
When I step in the code it is very obvious where it is breaking.. something alone the lines ofCode:MyTasklet$MyTHread - org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lazyBindingProxy.myReader1#sysinit': 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 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lazyBindingProxy.myReader1#sysinit': 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:312) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.batch.core.scope.util.PlaceholderTargetSource.getTarget(PlaceholderTargetSource.java:185) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:184) at $Proxy0.read(Unknown Source) at mycode..... at mycode.... 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:298) ... 7 more
is returning null. The question is, how do I get the thread that I create from within a tasklet to have access to the context?Code:StepContext context = StepSynchronizationManager.getContext();


Reply With Quote