WebSphere Application Server & Liberty

 View Only

Configure WebSphere Liberty application to put a message into an IBM MQ cluster queue

By Kok Sing Khong posted Tue November 01, 2022 09:58 AM

  
This article describes the key steps to configure an application running on the WebSphere Liberty server to put a message into the cluster queue of an MQ queue manager. A queue manager cluster is a network of queue managers, interconnected to fulfill a business function. Queue managers within the cluster can communicate with one another without the need to define sender/receiver channels or remote-queue definitions - which simplifies administration tasks. In addition, when configured in a gateway queue manager pattern, it does load balancing to two or more queue managers.

Prerequisites

  • IBM MQ Resource Adapter 9.3.0.1-IBM-MQ-Java-InstallRA.jar (download from IBM Fix Central). 
  • Docker
  • Docker Compose
  • curl
  • Visual Studio Code

Overview

Note: For setup convenience, I will not be installing MQ and WebSphere Liberty, but instead use the IBM-certified images from IBM repositories. I will be using docker-compose to run the demo. The diagram below shows the logical architecture.


Some notes about the setup:
  • There are 3 queue managers configured in the queue manager cluster called AUS.
    • CANBERRA is configured as a gateway queue manager and a partial repository.
    • SYDNEY is configured as a queue manager that hosts a cluster queue called KANGAROO.Q. It is also a full repository.
    • MELBOURNE is configured as a queue manager that hosts a cluster queue called KANGAROO.Q. It is also a full repository.
  • There is an application mdbtest configured with the following:
    • JMS code sends a message to the cluster queue while connecting the CANBERRA queue manager.
    • Message drive bean MDBQM1 receives a message from KANGAROO.Q queue on SYDNEY queue manager.
    • Message drive bean MDBQM2 receives a message from KANGAROO.Q queue on MELBOURNE queue manager.

Configuration Files

The configuration can be found in this Git repository https://github.com/khongks/ws-liberty-mq-cluster. I will walk through the key configurations.

mdbtest/src/main/liberty/config/server.xml

  • JMS Connection Factory referencing a CCDT file ccdt-canberra.json. It is important to know that to send a message to a cluster queue, we need to specify a blank ' ' in the queueManager field.
    <jmsConnectionFactory connectionManagerRef="ConMgr6" jndiName="jms/wmqCF">
        <properties.wmqJms ccdtURL="file://${server.config.dir}ccdt-canberra.json" password="{xor}Lz4sLChvLTs=" queueManager=" " userName="app"/>
    </jmsConnectionFactory>​

  • JMS Activation Specification referencing a CCDT file ccdt-sydney.json. Here, we need to specify the actual queue manager name (SYDNEY) in the queueManager field.
    <jmsActivationSpec authDataRef="mqAuth" id="mdbtest/SampleListenerMDBQM1">
        <properties.wmqJms 
            ccdtURL="file://${server.config.dir}ccdt-sydney.json"         
            queueManager="SYDNEY" 
            destinationRef="jms/queue1"/>
    </jmsActivationSpec>​
  • JMS Activation Specification referencing a CCDT file ccdt-melbourne.json. Here, we need to specify the actual queue manager name (MELBOURNE) in the queueManager field.
    <jmsActivationSpec authDataRef="mqAuth" id="mdbtest/SampleListenerMDBQM2">
        <properties.wmqJms 
            ccdtURL="file://${server.config.dir}ccdt-melbourne.json" 
            queueManager="MELBOURNE"
            destinationRef="jms/queue1"/>
    </jmsActivationSpec>​

mdbtest/src/main/liberty/config/ccdt-canberra.json


  • This is the CCDT file that is used to connect to the CANBERRA queue manager. Note that in Docker networking, we can use the container name as the hostname. You will see this is how we specify this in our docker-compose file.
    {
        "channel": [
          {
            "name": "APP.SVRCONN",
            "clientConnection": {
              "connection": [
                {
                  "host": "canberra",
                  "port": 1414
                }
              ],
              "queueManager": " "
            },
            "type": "clientConnection"
          }
        ]
    }

mdbtest/src/main/liberty/config/ccdt-sydney.json

  • This is the CCDT file that is used to connect to the SYDNEY queue manager.
    {
        "channel": [
          {
            "name": "APP.SVRCONN",
            "clientConnection": {
              "connection": [
                {
                  "host": "sydney",
                  "port": 1414
                }
              ],
              "queueManager": "SYDNEY"
            },
            "type": "clientConnection"
          }
        ]
    }
    

mdbtest/src/main/liberty/config/ccdt-melbourne.json

  • This is the CCDT file that is used to connect to the MELBOURNE queue manager.
    {
        "channel": [
          {
            "name": "APP.SVRCONN",
            "clientConnection": {
              "connection": [
                {
                  "host": "melbourne",
                  "port": 1414
                }
              ],
              "queueManager": "MELBOURNE"
            },
            "type": "clientConnection"
          }
        ]
    }

