Release Notes


20.5 Usage Scenarios

The MQSeries Functions can be used in a wide variety of scenarios. This section will review some of the more common scenarios, including Basic Messaging, Application Connectivity and Data Publication.

20.5.1 Basic Messaging

The most basic form of messaging with the MQSeries DB2 Functions occurs when all database applications connect to the same DB2 server. Clients may be local to the database server or distributed in a network environment.

In a simple scenario, Client A invokes the MQSEND function to send a user-defined string to the default service location. The MQSeries functions are then executed within DB2 on the database server. At some later time, Client B invokes the MQRECEIVE function to remove the message at the head of the queue defined by the default service and return it to the client. Again, the MQSeries functions to perform this work are executed by DB2.

Database clients can use simple messaging in a number of ways. Some common uses for messaging are:

The following scenario extends the simple scenario described above to incorporate remote messaging. That is, a message is sent between Machine A and Machine B. The sequence of steps is as follows:

  1. The DB2 Client executes an MQSEND call, specifying a target service that has been defined to represent a remote queue on Machine B.
  2. The MQSeries DB2 functions perform the actual MQSeries work to send the message. The MQSeries server on Machine A accepts the message and guarantees that it will deliver it to the destination defined by the service point definition and current MQSeries configuration of Machine A. The server determines that this is a queue on Machine B. It then attempts to deliver the message to the MQSeries server on Machine B, transparently retrying as needed.
  3. The MQSeries server on Machine B accepts the message from the server on Machine A and places it in the destination queue on Machine B.
  4. An MQSeries client on Machine B requests the message at the head of the queue.

20.5.2 Sending Messages

Using MQSEND, a DB2 user or developer chooses what data to send, where to send it, and when it will be sent. In the industry this is commonly called "Send and Forget," meaning that the sender just sends a message, relying on the guaranteed delivery protocols of MQSeries to ensure that the message reaches its destination. The following examples illustrate this.

Example 4: To send a user-defined string to the service point myPlace with the policy highPriority:

VALUES DB2MQ.MQSEND('myplace','highPriority','test')

Here, the policy highPriority refers to a policy defined in the AMI Repository that sets the MQSeries priority to the highest level and perhaps adjusts other qualities of service, such as persistence, as well.

The message content may be composed of any legal combination of SQL and user-specified data. This includes nested functions, operators, and casts. For instance, given a table EMPLOYEE, with VARCHAR columns LASTNAME, FIRSTNAME, and DEPARTMENT, to send a message containing this information for each employee in DEPARTMENT 5LGA you would do the following:

Example 5:

SELECT DB2MQ.MQSEND(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT)  
   FROM EMPLOYEE
   WHERE DEPARTMENT = '5LGA'

If this table also had an integer AGE column, it could be included as follows:

Example 6:

SELECT DB2MQ.MQSEND
      (LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' || char(AGE)) 
   FROM EMPLOYEE
   WHERE DEPARTMENT = '5LGA'

If the table EMPLOYEE had a column RESUME of type CLOB instead of an AGE column, then a message containing the information for each employee in DEPARTMENT 5LGA could be sent out with the following:

Example 7:

   SELECT DB2MQ.MQSEND
      (clob(LASTNAME) || ' ' || clob(FIRSTNAME) || ' ' ||
       clob(DEPARTMENT) || ' ' || RESUME))
   FROM EMPLOYEE
   WHERE DEPARTMENT = '5LGA'

Example 8:

Finally, the following example shows how message content may be derived using any valid SQL expression. Given a second table DEPT containing VARCHAR columns DEPT_NO and DEPT_NAME, messages can be sent that contain employee LASTNAME and DEPT_NAME:

Example 8:

SELECT DB2MQ.MQSEND(e.LASTNAME || ' ' || d.DEPTNAME) FROM EMPLOYEE e, DEPT d
   WHERE e.DEPARTMENT = d.DEPTNAME

20.5.3 Retrieving Messages

The MQSeries DB2 Functions allow messages to be either received or read. The difference between reading and receiving is that reading returns the message at the head of a queue without removing it from the queue, while receiving operations cause the message to be removed from the queue. A message retrieved using a receive operation can only be retrieved once, while a message retrieved using a read operation allows the same message to be retrieved many times. The following examples demonstrate this:

