How to configure concurrency to a single queue - java

I would like to configure number of consumers for a single queue in jms template. I tried to implement this: JmsTemplate - define concurrency per queue? but in the ActiveMQQueue is stiil shows 1.
my messanging context:
<bean id="parentContainer" abstract="true"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<bean id="parentContainer" abstract="true"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<bean id="playerStatsListener" parent="parentContainer">
<property name="destination" ref="playerStatsQueue" />
<property name="messageListener" ref="playerStatsService" />
<property name="concurrency" value="100" />
</bean>
<!-- Listeners -->
<bean id="playerStatsService" class="com.XXX.service.PlayerStatsService" />
<!-- Destinations -->
<bean id="playerStatsQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="playerStatsQueue" />
another related question: Is there a difference between the "listener" to "messageListener" property?

In general, you can set concurrentConsumers and maxConcurrentConsumers on the DefaultMessageListenerContainer. The concurrency setting gives this as a convenient range.
But according to the docs
Specify concurrency limits via a "lower-upper" String, e.g. "5-10", or
a simple upper limit String, e.g. "10" (the lower limit will be 1 in
this case).
So if you just say concurrency=100, it's still equivalent to 1-100, which would explain why you're seeing 1 consumer.

Related

ActiveMQ: How to prevent message from going to "Dispatched Queue"

I'm using ActiveMQ with the spring framework.
I have two consumers setup in the jms container. When I send 4 message to the queue, and some of the message are transferred to the "Dispatched Queue", because it takes a long time to the consumer to process the message.
I'm trying to find the way to prevent the message from going to the "Dispatched Queue", that is, I want them to be available to any consumer that is ready to consume the message.
I tried to set pre-fetch to 0, but it doesn't seem to work at all.
<bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
<property name="queuePrefetch" value="0"/>
</bean>
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="tcp://localhost:61616" />
<property name="prefetchPolicy" ref="prefetchPolicy"/>
</bean>
The following is the setup for my jms container:
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="defaultDestination" />
<property name="messageListener" ref="messageListener" />
<property name="concurrentConsumers" value="2" />
</bean>
I found the problem. I had the same beans declared twice at two different places. The second bean that was loaded did not have pre-fetch set to 0 and therefore it didn't work out.
The above setup I posted works!
Thank you!

Spring config properties from database and properties

I asked a similar question, but based on the responses, I did a bad job describing what I am after. I have a spring 4 webapp that loads properties from a properties file. We consume those properties both via the "${proper.name"} expressions in spring, as well as by injecting a properties object into some of our classes.
We want to move most of the properties to a database table and make them reloadable. However, a few need to stay in local properties, potentially overriding the database setting. These should also be loaded dynamically after the app is running.
I know that once a particular bean is injected, it won't get reloaded, that doesn't concern me, it's up to that module to handle that. But I am having trouble getting the behavior I want. In particular, I have implemented an AbstractConfiguration from apache commons configuration to get the dual source and overriding I am after. But while it works for injecting the properties object, expressions loaded with "${prop.name}" don't work at all.
How can I get them to work? Did I override the wrong thing? Is it just some config detail?
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean id="dbConfigFactory" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg ref="databaseConfigurator" />
</bean>
I haven't tested this, but I think it might work.
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="CommonsConfigurationFactoryBean"/>
</bean>
<bean name="CommonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfigurator"/>
</bean>

Producer and Consumer in Spring Jms use same connection factory?