ibmmq/CANBERRA/config.mqsc

  • One cluster receiver channel AUS.CANBERRA.
  • Two cluster sender channels AUS.SYDNEY connecting to SYDNEY queue manager and AUS.MELBOURNE connecting to MELBOURNE queue manager.
  • One server connection channel APP.SVRCONN for the application to connect to.
    DEF CHL(AUS.CANBERRA) CHLTYPE(CLUSRCVR) CONNAME('canberra(1414)') CLUSTER(AUS)
    
    DEF CHL(AUS.SYDNEY) CHLTYPE(CLUSSDR) CONNAME('sydney(1414)') CLUSTER(AUS)
    
    DEF CHL(AUS.MELBOURNE) CHLTYPE(CLUSSDR) CONNAME('melbourne(1414)') CLUSTER(AUS)
    
    DEF CHL(APP.SVRCONN) CHLTYPE(SVRCONN) MCAUSER('app') REPLACE
    
    SET CHLAUTH('*') TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(NOACCESS) DESCR('BackStop rule')
    
    SET CHLAUTH(AUS.CANBERRA) TYPE(BLOCKUSER) USERLIST('nobody') DESCR('Allow privileged users on this channel')
    
    SET CHLAUTH(AUS.CANBERRA) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(ASQMGR)
    
    SET CHLAUTH(APP.SVRCONN) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(ASQMGR)
    
    ALTER AUTHINFO(SYSTEM.DEFAULT.AUTHINFO.IDPWOS) AUTHTYPE(IDPWOS) ADOPTCTX(YES)
    
    REFRESH SECURITY TYPE(CONNAUTH)
    
    SET AUTHREC OBJTYPE(QUEUE) PROFILE(SYSTEM.CLUSTER.TRANSMIT.QUEUE) PRINCIPAL('app') AUTHRMV(ALL) AUTHADD(PUT,GET,BROWSE,INQ)​

ibmmq/SYDNEY/config.mqsc

  • Configured as a full repository.
  • One cluster receiver channel AUS.SYDNEY.
  • One cluster sender channels AUS.MELBOURNE connecting to MELBOURNE queue manager (peer full repository).
  • One local queue KANGAROO.Q configured as a cluster queue.
  • One server connection channel APP.SVRCONN for the application to connect to.
    ALTER QMGR REPOS(AUS)
    
    DEF CHL(AUS.SYDNEY) CHLTYPE(CLUSRCVR) CONNAME('sydney(1414)') CLUSTER(AUS)
    
    DEF CHL(AUS.MELBOURNE) CHLTYPE(CLUSSDR) CONNAME('melbourne(1414)') CLUSTER(AUS)
    
    DEF CHL(APP.SVRCONN) CHLTYPE(SVRCONN) MCAUSER('app') REPLACE
    
    DEF QL(KANGAROO.Q) CLUSTER(AUS) DEFBIND(NOTFIXED)
    
    SET CHLAUTH('*') TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(NOACCESS) DESCR('BackStop rule')
    
    SET CHLAUTH(AUS.SYDNEY) TYPE(BLOCKUSER) USERLIST('nobody') DESCR('Allow privileged users on this channel')
    
    SET CHLAUTH(AUS.SYDNEY) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(ASQMGR)
    
    SET CHLAUTH(APP.SVRCONN) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(ASQMGR)
    
    ALTER AUTHINFO(SYSTEM.DEFAULT.AUTHINFO.IDPWOS) AUTHTYPE(IDPWOS) ADOPTCTX(YES)
    
    REFRESH SECURITY TYPE(CONNAUTH)
    
    SET AUTHREC OBJTYPE(QUEUE) PROFILE(KANGAROO.Q) PRINCIPAL('app') AUTHRMV(ALL) AUTHADD(PUT,GET,BROWSE,INQ)​

ibmmq/MELBOURNE/config.mqsc

  • Configured as a full repository.
  • One cluster receiver channel AUS.MELBOURNE.
  • One cluster sender channels AUS.SYDNEY connecting to SYDNEY queue manager (peer full repository).
  • One local queue KANGAROO.Q configured as a cluster queue.
  • One server connection channel APP.SVRCONN for the application to connect to.
    ALTER QMGR REPOS(AUS)
    
    DEF CHL(AUS.MELBOURNE) CHLTYPE(CLUSRCVR) CONNAME('melbourne(1414)') CLUSTER(AUS)
    
    DEF CHL(AUS.SYDNEY) CHLTYPE(CLUSSDR) CONNAME('sydney(1414)') CLUSTER(AUS)
    
    DEF CHL(APP.SVRCONN) CHLTYPE(SVRCONN) MCAUSER('app') REPLACE
    
    DEF QL(KANGAROO.Q) CLUSTER(AUS) DEFBIND(NOTFIXED)
    
    SET CHLAUTH('*') TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(NOACCESS) DESCR('BackStop rule')
    
    SET CHLAUTH(AUS.MELBOURNE) TYPE(BLOCKUSER) USERLIST('nobody') DESCR('Allow privileged users on this channel')
    
    SET CHLAUTH(AUS.MELBOURNE) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(ASQMGR)
    
    SET CHLAUTH(APP.SVRCONN) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(ASQMGR)
    
    ALTER AUTHINFO(SYSTEM.DEFAULT.AUTHINFO.IDPWOS) AUTHTYPE(IDPWOS) ADOPTCTX(YES)
    
    REFRESH SECURITY TYPE(CONNAUTH)
    
    SET AUTHREC OBJTYPE(QUEUE) PROFILE(KANGAROO.Q) PRINCIPAL('app') AUTHRMV(ALL) AUTHADD(PUT,GET,BROWSE,INQ)​
