I am using the Spring AMQP library .How do I configure connectionTimeouts and socketTimeouts in CachingConnectionFactory.I assume it must internally use
http://www.rabbitmq.com/javadoc/com/rabbitmq/client/ConnectionFactory.html#setConnectionTimeout(int)
We have an open JIRA to expose some more of these attributes, which should be in the next releease.
In the meantime, you can wire up a Rabbit ConnectionFactory and provide it to the CachingConnectionFactory - see the documentation.
Related
From my spring-boot service(with camel) I need to connect to two RabbitMQ instances;not cluster, but altogether different instances(with diff IP, vhost and credentials)
Versions: spring-boot: 1.5.12 and camel: 2.21.5
I want to create multiple connection factories and specify them in the camel endpoint name like this.
rabbitmq:exchange1?connectionFactory=#customFactory1
rabbitmq:exchange2?connectionFactory=#customFactory2
Currently this is not supported as RabbitAnnotationDrivenConfiguration class expects only one instance of ConnectionFactory
Even if I qualify the ConnectionFactory Beans with #Qualifier/#Primary the connectionFactory query param used in camel endpoint is ignored (or) properties from camel.component.rabbitmq are taking priority
I'm now using a workaround to specify all the connection properties in the endpoint name like
rabbitmq:exchange1?host=<host>&vhost=<vhost>&username=something&password=something
Is there a better way to achieve this...?
I am using Spring Boot with spring-rabbitmq. My connection factory is configured in application.properties and it seems to be nice.
My aim is: during start check if exists queue if specific name, and in case of absence create such queue. I am not sure how to deal with it. What beans should I create in config class? From what I read it should be RabbitAdmin, however I am not sure about it. Can you help me?
Everything is described clearly in the Reference Manual:
The AMQP specification describes how the protocol can be used to configure Queues, Exchanges and Bindings on the broker. These operations which are portable from the 0.8 specification and higher are present in the AmqpAdmin interface in the org.springframework.amqp.core package.
And further:
When the CachingConnectionFactory cache mode is CHANNEL (the default), the RabbitAdmin implementation does automatic lazy declaration of Queues, Exchanges and Bindings declared in the same ApplicationContext.
So, you should declare Queue, Exchange and Binding beans in your application context and AmqpAdmin will take care about their definition on the target Broker.
There must be a note that according AMQP protocol, if entity already exists on the Broker, the declaration is just silent and idempotent.
So, in your case you don't need to worry about queues existence and just provide their declarations as beans in the application context.
Would it be possible to set up a DataSource using Spring Cloud in which open JDBC connections could be injected into all of my Spring Boot applications?
Something kind of like a JNDI server lookup? If so, can someone provide some examples or a description on how to use this type of configuration?
You could use a Spring Cloud bootstrap configuration to create a DataSource. I don't see much value in doing it that way over a normal Spring Boot autoconfiguration though. Link: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-developing-auto-configuration.
One solution I found out was to set all datasources info into the properties files which will supplied by Spring Cloud Config Server to applications clients. So the aplications clients which creates DataSources gets from remote properties those values.
Tomcat has a built-in JDBC connection pooling, but unfortunately no built-in JMS connection pooling.
We are migrating a legacy Tomcat web application from WebSphere MQ version 6 to 7.
Unfortunately, connection pooling has been removed in WebSphere MQ 7 as described here: http://www-01.ibm.com/support/docview.wss?uid=swg21665128
Now we are afraid that we will run into troubles if we just use the following code for configuring MQ in Tomcat:
<Resource name="jms/XXXQCF" auth="Container"
type="com.ibm.mq.jms.MQQueueConnectionFactory" factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
description="JMS Queue Connection Factory"
HOST="xxx.com" PORT="1429" CHAN="XXX" TRAN="1"
QMGR="XXX" />
The reason for our concerns is that this will not use a pooled JMS provider when using MQ 7. For details, see also http://activemq.apache.org/jmstemplate-gotchas.html
Alternative solutions we see are:
1) Use of Atomikos
Atomikos has a com.atomikos.jms.AtomikosConnectionFactoryBean that can be used instead of MQQueueConnectionFactory
But using an XA transaction manager is a huge overhead when we don't need XA
2) Use Spring's CachingConnectionFactory
looks like a good solution, but unfortunately our legacy application does not use Spring.
So we assume that using CachingConnectionFactory would mean quite some effort.
3) Use Apache Commons Pool
looks promising too, but implementing it correctly for JMS will require some good JMS knowledge
Our questions:
is there a JMS provider that can be used to wrap MQQueueConnectionFactory and that will pool connections, sessions, producers and consumers?
did anyone succeed in implementing one of the alternative solutions we outlined above?
As proposed by Umapathy in option 3, we now opted for the approach using Spring's CachingConnectionFactory, and it works well even for a non-Spring application. All you need to do is add the Spring Jars to the classpath, and wrap the MQQueueConnectionFactory with a CachingConnectionFactory.
We chose to create our own Tomcat QueueConnectionFactoryFactory that enables us to leave the original application code completely untouched, you just need to replace the original MQ connection factory from the Tomcat configuration file (shown above in the question) with the following XML definition:
<Resource name="jms/XXXQCF" auth="Container"
type="org.springframework.jms.connection.CachingConnectionFactory"
factory="at.rsf4j.core.utilities.RSFCachingMQQueueConnectionFactoryFactory"
description="JMS Queue Connection Factory"
HOST="xxx.com" PORT="1429" CHAN="XXX" TRAN="1"
QMGR="XXX" />
Here is the (simplified) code (without error checking) for the RSFCachingMQQueueConnectionFactoryFactory:
public class RSFCachingMQQueueConnectionFactoryFactory implements ObjectFactory{
public Object getObjectInstance (Object obj, Name name, Context nameCtx, Hashtable<?,?> environment)
throws NamingException {
Reference ref = (Reference) obj;
String beanClassName = ref.getClassName();
Class<?> beanClass = Class.forName(beanClassName);
if (CachingConnectionFactory.class.isAssignableFrom(beanClass)){
MQQueueConnectionFactoryFactory cff = new MQQueueConnectionFactoryFactory();
Reference mqReference = new Reference(
MQQueueConnectionFactory.class.getName());
Enumeration<RefAddr> allAddrs = ref.getAll();
while (allAddrs.hasMoreElements()){
mqReference.add(allAddrs.nextElement());
}
MQQueueConnectionFactory cf = (MQQueueConnectionFactory)cff.getObjectInstance(mqReference, name, nameCtx, environment);
CachingConnectionFactory ccf = (CachingConnectionFactory)beanClass.newInstance();
ccf.setTargetConnectionFactory(cf);
return ccf;
}
}
I think you already know the answer.
option 1: Go with a Java EE application server. This has inbuilt JMS pools.
option 2: If this is a simple application that does a single job (like putting on a queue with fire and forget type), you can connect to the JMS provider (qmgr) and create the producer or consumer in the servlet_init method. This means the legacy code needs an update. You also need to take care of the reconnect when something breaks as JMS reconnect properties doesn't kick off a reconnection (as far as my experience goes).
option 3: I have gone with Spring's CachingConnectionFactory when the application happens to be more than a little complex than one in option 2. I have applications that use JMSTemplate and some doesn't.
I managed to create simple Websocket application with Spring 4 and Stomp. See my last question here
Then I tried to use remote message broker(ActiveMQ). I just started the broker and changed
registry.enableSimpleBroker("/topic");
to
registry.enableStompBrokerRelay("/topic");
and it worked.
The question is how the broker is configured? I understand that in this case the application automagicaly finds the broker on localhost:defaultport, bu what if I need to point the app to some other broker on other machine?
The enableStompBrokerRelay method returns a convenient Registration instance that exposes a fluent API.
You can use this fluent API to configure your Broker relay:
registry.enableStompBrokerRelay("/topic").setRelayHost("host").setRelayPort("1234");
You can also configure various properties, like login/pass credentials for your broker, etc.
Same with XML Configuration:
<websocket:message-broker>
<websocket:stomp-endpoint path="/foo">
<websocket:handshake-handler ref="myHandler"/>
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic,/queue"
relay-host="relayhost" relay-port="1234"
client-login="clientlogin" client-passcode="clientpass"
system-login="syslogin" system-passcode="syspass"
heartbeat-send-interval="5000" heartbeat-receive-interval="5000"
virtual-host="example.org"/>
</websocket:message-broker>
See the StompBrokerRelayRegistration javadoc for more details on properties and default values.