# Integrating with IBM MQ

IBM MQ queues - channels that invoke services, MQMD and MQRFH2 headers, automatic replies and outgoing connections.

## Receiving messages from queues {#receiving-messages-from-queues}

No programming is needed to receive messages from IBM MQ queues. Create an IBM MQ channel in Dashboard, point it to a queue, and a service of your choice will be invoked for each message received.

[Video: New IBM MQ channel](https://zatosource-production.b-cdn.net/docs/gfx/channels/ibm-mq-create.webm?v=1790440787)

Dashboard menu: Connections > Message queues > IBM MQ > Channels

The message is available in self.request.input. If the message is JSON, it is the parsed object or array, so a service reads its fields directly, e.g. self.request.input\['transfer\_id'\]. Otherwise, it is the message body as bytes.

```python
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # The message
        data = self.request.input

        # Log what was received
        self.logger.info('IBM MQ message: %s', data)
```

## MQMD and MQRFH2 headers {#mqmd-and-mqrfh2-headers}

Every message's MQMD descriptor fields are available in self.request.headers, prefixed with "mqmd.".

If a message includes an MQRFH2 header, the way messages sent by JMS applications do, its folders are flattened into the same dictionary - a JMS property like Dst becomes "jms.Dst" and application properties from the usr folder become "usr.my\_property".

```python
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # MQMD fields
        message_id = self.request.headers['mqmd.message_id']
        format = self.request.headers['mqmd.format']

        # MQRFH2 folders, flattened
        destination = self.request.headers['jms.Dst']
        tenant = self.request.headers['usr.tenant']

        self.logger.info('Message %s for %s', message_id, tenant)
```

The channel option "Remove JMS headers" controls what reaches self.request.input. When it is on, the MQRFH2 bytes are stripped and self.request.input holds the bare message body, parsed if it is JSON. When it is off, the MQRFH2 bytes stay in front of the body and self.request.input holds the message as it arrived. The headers are exposed in self.request.headers either way.

## Replying to messages {#replying-to-messages}

When an incoming message names a reply-to queue, assigning to self.response.payload is all that is needed - the response is sent automatically to the reply-to queue at the reply-to queue manager, with its correlation ID set to the request's message ID.

```python
from zato.server.service import Service

class GetBalance(Service):

    def handle(self):
        account_id = self.request.json['account_id']

        # The assignment alone sends the reply
        self.response.payload = {'account_id': account_id, 'balance': 512.25}
```

## Sending messages to queues {#sending-messages-to-queues}

Create an IBM MQ outgoing connection in Dashboard and use self.ibm\_mq to send messages.

The connection is looked up by name, and .send() accepts strings, bytes, dicts, lists or any other JSON-serializable object.

```python
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # Get a connection by name
        conn = self.ibm_mq['my-publisher']

        # Send a string
        conn.send('Hello from Zato')
```

## Sending structured data {#sending-structured-data}

When you pass a dict or list, it is automatically serialized to JSON before sending.

```python
from zato.server.service import Service

class MyService(Service):

    def handle(self):
        conn = self.ibm_mq['my-publisher']

        conn.send({
            'event': 'order.created',
            'order_id': '12345',
            'customer': 'Acme Corp',
        })
```

## Connecting over TLS {#connecting-over-tls}

Both channels and outgoing connections support TLS. In the connection's Security tab, turn TLS on, pick a cipher spec such as ANY\_TLS12\_OR\_HIGHER and point the CA file to the PEM certificate of the authority that signed the queue manager's certificate. For mutual TLS, add the client certificate and private key PEM files too - no key databases or keystores need to be prepared, PEM files are all that is required.

## Testing with a local queue manager {#testing-with-a-local-queue-manager}

To test your connections without an existing IBM MQ installation, one command starts a complete queue manager in Docker, with default objects ready to use:

```bash
docker run -d --rm --name zato-mq -e LICENSE=accept -e MQ_QMGR_NAME=QM1 -e MQ_APP_PASSWORD=zato -p 1414:1414 icr.io/ibm-messaging/mq:latest
```

The queue manager takes about half a minute to start accepting connections after the container is up. Run the command below to check its status - it exits with an error while the queue manager is still starting and it exits cleanly, with no output, once connections can be made:

```bash
docker exec zato-mq chkmqready
```

The container's developer defaults map to connection details as below:

| Field | Value |
| --- | --- |
| Address | localhost:1414 |
| Queue manager | QM1 |
| MQ channel | DEV.APP.SVRCONN |
| Queue | DEV.QUEUE.1 (DEV.QUEUE.2 and 3 also exist) |
| Username | app |
| Password | The MQ\_APP\_PASSWORD value, here zato |

In Dashboard, create an IBM MQ outgoing connection with the details above, set the password through the connection's Change password menu option and click Ping to confirm that Zato can reach the queue manager.

For a complete round trip, add an IBM MQ channel pointing to the same DEV.QUEUE.1 queue and route it to a service of your choice. Each message sent through the outgoing connection will now be consumed by the channel and your service will be invoked with it - a full send and receive loop with no external systems needed.

When you are done, the container removes itself on stop:

```bash
docker stop zato-mq
```

## Learn more {#learn-more}

- [Development documentation](https://zato.io/docs/dev/) - The complete reference for writing services
- [Requests and responses](https://zato.io/docs/dev/request-response/) - What a service receives, what it returns and how both are structured
- [Integration examples](https://zato.io/docs/dev/examples/) - Ready-made code for the systems you are likely to connect to
- [IDE and debugging](https://zato.io/docs/dev/ide/) - Write services in the Dashboard or in your own editor
- [Data models](https://zato.io/docs/dev/model/) - Declare inputs and outputs and have them validated for you
- [In-depth API tutorial](https://zato.io/tutorials/main/01.html) - The full platform tutorial, from installation to production patterns
