0

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]
pojo-guy
  • 966
  • 1
  • 12
  • 39
  • A step-scoped bean should be initialized only at runtime when the step is active. Now if the partition handler bean is declared as a step-scoped bean but is still loaded at application startup, then there is a bean lifecycle issue. To help you efficiently, please gather those snippets in a github repo or a zip that shows the issue and I will try to help. – Mahmoud Ben Hassine Jul 04 '23 at 07:41
  • Thank you Mahmoud. This much helped enormously. There is definitely a bean lifecycle issue. I'll see what I can pull together. I think where I am having a conceptual issue is the boundary between the JMS and spring batch. There is a change in scope between the shared external AMQ system (global) and the step scoped handling of JMS messages. – pojo-guy Jul 05 '23 at 14:30
  • @MahmoudBenHassine Thanks to your pointer, I see that the bean declared in XML is global but all of the beans it references are step scoped. I'm checking out the correct pattern for defining a step scoped aggregator bean. – pojo-guy Jul 05 '23 at 15:52
  • Thee root cause is that there is a mix of java DSL configurations and XML configurations. The @Configuration class QueueingConfig executes in the web application scope, so singletons were not being created in the correct scope. Defining the beans defined in this scope with the singleton scope, then revisiting all of the wired beans to ensure they were defined to the correct scope appears to have corrected the issue. The spring integration components don't take a "scope" property in the XML, so I needed to refactor those using instead if – pojo-guy Jul 05 '23 at 17:49
  • 1
    `Defining the beans defined in this scope with the singleton scope, then revisiting all of the wired beans to ensure they were defined to the correct scope appears to have corrected the issue`. Glad to hear that! Always happy to help. – Mahmoud Ben Hassine Jul 06 '23 at 07:38

0 Answers0