I am using Spring Framework to concurrently consume messages off of a JMS queue using a DefaultMessageListenerContainer. I want the ability to create new instances of the beans that are autowired for each message that comes in. I thought setting the scope="prototype" would work but it doesn't seem to do the job. Does anybody know of a custom bean scope that would create new instances per JMS message? Much like the "request" scope does for HTTP Requests?
I realize that I could make com.sample.TestListener "BeanFactoryAware" and then just do a getBean("foo") in my onMessage but I wanted to avoid putting the Spring dependency into my code.
Thanks in advance for any help!
Example below, I want a new instances of "com.sample.Foo" and all beans injected into it each time a message comes in.
<bean id="consumer"
class="com.sample.TestListener">
<constructor-arg ref="foo" />
</bean>
<!--Configures the Spring Message Listen Container. Points to the Connection
Factory, Destination, and Consumer -->
<bean id="MessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="CachedConnectionFactory" />
<property name="destination" ref="Topic" />
<property name="messageListener" ref="consumer" />
<property name="concurrency" value="10"/>
</bean>
<bean id="foo" class="com.sample.Foo">
<property name="x" ref="xx" />
<property name="y" ref="yy" />
<property name="z" ref="zz" />
</bean>
Use SimpleThreadScope implementation which come with Spring
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/context/support/SimpleThreadScope.html
It's pretty easy to write a custom scope to do this...
and a sample context...
Note: with this simple scope, you have to put all the referenced beans in the scope as well (bar and baz above). You can make all the referenced beans inherit the scope, but it takes some work. That said - there's an example of how to do it in spring-batch's StepScope.
Note#2 this will get a new instance for every method call. If you call multiple methods you'll get a new bean for each call. If you want to scope it to allow all calls within onMessage to use the same instance, you'll need to add some more tricks.
EDIT: Here are some updates to support multiple calls to an instance within the onMessage()...
Now, you do have to clear the cache...
But even that could be done in an AOP @After advice, to keep the listener totally clean.