Running IBM MQ Container Image with Custom Configuration and Creating JMS JNDI Bindings

MQ

Recently I need to test some J2EE integration work on IBM MQ. Since it is for testing purposes I run it as a container instead of the full-blown VM.

Preparing a custom QMSC file

Create the following file 80-my-test.mqsc

define listener(LISTENER) trptype(tcp) control(qmgr) port(1414) replace
start listener(LISTENER)
define authinfo(my.authinfo) authtype(idpwos) chckclnt(reqdadm) chcklocl(optional) adoptctx(yes) replace
alter qmgr connauth(my.authinfo)
refresh security(*) type(connauth)
def chl(SYSTEM.ADMIN.SVRCONN) chltype(SVRCONN) replaceset chlauth('*') type(addressmap) address('*') usersrc(noaccess) descr('back-stop rule - blocks everyone') action(replace)set chlauth(SYSTEM.ADMIN.SVRCONN) type(blockuser) userlist('nobody') descr('block access for admin channel') action(replace)set chlauth(SYSTEM.ADMIN.SVRCONN) type(usermap) clntuser('admin') usersrc(channel) descr('allows admin user to connect via admin channel') action(replace)set chlauth(SYSTEM.ADMIN.SVRCONN) type(usermap) clntuser('admin') usersrc(map) mcauser(1001) descr('allow admin as 1001') action(replace)set authrec objtype(qmgr) principal('admin') authadd(all)
set authrec profile(*) objtype(queue) principal('admin') authadd(all)
define qlocal('testq1') replace
define qlocal('testq2') replace
define qlocal('testq3') replace
define qlocal('testq4') replace
define qlocal('testq5') replace

Define a listener on port 1414.

Define a authinfo named as my.authinfo and let the queue manager use it.

Create/re-create a channel with the default system channel name, SYSTEM.ADMIN.SVRCONN

Once the channel is defined, we set the access permission step by step. First, block all access from any IP address. Then we block the access for the channel of SYSTEM.ADMIN.SVRCONN. Lastly, we enable the user “admin” to access this channel.

Starting from version 9.1.5, the OS-based user authentication is not supported anymore. You have to use LDAP to authenticate the users other than the default available admin and app. Meantime, the container is running MQ with a specific user id 1000. In order for the admin user to access the MQ, we need to map user admin to the MQ process user id, 1000. This is what the line of mcauser(1000) does.

At the last of the authorization, we assign the admin the full admin access for any action in the resources for queue and queue manager.

With these settings, we will be able to access the MQ with MQ explorer and allow the application to connect the MQ through the admin channel.

At the end of the MQSC file, we create the local queues for the testing.

Launch of the Container

mkdir -p mytest/mqpodman run -d --name mq -p 1414:1414 -p 9443:9443 \
-v $HOME/my-test/mq:/mnt/mqm \
-v $HOME/80-load-test.mqsc:/etc/mqm/80-my-test.mqsc \
-e LICENSE=accept \
-e MQ_QMGR_NAME=QM1 \
-e MQ_DEV=false \
-e MQ_ADMIN_PASSWORD=CustomPassword \
-e MQ_APP_PASSWORD=CustomPassword \
ibmcom/mq

Expose the MQ port 1414 for the external app to connect. Expose the web console access on port 9443.

Map the /mnt/mq folder for data persistence. Map the custom mqsc file into the container at /etc/mqm/80-my-test.mqsc

Set couples of the environment variables to define the queue manager’s name and to disable the default DEV queues.

Once the container is running we can use MQ Explorer to connect with the admin and password defined in MQ_ADMIN_PASSWORD. The application can be configured to connect to the MQ with the admin account for testing purposes.

JMS JNDI Bindings

Create the following JMS definition file, jms.queues.txt

DEFINE QCF(mqqcf) QMGR(QM1) tran(client) chan(SYSTEM.ADMIN.SVRCONN) host(192.168.10.102) port(1414)DEFINE Q(testq1) QUEUE(testq1) QMGR(QM1)
DEFINE Q(testq2) QUEUE(testq2) QMGR(QM1)
DEFINE Q(testq3) QUEUE(testq3) QMGR(QM1)

Create the following JNDI config file, JMSAdmin.config

INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory
PROVIDER_URL=file:///tmp/jndi
SECURITY_AUTHENTICATION=none

Run podman cp to copy the above two files into the container.

podman cp JMSAdmin.config mq:/opt/mqm/java/bin
podman cp jms.queues.txt mq:/tmp

Launch a podman exec session to the MQ container, run the following

export CLASSPATH=$CLASSPATH:/opt/mqm/java/lib:/opt/mqm/java/lib/com.ibm.mq.jar:/opt/mqm/java/lib/com.ibm.mq.jms.Nojndi.jar:/opt/mqm/java/lib/com.ibm.mq.soap.jar:/opt/mqm/java/lib/com.ibm.mqetclient.jar:/opt/mqm/java/lib/com.ibm.mqjms.jarcd /opt/mqm/java/bin
rm -rf /tmp/jndi
mkdir -p /tmp/jndi

./JMSAdmin < /tmp/jms.queues.txt

watch the bindings file is created,

bash-4.4$ ls -la
total 108
drwxr-xr-x 2 1001 root 4096 May 4 04:00 .
drwxrwxrwt 4 root root 4096 May 12 16:42 ..
-rw-r--r-- 1 1001 root 98393 May 4 04:00 .bindings
bash-4.4$ pwd
/tmp/jndi

The .bindings file can be copied to external apps to perform the JNDI lookup and connections.

Cloud explorer