I had a working Spring Boot application which uses MQQueueConnectionFactory to initialize a connection to an MQ server.
In my applicationContext.xml I wired a custom configuration class equivalent to this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="mqConfiguration" class="com.myapp.MqConfiguration">
<property name="host" value="127.0.0.1" />
<property name="port" value="3005" />
<property name="username" value="joe" />
<property name="password" value="mypassword" />
<property name="queueManager" value="QUEUE_MANAGER_NAME" />
<property name="channel" value="SERVER_CHANNEL" />
<property name="sendQueue" value="OUTBOUND_QUEUE_NAME" />
<property name="receiveQueue" value="INBOUND_QUEUE_NAME" />
</bean>
</beans>
I was loading the applicationContext via @ImportResource( "classpath:applicationContext.xml")
Everything worked fine and it would send and receive messages via the MQ server.
Then I decided to eliminate my applicationContext.xml (the mqConfiguration bean was the only thing in it, anyway) and move the wiring of MqConfiguration into my application.properties file.
So, my basic strategy was to add the following into my application.properties:
configuration.mq.host="127.0.0.1"
configuration.mq.port="3005"
etc.
And then I removed the ImportResource directive and added the following annotation:
@PropertySources( {
@PropertySource( value = "classpath:application.properties" )
})
And then, in the MqConfiguration class, I used @Value to wire the application.properties values into the MqConfiguration class, like so:
public class MqConfiguration {
@Value( "${configuration.mq.host}" ) private String host;
@Value( "${configuration.mq.port}" ) private Integer port;
etc.
Upon making this change, suddenly my Java code will not connect to MQ (MQ responds with a MQRC_HOST_NOT_AVAILABLE and my sends and response cause exceptions).
This is very peculiar to me given that I can prove that the MQQueConnectionFactory bean is receiving the values that were provided in application.properties. Take a look at the MQQueueConnectionFactory bean:
public static MQQueueConnectionFactory mqQueueConnectionFactory( MqConfiguration mqConfiguration ) {
(...ommitted..)
System.out.println( mqConfiguration.getHost ); // this is 127.0.0.1.. proving we got the value from application.properties
mqConnectionFactory.setHostName( mqConfiguration.getHost() );
(...ommitted..)
}
}
Here is the basic layout of my beans which initialize the connection:
@Bean
public static MQQueueConnectionFactory mqQueueConnectionFactory( MqConfiguration mqConfiguration )
@Bean
UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter( MQQueueConnectionFactory mqQueueConnectionFactory ) {
@Bean
@Primary
public CachingConnectionFactory cachingConnectionFactory( UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter )
@Bean
public JmsOperations jmsOperations( CachingConnectionFactory cachingConnectionFactory )
And here is how I use the JmsOperations object to send and receive:
public Object receiveMessage( MqConfiguration mqConfiguration ) throws JmsException {
System.out.println( mqConfiguration.getReceiveQueue() ); // this is the proper value: INBOUND_QUEUE_NAME
return jmsOperations.receiveAndConvert( mqConfiguration.getReceiveQueue() );
}
public boolean sendMessage( String message, MqConfiguration mqConfiguration ) {
JmsTemplate jmsTemplate = ( JmsTemplate ) jmsOperations;
System.out.println( mqConfiguration.getSendQueue() ); // this is the proper value: OUTBOUND_QUEUE_NAME
MQQueue destinationQueue = jmsOperations.execute( executeSession -> MqQueueUtils.resolveQueue( jmsTemplate, executeSession, mqConfiguration.getSendQueue() ) );
jmsOperations.convertAndSend( destinationQueue, message );
return true;
}
Any thoughts on this one? It seems unbelievable that switching wiring via application.properties vs. applicationContext.xml would make any difference, especially if the same actual values are coming in from either source. But somehow I can not escape the conclusion that something with the MQ connection is getting messed up when the same values come from application.properties.