Spring JMS messaging with JmsListener - how it scales? - spring

I'm trying to use Spring JMS messaging with #JmsListener in a scalable way, but I'm not seeing it happening. I have a ConnectionFactory bean that returns a factory that connects to an Oracle Advanced Queue through JMS and a database DataSource pool.
The problem starts as every #JmsListener receiver connects again to JMS (and hence to the database pool). My understand is that I can have many #JmsListener methods, one for each service, but in this way it's doing I'm very limited.
The shared connection is turned on, but since each #JmsListener creates a different DefaultMessageListenerContainer, each one have a database connection.
If I also want the services to handle messages concurrently and set container.setConcurrency("3-5"), then it opens 3 * numberOfListeners connections.
If I use container.setCacheLevel(DefaultMessageListenerContainer.CACHE_NONE) then from each second every listener container connects and disconnects from the JMS/database.
I want something that connects one time (or more, if there is concurrent jobs to process) to JMS/database, not to connect count-of-listener times nor to connect-disconnect at each second for every listener.

You can use a SingleConnectionFactory to wrap the vendor factory and all containers will use the same connection.

Related

Using multiple MQ servers in Java Spring Boot

I have a Java Spring Boot application, and I need to send messages over IBM MQ and then listen for a response on a corresponding queue. I have a primary and (possibly multiple) fail-over MQ hosts. The queue names are different on each host (I have no control over this) so I need to have a different connection factory for each host.
I've looked at the mq-jms-spring code, and think I can adapt this to my needs. However, our current code, which works a comma separated list of hosts (and was written by someone else), creates both a connection factory and a transaction manager using that connection factory. It can use multiple hosts, but since the queue names are different for each host the fail-overs, well, fail. I'm assuming I need to create multiple transaction managers if I have multiple connection factories.
My questions are:
Do I need a transaction manager in this case?
If yes, then do I need a 1-1 relationship of connection factory to transaction manager?
If yes, how do I use the multiple transaction managers? I use the connection factory to write to the queue, but how do I notify spring which transaction factory to use? Does Spring automatically know this or is there some way I need to configure this?

How do I distribute JMS Listener Connections to ActiveMQ Network of Brokers using Spring Boot JMS?

Our JMS Listener application connects to an ActiveMQ network of brokers through a load balancer, which we are told distributes connections amongst brokers in a round-robin fashion. Our spring boot application is creating a connection via the load balancer, which in turn feeds the connection to one of the brokers amongst the network of brokers. If a message is published to the brokers then it would be a lot quicker if the message was on the broker that the JMS listener connection lived on. However, the likelihood of that occurring is slim unless we can distribute the connections across the brokers.
I've tried increasing the concurrency in the DefaultJmsListenerContainerFactory, but that didn't do the trick. I was thinking about somehow extending the AbstractJmsListenerContainerFactory, and somehow create a Map of DefaultMessageListenerContainer instances but it looks like the createListenerContainer will only return an instance of whatever is parameterized in the AbstractJmsListenerContainerFactory and we cannot parameterize it with an instance of Map.
We are using Spring Boot 1.5.14.RELEASE.
== UPDATE ==
I've been playing around with the classes above, and it seems like it is inherent in Spring JMS that a Jms Listener be associated with a Single Message Listener Container, which in turn is associated with a single (potentially shared) connection.
For any folks that have JMS Application Listeners that are connecting to a load balanced network of brokers, are you creating a single connection that is connecting to a single broker, and if so, do you experience significant performance degradation as a result of the network of brokers having to move any inbound messages to a broker with consumers?

JMS - One ConnectionFactory per Queue or one ConnectionFactory for all of the queues

I am using WebSphere with ActiveMQ and ActiveMQ's JCA adapter. In our application, there are a lot of queues for different functionalities. So can you tell me, should I create one ConnectionFactory for each queue(functionality) or only one ConnectionFactory for the whole application and shared for the queues ? And the reason.
Thanks in advance.
Really depends what are your requirements. It is not specific to ActiveMQ, but queuing in general. You usually may create separate connection factories when you have:
different host/port for different queues
different security credentials to connect
want to have different connection pools
So for example, if you want to ensure that at least n connections are available for certain queues you can create separate connection factory for that. As with one connection factory, in some extreme cases, when most of your application load is - let say - on functionalityA queues, then you may not have enough connections for your functionalityB queues and that functionality may suffer starving.

More than one JMS ConnectionFactory

I am new to JMS and currently developing a simple Chat application explained in Oreilly 'Java Message service'. I've configured a TopicConnectionFactory in ActiveMQ that receives chat messages from TopicPublishers and dispatch that to TopicSubscribers.
My question is 'why do we need to create more than one TopicConnectionFactory' in any JMS application? Since Connectionfactory instances are not tied up with a Topic/Queue, why can't we use one instance of ConnectionFactory for creating connections to all the Topics (or Queues) configured in an application?
Technically speaking you are right. You may be able just to use one ConnectionFactory.
However it is a better design to use multiple ConnectionFactories depending on your requirements so the traffic would be spread out evenly and you do not run out of connections.
So if you know about a JMS Client application that may be problematic (the logic does not allow proper connection handling open/close), you may isolate it to use its own connection factory.
Also some connection factories allow a pool of 10 default active connections at the same time (it depends on the implementation/ settings) if you will need more you may use more than one connection factory.
I've configured a TopicConnectionFactory in ActiveMQ that receives chat messages from TopicPublishers and dispatch that to TopicSubscribers.
Very ambiguous statement. TopicConnectionFactory does not receive or send any messages. It is just one of the admin Objects used to create Connection which in turn creates Session which in turn creates your publishers and subscribers which publish and subscribe the messages.
why can't we use one instance of ConnectionFactory for creating connections to all the Topics (or Queues) configured in an application?
You definitely can. There is no one stopping you from doing that.
As per specs
A connection factory object encapsulates a set of connection configuration
parameters that has been defined by an administrator. A client uses it to
create a connection with a JMS provider.
So unless you have different configuration requirements you can use same ConnectionFactory to create multiple Connections. And yes as otc has mentioned above number of connections is one of the configuration parameter.

Spring JMS: Creating multiple connection to a queue

To process a large number of messages coming to a queue i need guarantee of at least one jms connection to be there at any time. I am using spring and spring allows to have multiple sessions on a single connection only. In case one and only connection fails, application will come to standstill till spring reconnects to the JMS bridge.
So how can i create more than one connection to a queue in Spring, also how can i do connection pooling here.
The answer to this depends on whether you are using Spring inside a J2EE container(jboss etc.) or in a standalone application.
Standalone - you'll find pooling connections to be a problem. Springs SingleConnectionFactory can be setup to renew the connection on an exception garaunteeing that at some point a connection will come online and start processing the queue again, but you'll still have the problem of waiting for that single connection to renew, plus depending on what messaging implementation your dealing with and how it does load balancing you may find yourself stuck with a connection to a single node in a cluster.
If you are running in a container you can rely on the containers connection factory which will be much more robust. JBoss Messaging in the container for instance will failover seamlessly to other nodes and handles pooling under the covers, but if your working in the container its usually easier to bail on JMS template which kind of sucks and use whatever that container provides.

Resources