Example 8:

VALUES DB2MQ.MQREAD()

This example returns a VARCHAR string containing the message at the head of queue defined by the default service using the default quality of service policy. It is important to note that if no messages are available to be read, a null value will be returned. The queue is not changed by this operation.

Example 9:

VALUES DB2MQ.MQRECEIVE('Employee_Changes')

The above example shows how a message can be removed from the head of the queue defined by the Employee_Changes service using the default policy.

One very powerful feature of DB2 is the ability to generate a table from a user-defined (or DB2-provided) function. You can exploit this table function feature to allow the contents of a queue to be materialized as a DB2 table. The following example demonstrates the simplest form of this:

Example 10:

SELECT t.* FROM table ( DB2MQ.MQREADALL()) t 

This query returns a table consisting of all of the messages in the queue defined by the default service and the metadata about these messages. While the full definition of the table structure returned is defined in the Appendix, the first column reflects the contents of the message and the remaining columns contain the metadata. To return just the messages, the example could be rewritten:

Example 11:

SELECT t.MSG FROM table (DB2MQ.MQREADALL()) t

The table returned by a table function is no different from a table retrieved from the database directly. This means that you can use this table in a wide variety of ways. For instance, you can join the contents of the table with another table or count the number of messages in a queue:

Example 12:

SELECT t.MSG, e.LASTNAME 
   FROM table (DB2MQ.MQREADALL() ) t, EMPLOYEE e 
      WHERE t.MSG = e.LASTNAME

Example 13:

SELECT COUNT(*) FROM table (DB2MQ.MQREADALL()) t

You can also hide the fact that the source of the table is a queue by creating a view over a table function. For instance, the following example creates a view called NEW_EMP over the queue referred to by the service named NEW_EMPLOYEES:

Example 14:

CREATE VIEW NEW_EMP (msg) AS 
   SELECT t.msg FROM table (DB2MQ.MQREADALL()) t

In this case, the view is defined with only a single column containing an entire message. If messages are simply structured, for instance containing two fields of fixed length, it is straightforward to use the DB2 built-in functions to parse the message into the two columns. For example, if you know that messages sent to a particular queue always contain an 18-character last name followed by an 18-character first name, then you can define a view containing each field as a separate column as follows:

Example 15:

CREATE VIEW NEW_EMP2 AS
   SELECT left(t.msg,18) AS LNAME, right(t.msg,18) AS FNAME
   FROM table(DB2MQ.MQREADALL()) t

A new feature of the DB2 Stored Procedure Builder, the MQSeries Assist Wizard, can be used to create new DB2 table functions and views that will map delimited message structures to columns.

Finally, it is often desirable to store the contents of one or more messages into the database. This may be done using the full power of SQL to manipulate and store message content. Perhaps the simplest example of this is:

Example 16:

INSERT INTO MESSAGES 
   SELECT t.msg FROM table (DB2MQ.MQRECEIVEALL()) t

Given a table MESSAGES, with a single column of VARCHAR(2000), the statement above will insert the messages from the default service queue into the table. This technique can be embellished to cover a very wide variety of circumstances.

20.5.4 Application-to-Application Connectivity

Application integration is a common element in many solutions. Whether integrating a purchased application into an existing infrastructure or just integrating a newly developed application into an existing environment, we are often faced with the task of glueing a heterogeneous collection of subsystems together to form a working whole. MQSeries is commonly viewed as an essential tool for integrating applications. Accessible in most hardware, software, and language environments, MQSeries provides the means to interconnect a very heterogeneous collection of applications.

This section will discuss some application integration scenarios and how they may be used with DB2. As the topic is quite broad, a comprehensive treatment of Application Integration is beyond the scope of this work. Therefore, the focus is on just two simple topics: Request/Reply communications, and MQSeries Integrator and Publish/Subscribe.

20.5.4.1 Request/Reply Communications

