Blog
WebSphere MQ is messaging middleware by IBM - a message queue server - and this post shows how to integrate with MQ from Python and Zato.
The article will go through a short process that will let you:
password (optional)
Install Zato
Everything in Zato revolves around re-usability and hot-reconfiguration - each individual piece of configuration can be changed on the fly, while servers are running, without restarts.
Note that the concepts below are presented in the context of WebSphere MQ but they apply to other connection types in Zato too.
It is usually most convenient to configure environments during development using the GUI Dashboard but afterwards this can be automated with enmasse, [API]/en/docs/3.2/index.html or command-line interface.
Once configuration is defined, it can be used from Zato services which in turn represent APIs that Zato clients invoke. Then, external applications, such as a Django or Flask, will connect using HTTP to a Zato service which will on their behalf send messages to MQ queues.
Let's use web-admin to define all the Zato objects required for MQ integrations. (Hint: web-admin by default runs on http://localhost:8183)
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
# Zato
from zato.server.service import Service
class MQSender(Service):
""" Sends all incoming messages as they are straight to a remote MQ queue.
"""
def handle(self):
# This single line suffices
self.out.wmq.send(self.request.raw_request, 'customer.updates', 'CUSTOMER.1')
In practice, a service such as the one above could perform transformation on incoming messages or read its destination queue names from configuration files but it serves to illustrate the point that literally 1 line of code is needed to send MQ messages
Let's create a channel service now - one that will act as a callback invoked for each message consumed off a queue:
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
# Zato
from zato.server.service import Service
class MQReceiver(Service):
""" Invoked for each message taken from a remote MQ queue
"""
def handle(self):
self.logger.info(self.request.raw_request)
But wait - if this is the service that is a callback one then how does it know which queue to get messages from?
That is the key point of Zato architecture - services do not need to know it and unless you really need it, they won't ever access this information.
Such configuration details are configured externally (for instance, in web-admin) and a service is just a black box that receives some input, operates on it and produces output.
In fact, the very same service could be mounted not only on WebSphere MQ ones but also on REST or AMQP channels.
Without further ado, let's create a channel in that case, but since this is an article about MQ, only this connection type will be shown even if the same principle applies to other channel types.
After clicking OK a lightweight background task will start to listen for messages pertaining to a given queue and upon receiving any, the service configured for channel will be invoked.
You can start as many channels as there are queues to consume messages from, that is, each channel = one input queue and each channel may declare a different service.
In many MQ environments the majority of applications will be based on Java JMS and Zato implements the underlying wire-level MQ JMS protocol to let services integrate with such systems without any effort from a Python programmer's perspective.
When creating connection definitions, merely check Use JMS and everything will be taken care of under the hood - all the necessary wire headers will be added or removed when it needs to be done.
It's worth to emphasize again that at no point are server restarts required to reconfigure connection details.
No matter how many definitions, outgoing connections, channels there are, and no matter of what kind they are (MQ or not), changing any of them will only update that very one across the whole cluster of Zato servers without interrupting other API services running concurrently.
Let's now check how to add a REST channel for the MQSender service thus letting Django and Flask push MQ messages.
Where to next? Start off with the [tutorial]/en/docs/3.2/tutorial/01.html), then consult the [documentation]/en/docs/3.2/index.html, there is a lot of information for all types of API and integration projects, and have a look at support options in case you need absolutely any sort of assistance!