Ad

Unable To Connect To IBM MQ From A Spring Boot Application

- 1 answer

I am trying to connect to a centrally hosted IBM MQ from my Spring Boot application. This is the configuration I am trying with:

application.yml

spring:
  application:
    name: test-app

server:
  port: 8088

ibm:
  mq:
    channel: xxx.SVRCONN
    queue-manager: QM.xxx
    conn-name: xxx.xx.xxx(1414)
    user: user
    password: password

test:
  mq:
    queue-name: XXX.QUEUE

Bean Configuration

@Configuration
@EnableJms
public class JMSConfig {

    @Value("${ibm.mq.conn-name}")
    private String host;

    @Bean
    public MQQueueConnectionFactory mqQueueConnectionFactory() {
        MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
        mqQueueConnectionFactory.setHostName(host);
        try {
            String keystoreKey = "xxx";
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("mq-client.jks"),
                    keystoreKey.toCharArray());

            // Create key manager
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, keystoreKey.toCharArray());
            KeyManager[] km = keyManagerFactory.getKeyManagers();

            // Create trust manager
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] tm = trustManagerFactory.getTrustManagers();

            // Initialize SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(km, tm, null);
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            mqQueueConnectionFactory.setPort(1414);
            mqQueueConnectionFactory.setChannel(channel);
            mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
            mqQueueConnectionFactory.setObjectProperty(WMQConstants.WMQ_SSL_SOCKET_FACTORY, sslSocketFactory);
            // mqQueueConnectionFactory.setSSLCipherSuite("TLS_RSA_WITH_AES_256_CBC_SHA256");
            mqQueueConnectionFactory.setIntProperty(CommonConstants.WMQ_CONNECTION_MODE, CommonConstants.WMQ_CM_CLIENT);
            mqQueueConnectionFactory.setTransportType(CommonConstants.WMQ_CM_BINDINGS);


            MQEnvironment.sslSocketFactory = sslSocketFactory;
            MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA256";

        } catch (Exception e) {
            e.printStackTrace();
        }
        return mqQueueConnectionFactory;
}

The problem: In this configuration, if this line is added:

mqQueueConnectionFactory.setSSLCipherSuite("TLS_RSA_WITH_AES_256_CBC_SHA256");

then I get this exception:

Could not refresh JMS Connection for destination 'RCAEC.RCA.CPO.1.QUEUE' - retrying using FixedBackOff{interval=5000, currentAttempts=1, maxAttempts=unlimited}. Cause: JMSFMQ6312: An exception occurred in the Java(tm) MQI.; nested exception is com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2396'.

And if this line is added (removing the previously mentioned one):

MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_256_CBC_SHA256";

then I always get this exception:

Could not refresh JMS Connection for destination 'xxxx.QUEUE' - retrying using FixedBackOff{interval=5000, currentAttempts=2, maxAttempts=unlimited}. Cause: JMSFMQ6312: An exception occurred in the Java(tm) MQI.; nested exception is com.ibm.mq.jmqi.JmqiException: CC=2;RC=2495;AMQ8568: The native JNI library 'mqjbnd64' was not found. For a client installation this is expected. [3=mqjbnd64]

I also tried to set -Djava.library.path="C:/Program Files/IBM/WebSphere MQ/java/lib64", but no luck.

Am I missing something here?

Ad

Answer

Your first error shows an MQ Reason code of 2396 (MQRC_SSL_NOT_ALLOWED). The explanation of this in IBM Knowledge Center is:

A connection to a queue manager was requested, specifying TLS encryption. However, the connection mode requested is one that does not support TLS (for example, bindings connect).

Looking at your code, while you have set up a number of attributes needed for a client (aka network) connection, you finish off with the following line:-

mqQueueConnectionFactory.setTransportType(CommonConstants.WMQ_CM_BINDINGS);

which means that you are using a local bindings (aka memory) type of connection and not a client connection. This means that many of your other settings are ignored. Delete that line to allow the following earlier line, to take effect, and see how you get on.

mqQueueConnectionFactory.setTransportType(CommonConstants.WMQ_CM_CLIENT);

See IBM Knowledge Center: TRANSPORT for more details on this specific JMS Object property.

Please note, that once you switch to using a client connection instead of a local bindings connection, you will run into all sorts of other hurdles, such as the client security settings that will undoubtedly refuse you permission to connect initially! There are a good many questions on here about how to solve those issues. Remember to check your queue manager error log when you hit an MQ 2035 reason code.

Regarding the missing mqjbnd64, rather than repeating information, please see this answer (including comments).

Ad
source: stackoverflow.com
Ad