The Request/Reply (R/R) communications method is a very common technique for one application to request the services of another. One way to do this is for the requester to send a message to the service provider requesting some work to be performed. Once the work has been completed, the provider may decide to send results (or just a confirmation of completion) back to the requestor. But using the basic messaging techniques described above, there is nothing that connects the sender's request with the service provider's response. Unless the requester waits for a reply before continuing, some mechanism must be used to associate each reply with its request. Rather than force the developer to create such a mechanism, MQSeries provides a correlation identifier that allows the correlation of messages in an exchange.

While there are a number of ways in which this mechanism could be used, the simplest is for the requestor to mark a message with a known correlation identifier using, for instance, the following:

Example 17:

DB2MQ.MQSEND ('myRequester','myPolicy','SendStatus:cust1','Req1')

This statement adds a final parameter Req1 to the MQSEND statement from above to indicate the correlation identifier for the request.

To receive a reply to this specific request, use the corresponding MQRECEIVE statement to selectively retrieve the first message defined by the indicated service that matches this correlation identifier as follows:

Example 18:

DB2MQ.MQRECEIVE('myReceiver','myPolicy','Req1')

If the application servicing the request is busy and the requestor issues the above MQRECEIVE before the reply is sent, then no messages matching this correlation identifier will be found.

To receive both the service request and the correlation identifier a statement like the following is used:

Example 19:

SELECT msg, correlid FROM
           table (DB2MQ.MQRECEIVEALL('aServiceProvider','myPolicy',1)) t

This returns the message and correlation identifier of the first request from the service aServiceProvider.

Once the service has been performed, it sends the reply message to the queue described by aRequester. Meanwhile, the service requester could have been doing other work. In fact, there is no guarantee that the initial service request will be responded to within a set time. Application level timeouts such as this must be managed by the developer; the requester must poll to detect the presence of the reply.

The advantage of such time-independent asynchronous processing is that the requester and service provider execute completely independently of one another. This can be used both to accommodate environments in which applications are only intermittently connected and more batch-oriented environments in which multiple requests or replies are aggregated before processing. This kind of aggregation is often used in data warehouse environments to periodically update a data warehouse or operational data store.

20.5.4.2 Publish/Subscribe

Simple Data Publication

Another common scenario in application integration is for one application to notify other applications about events of interest. This is easily done by sending a message to a queue monitored by another application. The contents of the message can be a user-defined string or can be composed from database columns. Often a simple message is all that needs to be sent using the MQSEND function. When such messages need to be sent concurrently to multiple recipients, the Distribution List facility of the MQSeries AMI can be used.

A distribution list is defined using the AMI Administration tool. A distribution list comprises a list of individual services. A message sent to a distribution list is forwarded to every service defined within the list. This is especially useful when it is known that a few services will always be interested in every message. The following example shows sending of a message to the distribution list interestedParties:

Example 20:

DB2MQ.MQSEND('interestedParties','information of general interest');

When more control over the messages that particular services should receive is required, a Publish/Subscribe capability is needed. Publish/Subscribe systems typically provide a scalable, secure environment in which many subscribers can register to receive messages from multiple publishers. To support this capability the MQPublish interface can be used, in conjunction with MQSeries Integrator or the MQSeries Publish/Subscribe facility.

MQPublish allows users to optionally specify a topic to be associated with a message. Topics allow a subscriber to more clearly specify the messages to be accepted. The sequence of steps is as follows:

  1. An MQSeries administrator configures MQSeries Integrator publish/subscribe capabilities.
  2. Interested applications subscribe to subscription points defined by the MQSI configuration, optionally specifying topics of interest to them. Each subscriber selects relevant topics, and can also utilize the content-based subscription techniques of MQSeries Integrator V2. It is important to note that queues, as represented by service names, define the subscriber.
  3. A DB2 application publishes a message to the service point Weather. The messages indicates that the weather is Sleet with a topic of Austin, thus notifying interested subscribers that the weather in Austin is Sleet.
  4. The mechanics of actually publishing the message are handled by the MQSeries functions provided by DB2. The message is sent to MQSeries Integrator using the service named Weather.
  5. MQSI accepts the message from the Weather service, performs any processing defined by the MQSI configuration, and determines which subscriptions it satisfies. MQSI then forwards the message to the subscriber queues whose criteria it meets.
  6. Applications that have subscribed to the Weather service, and registered an interest in Austin will receive the message Sleet in their receiving service.

