I have a small Ballerina program where I receive a message from one JMS queue, call a stored procedure via JDBC and send a reply to another JMS queue.
The DB can process multiple requests in parallel, so I set up a JDBC connection pool for it. How do I set up a similar JMS connection pool?
Or should I just have a pool of Ballerina services instead?
The current ballerina implementation does not support any pooling of JMS resources.
The model of ballerina, however, should allow parallel processing, without explicit coding.
Using the code from the following GIST jmsreceiver.bal the processing was done in parallel.
It produced the following log:
Initiating service(s) in 'receiver.bal'
2018-12-08 18:38:38,963 INFO [ballerina/jms] - Message receiver created for queue MyQueue
2018-12-08 18:38:57,445 INFO [] - rcv ID:EMS-SERVER.55865C0BF16270:1500
2018-12-08 18:38:58,461 INFO [] - snd ID:EMS-SERVER.55865C0BF16270:1500
2018-12-08 18:38:58,466 INFO [] - rcv ID:EMS-SERVER.55865C0BF16270:1501
2018-12-08 18:38:58,474 INFO [] - rcv ID:EMS-SERVER.55865C0BF16271:1502
2018-12-08 18:38:59,469 INFO [] - snd ID:EMS-SERVER.55865C0BF16270:1501
2018-12-08 18:38:59,472 INFO [] - rcv ID:EMS-SERVER.55865C0BF16270:1503
2018-12-08 18:38:59,478 INFO [] - snd ID:EMS-SERVER.55865C0BF16271:1502
I'm not really familiar with Ballerina, but reading through the Ballerina JMS tutorial it appears Ballerina can use Java libraries. If that is the case, then you should check out https://github.com/messaginghub/pooled-jms. It was forked from the mature ActiveMQ JMS Pool and enhanced to provide JMS 2.0 functionality. It is built on top of Apache Commons Pool, and it is generic (i.e. no ties to ActiveMQ) so it will work with any JMS implementation you choose.
Here's a simple example of how to use it. You just need to instantiate a JmsPoolConnectionFactory and then call setConnectionFactory with the connection factory you would normall get from JNDI. After that you just use it like any normal JMS connection factory.
Related
We have been doing performance testing of an application that uses IBM MQ. Through JMeter we are injecting the payload via a JMS Publisher. However, when running the test it can be observed that the connections from the JMeter threads are not being released. This effects the ability to reach the throughput and test failure due to the accumulation of threads. Is there a better alternative than using the JMS Publisher? Or is there setting there that needs to be enabled in order to release the connection once the request has been sent?
https://www.blazemeter.com/blog/ibm-mq-tutorial - Is this the best practice to implement testing IBM MQ?
What are you trying to achieve? JMeter implements Object Pool Pattern so each JMeter thread (virtual user) creates its own JMS connection and on subsequent iterations of the JMS Publisher sampler the Publisher object is being returned from the pool rather than created from zero.
If this is not something you want (or not how your JMS application acts) and you would like to close the connection after posting a message to queue/topic you can achieve it quite easily using JSR223 PostProcessor and the following Groovy code:
def publisher = sampler.publisher
org.apache.jmeter.protocol.jms.client.ClientPool.removeClient(publisher)
org.apache.commons.io.IOUtils.closeQuietly(publisher, null)
sampler.publisher = null
I am using Spring Boot 2.2.1 (w/ Spring 5) to kick off my server with Spring JmsTemplate (HornetQ) connections. Every ~10s an ERROR is logged,
2020-01-17 18:00:49,091 [DefaultMessageListenerContainer-1] ERROR listener.DefaultMessageListenerContainer - Could not refresh JMS Connection for destination 'a.Topic' - retrying using FixedBackOff{interval=5000, currentAttempts=2, maxAttempts=unlimited}. Cause: clientID=myapp.Topic was already set into another connection
Did I accidentally create another client using the same id and compete for the connection/topic? Or something else I am not aware of.
Did I accidentally create another client using the same id and compete for the connection/topic?
Yes. According to the error message you're receiving you did.
I am new to JMS. I am trying to understand what is difference between JCA JMS (Java Connector Architecture) and Plain JMS. I tried finding it through the web, but I didn't find anything satisfactory. Can we write a code using JCA JMS which is supported for both WebLogic and JBoss?
From an API perspective there is no difference between "JCA JMS" and "Plain JMS". The difference is in how they behave. A JCA-based JMS connection factory has 2 big advantages over a plain JMS connection factory:
Pooled - Generally speaking, when a connection is "created" from a JCA-based JMS connection factory the underlying physical connection is taken out of a pool and when the connection is "closed" the underlying physical connection is returned to the pool. This eliminates the performance penalty of actually creating and destroying the physical connection which allows clients to be written in ways that would normally be considered an anti-pattern (e.g. "creating" and "closing" a connection for every sent message).
Automatic enlistment into JTA transactions - Most of the time applications running in a Java EE application server which consume JMS messages do so via an MDB. By default, the consumption of the message in an MDB (i.e. the execution of onMessage) happen within a JTA transaction. If a JCA-based JMS connection factory is used in the course of the MDB's processing (e.g. to send a message) then the JCA logic will automatically enlist the session into the JTA transaction so that the consumption of the message and the sending of the message are an atomic operation (assuming that the JCA-based connection factory is XA capable).
I would expect that you could write application code that would behave the same in both WebLogic and JBoss AS.
We have a spring boot application using spring-kafka (2.2.5.RELEASE) that always gets this error when starting up:
Could not configure topics
org.springframework.kafka.KafkaException: Timed out waiting to get existing
topics; nested exception is java.util.concurrent.TimeoutException
However, the application continues to startup:
org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1]
INFO o.s.k.l.KafkaMessageListenerContainer - partitions revoked: []
INFO o.s.k.l.KafkaMessageListenerContainer - partitions assigned: [my-reply-topic-1]
INFO o.s.k.l.KafkaMessageListenerContainer - partitions assigned: [my-request-topic-0]
INFO o.s.b.w.e.tomcat.TomcatWebServer -
Tomcat started on port(s): 8080 (http) with context path ''
At this point, the application interacts with Kafka as expected.
We like to keep our logs clean, so we would like to understand why this Exception is thrown. Also, it is a bit confusing, because when we move to a different environment where the networking has not been established between the application and the kafka broker(s), we get the same error, but the application does not function. Having the same Exception occur when there is truly a problem and when it can be ignored is irksome when trying to troubleshoot connectivity issues.
Is there a way, on application startup, to determine whether connectivity has been established with Kafka rather than just waiting for a timeout message (which may be a red herring anyway)?
If the topic(s) exist already, remove any NewTopic beans from the application context and the KafkaAdmin won't try to connect to the broker at all.
I've done some tests with ActiveMQ and Spring JMS. I've configured DefaultMessageListenerContainer (DMLC) with WorkManagerTaskExecutor and CommonJ to manage the threads. I want to have control over the threads are running in the server.
I have made the decision of using DMLC based on a post written by Juergen Holler in Spring's forum: http://forum.spring.io/forum/other-spring-related/remoting/24208-what-s-the-best-practice-for-using-jms-in-spring?p=256420#post256420
In this post, he says "DMLC is the only listener container that does not impose the thread management onto the JMS provider, that is, does not use/block JMS provider threads." So I thought that all the threads would be managed by the server and there wouldn't be threads of ActiveMQ.
However, analysing the server's threads using JConsole, I've seen some threads of ActiveMQ that I didn't expect.
As you can see in the image, there are ActimeMQ threads (inactivity threads, transport threads, etc).
When I'm executing the tests, I see in the logs that the JMS messages are processed by CommonJ threads and not by ActiveMQ threads, so that's fine. However, I don't understand why are ActiveMQ threads are created if they are not used. Specially "ActiveMQ Transport" threads because for every queue I use I've got one thread "ActiveMQ Transport". Therefore if I'm consuming 50 queues, I've got 50 threads of "ActiveMQ Transport". Is it to keep the socket opened? Are these threads mandatory?
Details about the configuration:
ConnectionFactory used: org.apache.activemq.ActiveMQConnectionFactory
ActiveMQ version: 5.11.1
Transport protocol: TCP
Using DefaultMessageListenerContainer the client is in a loop invoking MessageConsumer.receive() method.
It seems a silly question and surely I've misunderstood some basic concepts.
Thanks to Rob Davies' explanation in this thread http://activemq.2283324.n4.nabble.com/ActimeMQ-Client-s-thread-management-td4705885.html, I've understood that all the interaction with ActiveMQ require a TCP thread per connection.
However, the amount of transport threads can be minimised replacing ActiveMQConnectionFactory with one of these ConnectionFactories:
PooledConnectionFactory (ActiveMQ)
SingleConnectionFactory (spring-jms)
CachingConnectionFactory (spring-jms)