With rabbitmq client i can make it work with following bean inject well i heard CachingConnectionFactory has another constructor to apply a com.rabbitmq.client.ConnectionFactory, which will help to enable auto recovery, but it has limited attributes to go with it.
<bean id="rcf" class="com.rabbitmq.client.ConnectionFactory">
<property name="requestedHeartbeat" value="580" />
<property name="topologyRecoveryEnabled" value="true" />
<property name="automaticRecoveryEnabled" value="true" />
</bean>
But when it comes to spring amqp for rabbit , i found no options to do that.
I appreciate , Any help regarding the query i raised ..
This is really interesting and one of the important communication problem that we need solve when we are going to work under single Message Bus Architecture. Since, we are planning to abstracted out the internal details of Message Bus, it is necessary to provide what type of attributes that we need to enable in consumer as well as producer end.
This is my consumer.xml
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.host}" virtual-host="${rabbitmq.vhost}" username="${rabbitmq.user}" password="${rabbitmq.password}" />
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue id="mQueue" name="${rabbitmq.queue.m}" />
<rabbit:queue id="mrQueue" name="${rabbitmq.queue.mr}" />
Can you explain how to set auto recovery in this xml? Please add xml which will set auto recovery with above consumer xml
Spring AMQP has (and has always had) it's own connection recovery mechanism. The rabbit client added it much later and it's mechanism is incompatible with Spring AMQP. Setting automaticRecoveryEnabled will cause problems with Spring AMQP versions prior to 1.4.0.
1.4.0 and later are compatible with the rabbitmq settings, but still uses its own recovery mechanism.
You can change the recoveryInterval on the message listener container (default 5 seconds).
Related
I have a client app that is consuming from a queue in an activemq cluster. The app is running in tomcat 7 and uses camel (v2.10.3) and spring 3.1.2. I use a PooledConnectionFactory to connect.
Everything works for a while (sometimes days), but then all of the connections go away in the pool (the activemq broker web console shows no consumers. I figured it was the idletimeout issue, but adding the suggested config didn't help. I also upgraded to activemq-pool-5.10.0.jar, but also no luck.
SO, I'm trying to find out what is going on and was hoping to use JMX, but I can not find any related mbeans (via jconsole) that the pool registers. Is there a way to monitor/control the pool via JMX (or another/better way)?
My config fyi:
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMWSslConnectionFactory">
<property name="brokerURL" value="failover://ssl://...."/>
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="idleTimeout" value="0"/>
</bean>
As simple as it sounds, I don't see any other option other than to turn on TRACE level logging for that class. Check out the logs of this question.
In Fabric8, the preferred way to obtain an ActiveMQ connection is via the mq-fabric profile, which provides an ActitveMQConnection object via Declarative Services. An example of this is given on GitHub, which works just fine.
However, I've yet to find a way for Declarative Services and Blueprint Services to collaborate in Fabric8 (or any OSGI-environment, really), thus, my OSGI application must either use DS or blueprint. Mixing both doesn't seem to be an option.
If you want to use blueprint (which I do), you must first create a broker through the web UI, then go back to the console and type cluster-list, finding the port that Fabric8 assigned to the broker and then configure a connection in blueprint like so:
<bean id="activemqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://mydomain:33056" />
<property name="userName" value="admin" />
<property name="password" value="admin" />
</bean>
While this does work, it's not exactly deployment-friendly, as it involves a few manual steps that I'd like to avoid if possible. The main issue is that I don't know what that port is going to be. I've combed through the config files and couldn't find it anywhere.
Is there a cleaner, more automated way to obtain an ActiveMQ connection in Fabric8 via blueprint, or must we use Declarative Services?
Stumbled across a solution to this issue in the fabric-camel-demo, which illustrates how to instantiate an ActiveMQConnectionFactory bean in Fabric8 via Blueprint.
<!-- use the fabric protocol in the brokerURL to connect to the ActiveMQ broker registered as default name -->
<!-- notice we could have used amq as the component name in Camel, and avoid any configuration at all,
as the amq component is provided out of the box when running in fabric -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="discovery:(fabric:default)"/>
<property name="userName" value="admin"/>
<property name="password" value="admin"/>
</bean>
Hope this helps!
Our system will not shutdown when a "Stop" command is issued from the Tomcat Manager. I have determined that it is related to ActiveMQ/Spring. I have even figured out how to get it to shutdown, however my solution is a hack (at least I hope this isn't the "correct" way to do it). I would like to know the proper way to shutdown ActiveMQ so that I can remove my hack.
I inherited this component and I have no information about why certain architectural decisions were made, after a lot of digging I think I understand his thoughts, but I could be missing something. In other words, the real problem could be in the way that we are trying to use ActiveMQ/Spring.
We run in ServletContainer (Tomcat 6/7) and use ActiveMQ 5.9.1 and Spring 3.0.0 Multiple instances of our application can run in a "group", with each instance running on it's own server. ActiveMQ is used to facilitate communication between the multiple instances. Each instance has it's own embedded broker and it's own set of queues. Every queue on every instance has exactly 1 org.springframework.jms.listener.DefaultMessageListenerContainer listening to it, so 5 queues = 5 DefaultMessageListenerContainers for example.
Our system shut down properly until we fixed a bug by adding queuePrefetch="0" to the ConnectionFactory. At first I assumed that this change was incorrect in some way, but now that I understand the situation, I am confident that we should not be using the prefetch functionality.
I have created a test application to replicate the issue. Note that the information below makes no mention of message producers. That is because I can replicate the issue without ever sending/processing a single message. Simply creating the Broker, ConnectionFactory, Queues and Listeners during boot, is enough to keep the system from stopping properly.
Here is my sample configuration from my Spring XML. I will be happy to provide my entire project if someone wants it:
<amq:broker persistent="false" id="mybroker">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://0.0.0.0:61616"/>
</amq:transportConnectors>
</amq:broker>
<amq:connectionFactory id="ConnectionFactory" brokerURL="vm://localhost?broker.persistent=false" >
<amq:prefetchPolicy>
<amq:prefetchPolicy queuePrefetch="0"/>
</amq:prefetchPolicy>
</amq:connectionFactory>
<amq:queue id="lookup.mdb.queue.cat" physicalName="DogQueue"/>
<amq:queue id="lookup.mdb.queue.dog" physicalName="CatQueue"/>
<amq:queue id="lookup.mdb.queue.fish" physicalName="FishQueue"/>
<bean id="messageListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer" abstract="true">
<property name="connectionFactory" ref="ConnectionFactory"/>
</bean>
<bean parent="messageListener" id="cat">
<property name="destination" ref="lookup.mdb.queue.dog"/>
<property name="messageListener">
<bean class="com.acteksoft.common.remote.jms.WorkerMessageListener"/>
</property>
<property name="concurrentConsumers" value="200"/>
<property name="maxConcurrentConsumers" value="200"/>
</bean>
<bean parent="messageListener" id="dog">
<property name="destination" ref="lookup.mdb.queue.cat"/>
<property name="messageListener">
<bean class="com.acteksoft.common.remote.jms.WorkerMessageListener"/>
</property>
<property name="concurrentConsumers" value="200"/>
<property name="maxConcurrentConsumers" value="200"/>
</bean>
<bean parent="messageListener" id="fish">
<property name="destination" ref="lookup.mdb.queue.fish"/>
<property name="messageListener">
<bean class="com.acteksoft.common.remote.jms.WorkerMessageListener"/>
</property>
<property name="concurrentConsumers" value="200"/>
<property name="maxConcurrentConsumers" value="200"/>
</bean>
My hack involves using a ServletContextListener to manually stop the objects. The hacky part is that I have to create additional threads to stop the DefaultMessageListenerContainers. Perhaps I'm stopping the objects in the wrong order, but I've tried everything that I can imagine. If I attempt to stop the objects in the main thread, then they hang indefinitely.
Thank you in advance!
UPDATE
I have tried the following based on boday's recommendation but it didn't work. I have also tried to specify the amq:transportConnector uri as tcp://0.0.0.0:61616?transport.daemon=true
<amq:broker persistent="false" id="mybroker" brokerName="localhost">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://0.0.0.0:61616?daemon=true"/>
</amq:transportConnectors>
</amq:broker>
<amq:connectionFactory id="connectionFactory" brokerURL="vm://localhost" >
<amq:prefetchPolicy>
<amq:prefetchPolicy queuePrefetch="0"/>
</amq:prefetchPolicy>
</amq:connectionFactory>
At one point I tried to add similar properties to the brokerUrl parameter in the amq:connectionFactory element and the shutdown worked properly, however after further testing I learned that the properties were resulting in an exception to be thrown from VMTransportFactory. This resulted in improper initialization and the basic message functionality didn't work.
In case anyone else is wondering, as far as I can see it's not possible to have a daemon ListenerContainer using ActiveMQ.
When the ActiveMQConnection is started, it creates a ThreadPoolExecutor with non-daemon thread. This is seemingly to avoid issues when failing over the connection from one broker to another.
https://issues.apache.org/jira/browse/AMQ-796
executor = new ThreadPoolExecutor(1, 1, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "ActiveMQ Connection Executor: " + transport);
//Don't make these daemon threads - see https://issues.apache.org/jira/browse/AMQ-796
//thread.setDaemon(true);
return thread;
}
});
try setting daemon=true on your TCP transport, this allows the process to run as a deamon thread which won't block the shutdown of your container
see http://activemq.apache.org/tcp-transport-reference.html
I need some precise steps (with reference to glassfish docs) for the following scenario;
How to create JMS queues to support "store locally and forward remotely". The remote system is HornetQ.
The remote connectivity should support SSL and user/password authentication
It should support automatic retry and configuration of # of retry.
In case of any failure, it should be possible to select the jms messages are resend in bulk
I already went through some of the glassfish docs but needs to be further validated by the experts.
Simple Scenario but still not working "Send a JMS to sourceQueue and JMS bridge service to transfer to targetQueue". Here are the configurations;
A. domain.xml (extract)
<jms-service default-jms-host="default_JMS_host" type="EMBEDDED">
<jms-host host="localhost" name="default_JMS_host" lazy-init="false">
<property name="imq.bridge.bridge1.type" value="jms"></property>
<property name="imq.bridge.bridge1.xmlurl" value="file:///C:/TEMP/bridge.xml"></property>
<property name="imq.bridge.bridge1.autostart" value="true"></property>
<property name="imq.bridge.bridge1.logfile.limit" value="0"></property>
<property name="imq.bridge.bridge1.logfile.count" value="1"></property>
<property name="imq.bridge.enabled" value="true"></property>
<property name="imq.bridge.admin.user" value="admin"></property>
<property name="imq.bridge.admin.password" value="admin"></property>
<property name="imq.bridge.activelist" value="bridge1"></property>
</jms-host>
</jms-service>
B. bridge.xml (bridge configuration)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jmsbridge SYSTEM "sun_jmsbridge_1_0.dtd">
<jmsbridge name="bridge1">
<link name="link1">
<enabled ="true"></enabled>
<source connection-factory-ref=”jms/__defaultConnectionFactory" destination-ref="sourceQueue"></source>
<target connection-factory-ref="jms/__defaultConnectionFactory" destination-ref="targetQueue "></target>
</link>
<connection-factory ref-name="jms/__defaultConnectionFactory"/>
<connection-factory ref-name="jms/__defaultConnectionFactory"/>
<destination ref-name="sourceQueue" type="queue" lookup-name="sourceQueue"/>
<destination ref-name="targetQueue" type="queue" lookup-name="targetQueue"/>
</jmsbridge>
Glassfish deploys the Glassfish JMS server. If you want to talk to HornetQ you need to use HornetQ libraries and use the proper API (either core or JMS) to talk to the HornetQ server.
If you need XA integration through MDBs then you will need to deploy the Resource Adapter and do the proper recovery integration. Look at the glassFish on how to deploy an external resource adapter.. but that's an area that nobody at RedHat has tested yet and given the state of glassFish being discontinued I doubt that will happen any time soon.
Another way you could do is to deploy the JMS Bridge within JBoss / HornetQ, Where any message sent on GlassFish JMS would be consumed on HornetQ through the bridging process.
How do I set the redeliveryPolicy in ActiveMQ on a Queue?
1) In the doc, see: activeMQ Redelivery, the explain that you should set it on the ConnectionFactory or Connection. But I want to use different value's for different Queue's.
2) Apart from that, I don't seem to get it work. Setting it on the connection factory in Spring (I am using activemq 5.4.2. with Spring 3.0) like this don't seem to have any effect:
<amq:connectionFactory id="amqConnectionFactory" brokerURL="${jms.factory.url}" >
<amq:properties>
<amq:redeliveryPolicy maximumRedeliveries="6" initialRedeliveryDelay="15000" useExponentialBackOff="true" backOffMultiplier="5"/>
</amq:properties>
</amq:connectionFactory>
I also tried to set it as property on the defined Queue, but that also seem to be ignored as the redelivery occurs sooner that the defined values:
<amq:queue id="jmsQueueDeclarationSnd" physicalName="${jms.queue.declaration.snd}" >
<amq:properties>
<amq:redeliveryPolicy maximumRedeliveries="6" initialRedeliveryDelay="15000" useExponentialBackOff="true" backOffMultiplier="5"/>
</amq:properties>
</amq:queue>
Thanks
I too was using the method shown by Ivan above for amq:connectionFactory
Whilst upgrading to ActiveMQ 5.7.0 I noticed this no longer works (since the implementation of https://issues.apache.org/jira/browse/AMQ-3224). Anyway after reading a better post on the ActiveMQ forums I currently use :-
<amq:queue id="emailQueue" physicalName="emailQueue" />
<amq:queue id="smsQueue" physicalName="smsQueue" />
<!-- Wait 15 seconds first re-delivery, then 45, 135, 405, 1215, 3645 seconds -->
<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="backOffMultiplier" value="3" />
<property name="initialRedeliveryDelay" value="15000" />
<property name="maximumRedeliveries" value="6" />
<property name="queue" value="*" />
<property name="redeliveryDelay" value="15000" />
<property name="useExponentialBackOff" value="true" />
</bean>
<amq:connectionFactory id="jmsFactory" brokerURL="yourProtocol/BrokerURL">
<property name="redeliveryPolicy" ref="redeliveryPolicy" />
</amq:connectionFactory>
Note that for any messages that fail to be redelivered after 6 retries, ActiveMQ will create a DLQ.emailQueue' or DLQ.smsQueue and enqueue the message on that queue (dequeuing it from the original queue).
I got it working by setting it on the factory as done above but only when creating the connection factory as a Spring bean and not through XBean as shown above. This is because the xsd doesn't allow you to set the redeliveryPolicy as an object, but merely as a String.
After setting the cache level to Consumer in Spring's DefaultMessageListenerContainer, it all worked.
On the queue , it seems that you simple can set a delivery policy... Strange, as I would like to have different settings for different queue's/topics. Just imagine you have a slow and faster queue, or a external system that you connect to that needs more time to recover..
Maybe this feature is still to be implemented
You can set the redeliveryPolicy within the amq namespace like this:
<amq:connectionFactory id="jmsRedeliverConnectionFactory" brokerURL="vm://localhost">
<amq:redeliveryPolicy>
<amq:redeliveryPolicy maximumRedeliveries="5" initialRedeliveryDelay="1000" useExponentialBackOff="true" backOffMultiplier="5" />
</amq:redeliveryPolicy>
</amq:connectionFactory>
I could not get ActiveMQ (5.7.0) to recognize my redelivery policy when I defined it using <amq:properties> on the ConnectionFactory or the Queue (it kept using the default redelivery policy). What worked for me is this:
Create the RedeliveryPolicy as a standalone bean, then Spring-reference it in the ConnectionFactory
Create an explicit DLQ and Spring-reference it in the RedeliveryPolicy
Spring config as follows:
<amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost" redeliveryPolicy="#activeMQRedeliveryPolicy" />
<amq:redeliveryPolicy id="activeMQRedeliveryPolicy" destination="#myDLQ" useExponentialBackOff="true" backOffMultiplier="3" maximumRedeliveries="4" />
<amq:queue id="myDLQ" physicalName="DLQ.myDLQ" />