To publish this data using all the defaults and a null topic, you would use the following statement:

Example 21:

SELECT DB2MQ.MQPUBLISH
                  (LASTNAME || ' ' || FIRSTNAME || ' ' || 
                   DEPARTMENT|| ' ' ||char(AGE)) 
   FROM EMPLOYEE 
      WHERE DEPARTMENT = '5LGA'

Fully specifying all the parameters and simplifying the message to contain only the LASTNAME the statement would look like:

Example 22:

SELECT DB2MQ.MQPUBLISH('HR_INFO_PUB', 'SPECIAL_POLICY', LASTNAME, 
   'ALL_EMP:5LGA', 'MANAGER') 
   FROM EMPLOYEE
      WHERE DEPARTMENT = '5LGA'

This statement publishes messages to the HR_INFO_PUB publication service using the SPECIAL_POLICY service. The messages indicate that the sender is the MANAGER topic. The topic string demonstrates that multiple topics, concatenated using a ':' can be specified. In this example, the use of two topics allows subscribers to register for either ALL_EMP or just 5LGA to receive these messages.

To receive published messages, you must first register your interest in messages containing a given topic and indicate the name of the subscriber service that messages should be sent to. It is important to note that an AMI subscriber service defines a broker service and a receiver service. The broker service is how the subscriber communicates with the publish/subscribe broker and the receiver service is where messages matching the subscription request will be sent. The following statement registers an interest in the topic ALL_EMP.

Example 23:

DB2MQ.MQSUBSCRIBE('aSubscriber', 'ALL_EMP')

Once an application has subscribed, messages published with the topic ALL_EMP will be forwarded to the receiver service defined by the subscriber service. An application can have multiple concurrent subscriptions. To obtain the messages that meet your subscription, any of the standard message retrieval functions can be used. For instance if the subscriber service aSubscriber defines the receiver service to be aSubscriberReceiver then the following statement will non-destructively read the first message:

Example 24:

DB2MQ.MQREAD('aSubscriberReceiver')

To determine both the messages and the topics that they were published under, you would use one of the table functions. The following statement would receive the first five messages from aSubscriberReceiver and display both the message and the topic:

Example 25:

SELECT t.msg, t.topic
   FROM table (DB2MQ.MQRECEIVEALL('aSubscriberReceiver',5)) t

To read all of the messages with the topic ALL_EMP, you can leverage the power of SQL to issue:

Example 26:

SELECT t.msg FROM table (DB2MQ.MQREADALL('aSubscriberReceiver')) t 
   WHERE t.topic = 'ALL_EMP'
Note:
It is important to realize that if MQRECEIVEALL is used with a constraint then the entire queue will be consumed, not just those messages published with topic ALL_EMP. This is because the table function is performed before the constraint is applied.

When you are no longer interested in subscribing to a particular topic you must explicitly unsubscribe using a statement such as:

Example 27:

DB2MQ.MQUNSUBSCRIBE('aSubscriber', 'ALL_EMP')

Once this statement is issued the publish/subscribe broker will no longer deliver messages matching this subscription.

Automated Publication

Another important technique in database messaging is automated publication. Using the trigger facility within DB2, you can automatically publish messages as part of a trigger invocation. While other techniques exist for automated data publication, the trigger-based approach allows administrators or developers great freedom in constructing the message content and flexibility in defining the trigger actions. As with any use of triggers, attention must be paid to the frequency and cost of execution. The following examples demonstrate how triggers may be used with the MQSeries DB2 Functions.

The example below shows how easy it is to publish a message each time a new employee is hired. Any users or applications subscribing to the HR_INFO_PUB service with a registered interest in NEW_EMP will receive a message containing the date, name and department of each new employee.

Example 28:

CREATE TRIGGER new_employee AFTER INSERT ON employee REFERENCING NEW AS n
      FOR EACH ROW MODE DB2SQL
      VALUES DB2MQ.MQPUBLISH('HR_INFO_PUB&',  'NEW_EMP', 
      current date || ' ' || LASTNAME || ' ' || DEPARTMENT)


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]