Link to home
Start Free TrialLog in
Avatar of Jay Roy
Jay RoyFlag for United States of America

asked on

spring beans , avoid redundancy

hi guys

In my spring beans xml i have 3 queue beans defined like this

	<bean id="queue1" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName" value="INT.QUEUE1"/>			 
	</bean>

	<bean id="queue2" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName" value="INT.QUEUE2"/>			 
	</bean>

	<bean id="queue3" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName" value="INT.QUEUE3"/>			 
	</bean> 

Open in new window


These Queues are used by Listeners listening for messages

<bean id="listener1"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">		 
		<property name="destination" ref="queue1" />
		 
	</bean>


	<bean id="listener2"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">		 
		<property name="destination" ref="queue2" />
		 
	</bean>


	<bean id="listener3"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">		 
		<property name="destination" ref="queue3" />		 
	</bean> 

Open in new window

So tomorrow if i have to add another listener i have to add another bean (listener4).

Is there a better way to do this?
I want to avoid adding beans.

Thanks
Avatar of mccarl
mccarl
Flag of Australia image

One other different way (not necessarily better) is to do this... (note that this replaces BOTH of your code snippets from above)
	<bean id="destinationResolver" 
		class="org.springframework.jms.support.destination.JndiDestinationResolver">
		<property name="jndiTemplate" ref="jndiTemplate" />
	</bean>


	<bean id="abstractListener" abstract="true" 
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="destinationResolver" ref="destinationResolver" />
	</bean>


	<bean id="listener1" parent="abstractListener">		 
		<property name="destinationName" value="INT.QUEUE1" />
	</bean>


	<bean id="listener2" parent="abstractListener">		 
		<property name="destinationName" value="INT.QUEUE2" />
	</bean>


	<bean id="listener3" parent="abstractListener">		 
		<property name="destinationName" value="INT.QUEUE3" />
	</bean>

Open in new window

And then if you need to add listeners, you just need to duplicate 3 lines of code.

Otherwise, if the above is not what you are after you will need to explain more about what you want...
So tomorrow if i have to add another listener
If you add another listener, then you must need to do "something" to your application in order for it to know about it...
I want to avoid adding beans
Ok, so if you don't want to add beans, what other ways do you envisage your application "finding out" that you want to add a listener? Are you talking about wanting to configure it in a property file? Maybe configure it in a database somewhere? Or even, do you want it to automatically "see" that you have added a queue to the JMS server and start consuming from it?

(BTW, I am not advocating any of the above methods, I am just trying to extract out of you what it is you are truly looking for)
Avatar of Jay Roy

ASKER

>> Are you talking about wanting to configure it in a property file?
Yeah, that's the direction I was thinking about.

We have a project properties file, I was thinking to add a property like
Number_of_listeners= n

Thanks for your suggestions.
There is not going to be anything "built-in" (in either Spring or Java) to do this for you. So you will have to "roll your own" somewhat.

Just wondering though, are the queues that you are consuming from named exactly like that, and if say you had Number_of_listeners=20 then the queues would be named INT.QUEUE1 through to INT.QUEUE20 ?  Also, its not obvious from your initial xml configuration but do each of the listeners have a different "messageListener" set for them, or are they all processed by the same listener?

Also, if you can give me a bit more mackground on exactly what you are trying to do, I can possibly give you advice on whether this is really the best way to go about it, ie. there may be a more appropriate way to handle what you are doing, different even from what you gave in the original question?
Avatar of Jay Roy

ASKER

hi

>>There is not going to be anything "built-in" (in either Spring or Java) to do this for you. So you will have to "roll your own" somewhat.

yep, totally agree.

>>Just wondering though, are the queues that you are consuming from named exactly like that, and if say you had Number_of_listeners=20 then the queues would be named INT.QUEUE1 through to INT.QUEUE20 ?

Actually, no
The queue names are totally independent of each other and follow no sequence.


>>Also, its not obvious from your initial xml configuration but do each of the listeners have a different "messageListener" set for them, or are they all processed by the same listener?
They actuallly have their own messageListener
Overall it looks something like this:

 
<bean id="queue1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName" value="INT.QUEUE1"/>			 
	</bean>
	<bean id="queue2" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName" value="INT.QUEUE2"/>			 
	</bean>
	<bean id="queue3" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName" value="INT.COMXQ3"/>			 
	</bean> 
	
	
 
	<bean id="messagelistener1" class="com.comxcustom.CustomMessageListener1">		 
	<property name="queueName" value="INT.QUEUE1" />
	</bean>	
	<bean id="messagelistener2" class="com.custom.CustomMessageListener2">		 
	<property name="queueName" value="INT.QUEUE2" />
	</bean>	
	<bean id="messagelistener3" class="com.custom.CustomMessageListener3">		 
	<property name="queueName" value="INT.COMXQ3" />
	</bean>

	<!-- DefaultMessageListenerContainer definitions -->

	
<bean id="listener1"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">		 
		<property name="destination" ref="queue1" />
		 <property name="connectionFactory" ref="cachedConnectionFactory" />
		<property name="messageListener" ref="messagelistener1" />
		<property name="destination" ref="queue1" />
		<property name="concurrentConsumers" value="5" />
		<property name="maxConcurrentConsumers" value="15" />
	</bean>
	<bean id="listener2"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">		 
		<property name="destination" ref="queue2" />
		 <property name="connectionFactory" ref="cachedConnectionFactory" />
		<property name="messageListener" ref="messagelistener2" />
		<property name="destination" ref="queue2" />
		<property name="concurrentConsumers" value="5" />
		<property name="maxConcurrentConsumers" value="15" />
	</bean>	
	<bean id="listener3"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">		 
		<property name="destination" ref="queue3" />
		 <property name="connectionFactory" ref="cachedConnectionFactory" />
		<property name="messageListener" ref="messagelistener3" />
		<property name="destination" ref="queue3" />
		<property name="concurrentConsumers" value="5" />
		<property name="maxConcurrentConsumers" value="15" />
	</bean>

Open in new window

     

CustomMessageListener1,CustomMessageListener2,CustomMessageListener3 all impliment javax.jms.MessageListener and override the public void onMessage(Message message) method.
      
I feel there is a lot of redundancy (copy-pasting) going and the coding logic can be made more simpler and elegant.
      
Your thoughts will be appreciated?
      
Thanks.
Actually, no
The queue names are totally independent of each other and follow no sequence
Well then just a simple "Number_of_listeners=n" type of property is obviously not going to work. If that is all the configuration that you have, how is your code supposed to know what the queues are called? And I guess the same for the MessageListener classes?

So I think that cleaning up the xml using Spring's "abstract" bean and the JndiDestinationResolver as I showed above it the best that you will get. You can also move the definitions of those message listeners to be "inline" with the DefaultMessageListenerContainer definitions too which should help.
I was also going to add.... For all the benefits that Spring gives you, yes I have also found that the Ctrl+C Ctrl+V gets a bit more of a workout when build my .xml config files. It's just one of those things! :)
SOLUTION
Avatar of Murali Murugesan
Murali Murugesan
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Jay Roy

ASKER

Thanks
On a high level I want to be able to define number of listeners in a property file.
Based on that number I would spawn up that many DefaultMessageListererContainer beans
on the fly.
To start working on such a requirment i would like to know if I can create beans in the jvm at runtime.
I believe StaticApplicationContext would be suitable for this.

Refer: http://java.dzone.com/articles/spring-static-application
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Jay Roy

ASKER

Thanks , very good ideas. Was able to impliment Mccarl's sugession.
Not a problem, glad to help! :)