I have a component which reads messages from a queue and meanwhile sends the processed messages to another queue. Therefore, this component is both a message consumer and producer. For configuring them, I need a connection factory for consuming and another connection factory for the producing. Here is part of the spring configuration.
<!-- Configuration for listener -->
<bean id="mdc.TargetConnectionFactory4Listener" class="com.tibco.tibjms.TibjmsConnectionFactory">
<property name="serverUrl" value="tcp://localhost:7222"/>
</bean>
<bean id="mdc.ConnectionFactory4Listener" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="mdc.TargetConnectionFactory"/>
<property name="username" value="admin" />
<property name="password" value="test" />
</bean>
<bean id="mdc.InputQueue" class="com.tibco.tibjms.TibjmsQueue">
<constructor-arg>
<value>INPUT_QUEUE</value>
</constructor-arg>
</bean>
<bean id="mdc.JmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="mdc.ConnectionFactory4Listener" />
<property name="destination" ref="mdc.InputQueue" />
<property name="messageListener" ref="mdc.MessageReceiver" />
......
</bean>
<!-- Configuration for sender -->
<bean id="mdc.TargetConnectionFactory4Sender" class="com.tibco.tibjms.TibjmsQueue">
<property name="serverUrl" value="tcp://localhost:7222"/>
</bean>
<bean id="mdc.CachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="mdc.TargetConnectionFactory4Sender" />
<property name="sessionCacheSize" value="50" />
</bean>
<bean id="mdc.OutputQueue" class="com.tibco.tibjms.TibjmsQueue">
<constructor-arg>
<value>DISCOVERY_QUEUE</value>
</constructor-arg>
</bean>
<bean id="mdc.JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="mdc.CachingConnectionFactory" />
</bean>
<bean id="mdc.MessageReceiver" class="net.siemens.discovery.queue.QueueMessageListener">
<property name="jmsTemplate" ref="mdc.JmsTemplate" />
<property name="destination" ref="mdc.OutputQueue" />
......
</bean>
The two queues are running on the same EMS server. Some has opinions about this configurations: they can be configured by using only one ConnectionFactory and two instances are not necessary. However, if I use one ConnectionFactory instance, then the instance is used both in the DefaultMessageListenerContainer and the CachingConnectionFactory (further used in JmsTemplate). I don't know whether they have impact on each other.
It is perfectly normal to use a single connection factory; it is very unusual to use 2 factories in this case.
In fact, if you want to perform JmsTemplate operations on the container thread and you want the interactions to run in a transaction (sessionTransacted = true in the container), then you must use the same connection factory. This allows everything to roll back if there's an exception.
When using a caching connection factory in the listener container you should set the connection factory cacheConsumers to false. (See this answer for more information.

JmsTemplate - define concurrency per queue?

So far i've only been able to find concurrency setting in the jms connection factory:
<jms:listener-container connection-factory="myConnectionFactory"
task-executor="myTaskExecutor"
destination-resolver="myDestinationResolver"
transaction-manager="myTransactionManager"
concurrency="10">
Is it possible to configure the number of consumers for a single queue? i.e something like:
<jms:listener destination="playerStatsQueue" ref="playerStatsService"
method="onMessage" concurrency="100" />
Thanks!~
Do not use the namespace but an abstract parent DefaultMessageListenerContainer and create one child instance per listener. That way you can tweak all the properties you need.
<bean id="parentContainer" abstract="true"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="messageListener" ref="messageListener"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="playerStatsListener parent="parentContainer">
<property name="destination" ref="playerStatsQueue"/>
<property name="listener" ref="playerStatsService"/>
<property name="concurrency" value="100"/>
</bean>

How to execute method using spring beans

I need findItemByPIdEndDate() method of the MngtImpl class to be invoked every 5000ms, but nothing appears to be happening. Am I missing something?
<bean id="findItemByPIdEndDate" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="MngtImpl"/>
<property name="targetMethod" value="findItemByPIdEndDate"/>
<property name="repeatInterval" value="50000"/>
</bean>
#matt b I've read some of this, everything is new to me here ..so I came with this .. and again its not working, what am I missing this time ?
<bean id="findItemByPIdEndDate" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="MngtImpl" />
<property name="targetMethod" value="findItemByPIdEndDate" />
</bean>
<bean id="compareDateTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="findItemByPIdEndDate" />
<property name="startDelay" value="0" />
<property name="repeatInterval" value="50000" />
</bean>
For this task, the Chapter 23. Scheduling and Thread Pooling is your friend. That said, here is a short summary.
First, define your Job:
<bean id="findItemByPIdEndDate" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="MngtImpl"/>
<property name="targetMethod" value="findItemByPIdEndDate"/>
</bean>
Now, you need to schedule the job using a trigger and a SchedulerFactoryBean. For the trigger, I suggest to use a SimpleTriggerBean in your case:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!-- see the example of method invoking job above -->
<property name="jobDetail" ref="findItemByPIdEndDate" />
<!-- 10 seconds -->
<property name="startDelay" value="10000" />
<!-- repeat every 50 seconds -->
<property name="repeatInterval" value="50000" />
</bean>
To finalize everything, set up the SchedulerFactoryBean:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
You need a lot more plumbing than that to make Quartz work. Just declaring the MethodInvokingJobDetailFactoryBean on its own will do nothing.
However, Quartz is overkill for this, Java5+ can do this on its own. I suggest reading up on Spring's ScheduledExecutorFactoryBean, which in combination with MethodInvokingRunnable, allows you to invoke your method periodically.
What you've done so far is the equivalent of only instantiating a MethodInvokingJobDetailFactoryBean() - essentially all you've done is created the Job. Now you need to have some configuration for how it's scheduled, and what triggers it.
Take a look at the section in the Spring manual on Quartz.

Categories

Resources