Description of problem:

In testing, I realized that I had a globally scoped bean "partitionHandler" of type o.s.b.i.p.MessageChannelPartitionHandler that needed to be step scoped.

When I followed the examples of the other step scoped beans in the xml file, the job failed to load because no step scoped bean was active.

I can make my code as functional as it has been again by removing the scope="step" from the bean definition, but that is not a step forward and does not help me to understand the underlying issue to move forward.

Is there a functional example of making a MessageChannelPartitionHandler a step scoped bean in an xml context?

(Edit 2)

The root issue appears to be that the aggregator is defined as a global bean, but all of the beans it references (am-partitionHandler, am-replyChannel, and am-aggregatedReplyChannel) are step scoped beans.

<int:aggregator ref="am-partitionHandler"
                input-channel="am-replyChannel"
                output-channel="am-aggregatedReplyChannel"/>

(Edit )

In tracing the code:

  • ResourceXmlApplicationContext.preInstantiateSingletons() is looking for an o.s.i.c.AggregatorFactoryBean that is expected to be a singleton, then attempting to create it in the step scope as a ReleaseStrategyFactoryBean.
  • AbstractBeanFctory.doGetBean() is looking for a bean with the name "scopedTarget.partitionHandler" in the scope named "step", then throwing the exception.
  • StepScope.getContext() is not finding the stepScope in StepSynchronizationManager.getContext(), throwing the root exception

When chasing other links:

One of those I found is an almost identical symtom in a previous SE question of mine: Spring Batch - why is the job Step bean is being created/executed in the web context instead of the Job context? . The original link describes issues loading one of my application at job execution time, while this happens to a spring batch integration class during the initial XML context loading time (at application startup), well before the bean is actually executed.

XML snip:

<bean class="org.springframework.batch.core.scope.JobScope">
    <property name="proxyTargetClass" value="true" />
</bean>

<bean class="org.springframework.batch.core.scope.StepScope">
    <property name="proxyTargetClass" value="true" />
</bean>

<bean id="retryListItemWriterListener"
    name="retryListItemWriterListener"
    class="com.myApp.jobscope.RetryListItemWriterListener"
    scope="step" />  <!-- no problems with this and other step scoped beans -->

<int:channel id="aggregatedReplyChannel" scope="step">
    <int:queue/>
</int:channel>

<bean id="partitionHandler" 
    name="partitionHandler" 
    class="org.springframework.batch.integration.partition.MessageChannelPartitionHandler"
    scope="step"> <!-- step scope breaks this bean at initialization -->
    
    <property name="stepName" value="as-step0002.slave"/>
    <property name="gridSize" value="3"/>  
    <property name="replyChannel" ref="aggregatedReplyChannel"/>
    <property name="jobExplorer" ref="jobExplorer"/>
    <property name="releaseStrategy" ref="releaseStrategy" />
    
    <property name="messagingOperations">
        <bean class="org.springframework.integration.core.MessagingTemplate">
          <property name="defaultChannel" ref="requestsChannel"/>
          <property name="receiveTimeout" value="1000000"/>
        </bean>
    </property>
</bean>
        
<batch:job id="eventuallyconsistent-master">
    <batch:step id="am-step0002.master">
        <batch:partition partitioner="flatSourceDataPartitioner" handler="partitionHandler"/> 
        <batch:fail on="FAILED" />  
        <batch:next on="*" to="am-step9998" />
        <batch:listeners>
            <batch:listener ref="flatSourceDataPartitioner" />
            <batch:listener ref="ruleFactory" />
        </batch:listeners>      
    </batch:step>
</batch:job>

Log snip:

main 2023-06-29 10:48:54,050 INFO  o.s.a.f.CglibAopProxy - Unable to proxy interface-implementing method [public final void org.springframework.integration.context.IntegrationObjectSupport.afterPropertiesSet()] because it is marked as final: Consider using interface-based JDK proxies instead!
main 2023-06-29 10:48:54,051 INFO  o.s.a.f.CglibAopProxy - Unable to proxy interface-implementing method [public final void org.springframework.integration.context.IntegrationObjectSupport.setBeanName(java.lang.String)] because it is marked as final: Consider using interface-based JDK proxies instead!
main 2023-06-29 10:48:54,064 INFO  o.s.a.f.CglibAopProxy - Unable to proxy interface-implementing method [public final void org.springframework.integration.context.IntegrationObjectSupport.afterPropertiesSet()] because it is marked as final: Consider using interface-based JDK proxies instead!
main 2023-06-29 10:48:54,065 INFO  o.s.a.f.CglibAopProxy - Unable to proxy interface-implementing method [public final void org.springframework.integration.context.IntegrationObjectSupport.setBeanName(java.lang.String)] because it is marked as final: Consider using interface-based JDK proxies instead!

main 2023-06-28 17:08:01,054 ERROR c.m.m.AppInitializer - Failed to start bean 'automaticJobRegistrar'; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.AggregatorFactoryBean#0' defined in file [C:\myApp\jobrepository\eventuallyconsistent-master.xml]: Cannot create inner bean '(inner bean)#5791a9cb' of type [org.springframework.integration.config.ReleaseStrategyFactoryBean] while setting bean property 'releaseStrategy'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5791a9cb': Invocation of init method failed; nested exception is org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.partitionHandler': 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.context.ApplicationContextException: Failed to start bean 'automaticJobRegistrar'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.AggregatorFactoryBean#0' defined in file [C:\jobrepository\eventuallyconsistent-master.xml]: Cannot create inner bean '(inner bean)#5791a9cb' of type [org.springframework.integration.config.ReleaseStrategyFactoryBean] while setting bean property 'releaseStrategy'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5791a9cb': Invocation of init method failed; nested exception is org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.partitionHandler': 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.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.18.jar:5.3.18]
    at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.18.jar:5.3.18]
0

There are 0 best solutions below