There are four Dockerfile(s), and each is used to build the image.

  • ibmmq/CANBERRA/Docker is used to build the canberra image used to run the CANBERRA queue manager.
  • ibmmq/SYDNEY/Docker is used to build the sydney image used to run the SYDNEY queue manager.
  • ibmmq/MELBOURNE/Dockerfile is used to build the melbourne image used to run the MELBOURNE queue manager.
  • mdbtest/Dockerfile is used to build the mdbtest image used to run the WebSphere Liberty application. 
  • compose.yaml is a docker-compose file used to run all the containers in the demo.

Steps to run the demo

  • Build all the images.
    % cd ibmmq/CANBBERA
    % ./build.sh
    
    % cd ibmmq/SYDNEY
    % ./build.sh
    
    % cd ibmmq/MELBOURNE
    % ./build.sh
    
    % cd mdbtest
    % docker build -t mdbtest .​
  • Verify all the images are built
    % docker images
    REPOSITORY                                       TAG            IMAGE ID       CREATED         SIZE
    mdbtest                                          latest         e7c251230d01   2 days ago      1.11GB
    canberra                                         latest         4b50596ac4dc   3 days ago      833MB
    melbourne                                        latest         c26b4a8ead0a   3 days ago      833MB
    sydney                                           latest         89fc9db0d04f   3 days ago      833MB​
  • To run all the containers, we used Docker Compose.
    % docker-compose up -d​
    Creating network "ws-liberty-mq-cluster_mq-cluster" with the default driver
    Creating sydney    ... done
    Creating melbourne ... done
    Creating canberra  ... done
    Creating mdbtest   ... done
  • To check if all the containers are runnings
    % docker ps
    CONTAINER ID   IMAGE       COMMAND                  CREATED              STATUS              PORTS                                                                                            NAMES
    3fdbbe1e93cd   mdbtest     "/opt/ibm/helpers/ru…"   About a minute ago   Up About a minute   0.0.0.0:9080->9080/tcp, :::9080->9080/tcp, 0.0.0.0:10443->9443/tcp, :::10443->9443/tcp           mdbtest
    166ad3bc1b45   canberra    "runmqdevserver"         About a minute ago   Up About a minute   0.0.0.0:1414->1414/tcp, :::1414->1414/tcp, 0.0.0.0:9443->9443/tcp, :::9443->9443/tcp, 9157/tcp   canberra
    d7ea4105ccc5   melbourne   "runmqdevserver"         About a minute ago   Up About a minute   9157/tcp, 0.0.0.0:1416->1414/tcp, :::1416->1414/tcp, 0.0.0.0:9445->9443/tcp, :::9445->9443/tcp   melbourne
    8e435b0ba444   sydney      "runmqdevserver"         About a minute ago   Up About a minute   9157/tcp, 0.0.0.0:1415->1414/tcp, :::1415->1414/tcp, 0.0.0.0:9444->9443/tcp, :::9444->9443/tcp   sydney​

  • To check and tail the logs
    % docker-compose logs -f​
  • To test, open another terminal window and run the test script sendmessage.sh, specify the number of messages to put.
    % cd test
    ./sendmessage.sh 100​
  • From the logs, you will find that the messages are received alternately from each of the queue managers SYDNEY and MELBOURNE.
    mdbtest      | Message enqueued.
    mdbtest      | MDB received from QM1: test message #1
    mdbtest      | Message enqueued.
    mdbtest      | MDB received from QM1: test message #2
    mdbtest      | Message enqueued.
    mdbtest      | MDB received from QM2: test message #3
    mdbtest      | Message enqueued.
    mdbtest      | MDB received from QM1: test message #4
    mdbtest      | Message enqueued.
    ...
    ...
    ...
    ...
    mdbtest      | Message enqueued.
    mdbtest      | MDB received from QM1: test message #99
    mdbtest      | Message enqueued.
    mdbtest      | MDB received from QM2: test message #100

  • Finally, to stop all the container
    % docker-compose down​
    Stopping mdbtest   ... done
    Stopping canberra  ... done
    Stopping melbourne ... done
    Stopping sydney    ... done
    Removing mdbtest   ... done
    Removing canberra  ... done
    Removing melbourne ... done
    Removing sydney    ... done
    Removing network ws-liberty-mq-cluster_mq-cluster
0 comments
109 views

Permalink