BEA Logo BEA MessageQ Release 5.0

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   MessageQ Doc Home   |   Programmer's Guide   |   Previous Topic   |   Next Topic   |   Contents   |   Index

Sending and Receiving BEA MessageQ Messages

 

This chapter covers the following topics:

Overview

BEA MessageQ enables applications to exchange information in the form of messages using the following PAMS API functions:

BEA MessageQ provides applications with three distinct ways to send and receive messages using:

This variety of methods for sending and receiving messages enables application developers to choose the type of messaging that best suits the application's present and future needs.

The Basics of Sending and Receiving Messages

To send or receive messages, an application must be attached to at least one message queue on the message queuing bus. This queue serves as the application's primary queue-the main mailbox in which it receives information. To attach to a queue, the application must successfully execute the pams_attach_q function. Once attached, the application can send a message to a known target queue address using the pams_put_msg function.

BEA MessageQ offers the following functions for receiving messages:

When the application is finished sending or receiving messages, it detaches from the message queuing bus using the pams_detach_q function.

Refer to the programming examples distributed as part of the BEA MessageQ kit to view sample programs for each of these PAMS API functions.

Note: If you are new to using BEA MessageQ, you should begin by reading the Introduction to Message Queuing. This introduction explains the BEA MessageQ concepts that you need to understand before you can begin successfully developing applications.

Sending and Receiving Message Buffers

Sending and receiving information as static message buffers is the easiest way to exchange information using BEA MessageQ. A static message buffer is a predefined, static data structure. Often, an application uses a version number to identify the structure layout. So, for example, when a payroll system sends employee payroll information using version 1 of its payroll data structure, the receiving application can interpret each field of data in the buffer because it knows the definition of the version 1 payroll data structure.

Passing information using a static data structure in the form of a message buffer is the fastest way to exchange information between BEA MessageQ applications. Because the data structure definition is known to both the sending and receiving applications, no interpretation is required. Therefore, processing of information between both sender and receiver programs is faster.

See the following topics for information on how to:

How to Send BEA MessageQ Messages

When programming BEA MessageQ applications, there are four basic functions that are used in the sending messages. The first function called is pams_attach_q. This function is used to connect your BEA MessageQ applications to the BEA MessageQ message queuing bus. Attaching to the message queuing bus provides the application with a default queue address for receiving the reply message and a means to share information with all other BEA MessageQ applications.

The example in Listing 1-1 illustrates how to attach to a queue by name. The queue name must be defined appropriately in your group initialization file.

Listing 1-1 Example of Attaching to a Queue by Name


#include <stdio.h>
#include <string.h>
#include "p_entry.h"
#include "p_return.h"
#include "p_symbol.h"
.
.
.
int32 attach_mode;
int32 dmq_status;
int32 q_name_len;
int32 q_type;
char q_name[12];
q_address my_primary_queue;
strcpy(q_name,"example_q_1");
attach_mode = PSYM_ATTACH_BY_NAME;
q_type = PSYM_ATTACH_PQ;
q_name_len = (int32)sizeof( q_name );
dmq_status = pams_attach_q(
&attach_mode,
&my_primary_queue,
&q_type,
q_name,
&q_name_len,
(int32 *) 0, /* Use default name space */
(int32 *) 0, /* No name space list len */
(int32 *) 0, /* Timeout */
(char *) 0, /* Reserved by MessageQ */
(char *) 0 ); /* Reserved by MessageQ */

  if ( dmq_status == PAMS__SUCCESS )
printf( "Attached successfully to queue: \"%s\".\n", q_name );
else
printf( "Error attaching to queue: \"%s\"; status returned
is: %ld\n", q_name, dmq_status );
.
.
.


After attaching to a queue, the application uses the pams_put_msg function to send a message to the queue address of the receiver program. Before the message can be sent, the application needs to provide application data in a message buffer. The data structure of the message buffer is predefined so that both the sending and the receiving application can interpret the message contents.

The example in Listing 1-2 illustrates how to send a number of messages to a queue.

Listing 1-2 Example of Sending Messages to a Queue


    int32         attach_mode;
int32 dmq_status;
int32 q_name_len;
int32 q_type;
int32 timeout;
short class;
short type;
short msg_size;
char delivery;
char priority;
char uma;
static char msg_area[18];
static char q_name[12];
q_address my_queue;
struct PSB put_psb;
.
.
.
/*
** Put a message into my own queue
*/
priority = 0;
class = 0;
type = 0;
delivery = PDEL_MODE_NN_MEM;
msg_size = (short) strlen( msg_area );
timeout = 50; /* 5 seconds */
uma = PDEL_UMA_DISCL;

dmq_status = pams_put_msg(
msg_area,
&priority,
&my_queue,
&class,
&type,
&delivery,
&msg_size,
&timeout,
&put_psb,
&uma,
(q_address *) 0,
(char *) 0,
(char *) 0,
(char *) 0 );

   if ( dmq_status == PAMS__SUCCESS )
printf( "\n\tPut successfully to queue: \"%s\".\n", q_name );
else
printf( "\nError sending to queue: \"%s\"; status returned
is: %ld\n", q_name, dmq_status );
.
.
.


BEA MessageQ applications use the pams_get_msg function to read messages from a queue. Because both sending and receiving programs use the predefined buffer structure, the receiving application can interpret the message.

When a BEA MessageQ application is finished, the pams_detach_q is called to disconnect the program from the message queuing bus.

Static data structures limit the flexibility of applications to adapt to changing business conditions. To change the data structure, both the sender and receiver programs must be recoded to send and interpret the new message correctly. In addition, all production applications must be shut down and the newer versions started up for the change to take affect. Such large changes to an integrated application environment often result in synchronization problems where some applications have not yet been restarted using the new message format. This leads to processing errors until all applications are using the same version of the message data structure.

Another limitation in using static message buffers is that data is passed "as is" from one system to another in the network. So, if a message must be delivered between two computers that use different byte orders, the application must perform the byte order translation to ensure that the data is interpreted properly by the target application. BEA MessageQ does not perform data marshalling between systems with unlike hardware data formats when messages are sent using the static message buffer approach.

Prior to BEA MessageQ Version 4.0, the only way to send a message was to use the predefined message data structure which allowed messages to be as large as 32 kilobytes. If either the sending or receiving data structure needed to change the message structure, both sending and receiving applications were programmed to use the new message structure. For this change to take effect, both sending and receiving programs needed to be reloaded.

How to Send Large Messages

BEA MessageQ enables applications to send buffer-style and FML-style messages up to 4MB in size. For FML-style messaging no differences in approach are required to send small or large messages. However, use the following procedure when sending and receiving buffer-style messages larger than 32K.

To send a large buffer-style message, applications still use the pams_put_msg function. Most arguments to this call are specified in the same way for large and small messages. However, the following list describes the arguments that are specified differently for large messages:

To retrieve a large buffer-style message from a queue, you still use the pams_get_msg, pams_get_msgw, or the pams_get_msga functions. To retrieve a large message from an auxiliary journal, use the pams_read_jrn function. The following arguments are supplied to these functions to read large messages:

These functions return the actual size of the message written to the message buffer in the large_size argument.

A sample program illustrating how to send a large message called x_putbig.c is contained in the programming examples directory of your media kit.

Receiving Messages Using Message Pointers

Receiving applications can use message pointers to allow for automatic buffer reallocation when the buffer received is larger than the buffer allocated. (Message pointers are also required for processing self-describing messages based on FML buffers. See Self-Describing Messaging with FML for more information.)

To retrieve a buffer-style message from a queue using pams_get_msg and pointers:

If the message received will not fit in the allocated space or if the pointer is NULL, the buffer is reallocated, the pointer to the new buffer is returned in the msg_area, and its length is returned in the large_area_len arguments.

When the message is retrieved from the queue:

Self-Describing Messaging with FML

Self-describing messaging using Field Manipulation Language (FML) is new in BEA MessageQ Version 5.0. FML-based messaging replaces the SDM capabilities provided in BEA MessageQ V4.0. While basic information on FML is included in this document, see the BEA MessageQ FML Programmer's Guide and the BEA MessageQ Reference Manual for more information on FML.

FML is a set of C language functions for defining and manipulating storage structures called fielded buffers, that contain attribute-value pairs in fields. The attribute is the field's identifier, and the associated value represents the field's data content.

Using FML, applications construct messages containing both the message content and the information needed by the receiver program to understand what is in the message. The receiver program dynamically interprets the contents of the message by "decoding" some or all of the data contained in it. Message pointers are used when a receiving application retrieves an FML-style message from a message queue.

Using FML buffers, applications do not interact with a message structure. Instead, sender programs encode the contents of the message using the appropriate FML function. Each field in the message has a value (the content) and a tag (identifier). When an application retrieves an FML message, the content is not directly visible. The receiver program must use FML functions to interpret the contents of the message that are appropriate to its operation.

Because FML messages contain information about how to interpret the message contents, self-describing messaging provides applications with more flexibility in adding fields to a message or changing the message contents without necessarily needing to recode all of the receiving applications. In addition, FML performs data marshaling of data formats between computer systems with unlike hardware data formats.

How Self-Describing Messaging Works

FML messages, which are accessed by a pointer, contain tagged values that are manipulated by specific FML functions. When you code, you build the message buffer using assignments inside the message data structure which you have defined. FML uses the following fielded buffer structure:

Figure 1-1 Fielded Buffer Structure

In the above figure, the message structure contains pairs of attributes and values. Each field is labeled with an integer that combines information about the data type of the accompanying field with a unique identifying number. The label is called a field identifier or fldid. For variable-length items, fldid is followed by a length indicator. The buffer can be represented as a sequence of fldid/data pairs or fldid/length/data triples for variable-length items.

Benefits of Using FML

There are several advantages to using FML. These advantages are as follows:

FML manages data transformation so that an FML message can be interpreted properly on any platform. Figure 1-1 illustrates how using fielded buffers creates a formatted message that replaces all platform-dependent compiler assignments through an API, which has decoupled and hidden all the machine, operating system, and platform dependencies. It has also properly encoded the message so that it can be safely transported from platform to platform in a heterogeneous environment. Furthermore, it protects applications from message structure changes.

For example, suppose you have an application running on a Hewlett-Packard machine and a Compaq machine and the message data has a little endian data format. When messages are sent to the Compaq machine from the Hewlett-Packard machine, a conversion from little endian to big endian data format must take place. This is handled by encoding the little endian format and converting it to a platform independent format. Then, the platform independent format is decoded into the big endian format for the Compaq machine.

Performance Considerations When Using FML

One performance consideration in using FML is that it uses a larger message size to deliver the same amount of user data and can take longer to pass back and forth between machines. The message size is larger because the message contains both the information and a description of the information, encoded in a platform-independent manner.

For example, consider a message that is 100 characters. With a defined message buffer, the message is only 101 bytes using a C message structure. In a worst case scenario, the FML message size could be 800 bytes. Each of the original 100 bytes requires 1 byte of data and 4 bytes of identifier. Because each byte of data must be aligned on word boundaries for platform independence, each byte requires three additional padding bytes.

A more efficient way to encode character data is to use an array. You can encode the 100 bytes as an array of 100 bytes. With an array, the padding necessary to accomplish word alignment is not needed and the tag is present only once. Using this approach, the actual size needed is 108 bytes (including the tag and length).

You may be able to structure the application to use the larger FML message only when needed and a message buffer at other times. For more information on this technique, see the Designing Applications to Use a Mixed Messaging Environment topic.

An additional performance consideration is the time required to encode and decode information when exchanging messages between platforms having different data formats.

Designing Applications to Use a Mixed Messaging Environment

A mixed messaging environment is an environment where you want to exchange static buffer messages and FML messages in the same application. If you are programming an application to use both kinds of messages, consider having your application use two queues-one queue for buffer-style messages and another queue for FML messages. By designing your application this way, you guarantee that your application does not dequeue an FML message by mistake.

Note that for performance reasons, it might be better to modify the buffer structure and redistribute all software than to use a mixed messaging environment. This may be the recommended approach when your applications are close geographically and there is a convenient time to update software.

How to Send an FML Message

When sending FML messages, you code in a similar manner as with a message buffer. However, the main difference is that messages are manipulated using message pointers rather than using the actual message buffer. The message pointer is provided to pams_put_msg as the first argument (msg_area). To code an FML message, you must add the following steps to your program logic after attaching to a queue:

  1. Define field identifiers and map them to field names.

  2. Build messages using the appropriate FML functions.

  3. Send the message. To use an FML message pointer when sending a message, the sender program specifies the symbol PSYM_MSG_FML as the msg_size argument in the pams_put_msg function.

  4. Once your application is done using the FML message, delete the FML message using Ffree32() to prevent memory leaks.

A sample program called x_fml.c which illustrates how to send and receive FML messages is distributed as part of your media kit.

Defining Field Identifiers

FML message fields are tagged with field identifiers. Each tag implicitly defines the data type of the information it is associated with. This guarantees that the sender and the receiver of an FML message have an explicit agreement about the kind of information they exchange. The collection of tags builds a kind of message dictionary.

The following table describes the tag data type symbols as defined in fml32.h:

Data Type

Symbol

short int

FML_SHORT

long int

FML_LONG

character

FML_CHAR

single-precision float

FML_FLOAT

double-precison float

FML_DOUBLE

string, null terminated

FML_STRING

character array

FML_ARRAY

Fields are usually referred to by their field identifier (fldid), an integer. This allows you to reference fields in a program without using the field name.

Identifiers are assigned (mapped) to field names in the following ways:

A typical application may use one or both of these methods.

Building the FML Message

The FML API provides functions to place tagged values in a fielded buffer accessed with its pointer. A variety of functions are provided to support a large number of buffer operations.

Any field in a fielded buffer can occur more than once. Many FML functions take an argument that specifies which occurrence of a field is to be retrieved or modified. If a field occurs more than once, the first occurrence is numbered 0, and additional occurrences are numbered sequentially.

The example in Listing 1-3 shows a program which builds a message with the queue id and time stamp. The message is then put into a message queue.

Listing 1-3 Example of Building a Fielded Buffer


/* applications fields */
#include myFields.h"
FBFR32 *fbfr;
fbfr = Falloc32(10,100);
Fadd32(fbfr, QID, 0, &qid, 0);
Fadd32(fbfr, TSTAMP, 0, &timestamp, 0);


Note that FML provides data transparency. That is to say that your application does not know nor need to know how any data values are stored in the message. The FML and PAMS API functions handle this for your application.

Sending the FML Message

After creating a pointer and building the message, you can send the message to the target queue. To send an FML buffer, the sender program specifies the symbol PSYM_MSG_FML as the msg_size argument to the pams_put_msg function. The system verifies that the buffer is an FML32 buffer. If the buffer is not an FML32 buffer, the pams_put_msg call will fail and return PAMS__NOTFLD.

The code fragment example in Listing 1-4 sends the FML message. The previously encoded message is contained in the msg_area argument.

Listing 1-4 Example of Sending an FML message


/*  Sends the message identified by the pointer. The symbol   */
/* PSYM_MSG_FML_ in the msg_size argument indicates that */
/* the message is a pointer to an FML buffer. */

/* Define any variables needed to the put function here. */

msg_size = PSYM_MSG_FML;
.
.
.
dmq_status = pams_put_msg(
(char *) fbfr,
&priority,
&my_queue,
&class,
&type,
&delivery,
&msg_size,
&timeout,
&put_psb,
&uma,
(q_address *) 0,
(char *) 0,
(char *) 0,
(char *) 0, );

If ( dmq_status == PAMS__SUCCESS )
printf ( "Message pointer successfully put to the queue");
else
printf ( "Error putting message to queue");
.
.
.


How to Receive an FML Message

When receiving FML messages, you code in a similar manner as with a buffer-style message. However, you must add the following steps to your program logic after attaching to a queue:

  1. Include the predefined field identifier definitions to your code to guarantee that both sending and receiving applications are using the same definitions.

  2. Create a pointer to a pointer to dynamically allocated space using Falloc or malloc and Finit.

  3. Set large_area_len to the length of the allocated space or to 0 if it is NULL.

  4. Read the message from the queue. The receiver program determines whether the message is a pointer to an FML buffer pointer by reading the endian field in the show_buffer argument of the pams_get_msg or pams_get_msgw function. If this field contains the symbol PSYM_FML, the message is an FML buffer.

  5. Access the message fields using the appropriate FML API functions.

  6. Delete or reuse the message pointer to prevent memory leaks.

    Note: When an FML message is received, the endian field of the show_buffer argument returned by the pams_get_msg or pams_get_msgw functions is set to PSYM_FML.

Reading the Message from the Queue

To read a message from a queue, use the pams_get_msg function after you have included the tag definitions and created a message pointer. The code fragment example in Listing 1-5 creates a message handle and gets the message:

Listing 1-5 Example of Reading an FML Message


/*  Include the predefined field identifier definition        */

#include "myfields.h";
FBFR32 *fbfr;
FBFR32 **pfbfr;

/* Read the message identified by the pointer. The symbol */
/* PSYM_MSG_BUFFER_PTR in the len_data argument indicates that */
/* the message is a pointer and not a message buffer. */


/* Define any variables needed for the get function here. */

len_data = PSYM_MSG_BUFFER_PTR;
pfbfr = &fbfr;
.
.
.
dmq_status = pams_get_msg(
(char *) pfbfr,
&priority,
&msg_source,
&class,
&type,
&msg_area_len,
&msg_len,
(int32 *)&sel_filter,
(struct PSB *) 0,
(struct show_buffer *) 0,
&show_buffer_len
&large_area_len,
&large_size,
(char *) 0, );

If ( dmq_status == PAMS__SUCCESS )
printf ( "Message pointer successfully read");
printf ( "Error reading message");
.
.
.


Interpreting the Message

After your application creates a message pointer and gets the message, it can interpret the message. Your application can use FML API functions to manipulate the fielded buffer.

Exchanging Messages Between BEA MessageQ and BEA TUXEDO or BEA M3

BEA MessageQ V5.0 include a messaging bridge that allows the exchange of messages between BEA MessageQ V5.0 and BEA TUXEDO V6.4 or BEA M3 2.1. BEA MessageQ applications can send a message using pams_put_msg that a TUXEDO application can retrieve through a call to tpdequeue. TUXEDO applications can send a message using tpenqueue that a BEA MessageQ application can retrieve through a call to pams_get_msg(w). In addition, a BEA MessageQ application can invoke a TUXEDO service using pams_put_msg. It is also possible for a TUXEDO application to use tpenqueue to put a message on a queue and to use tpdequeue to retrieve a message from a queue.

This exchange of messages is made possible by two TUXEDO servers that are included in the BEA MessageQ kit and that run on the same machine as BEA MessageQ: TMQUEUE_BMQ and TMQFORWARD_BMQ.

TMQUEUE_BMQ redirects TUXEDO tpenqueue requests to a BEA MessageQ queue where they can be retrieved with pams_get_msg(w). TMQUEUE_BMQ also redirects pams_put_msg or tepenqueue requests to TUXEDO where they can be retrieved with tpdequeue.

TMQFORWARD_BMQ listens on specified BEA MessageQ queues and forwards pams_put_msg requests to a TUXEDO service. It also puts a reply or failure message on the sender's response queue.

The target queue and service are defined when TMQUEUE_BMQ and TMQFORWARD_BMQ are configured. This ensures that message exchange between BEA MessageQ and TUXEDO is transparent to the application.

Figure 1-2 illustrates message exchange between MessageQ and TUXEDO.

Figure 1-2 Message Exchange Between MessageQ and TUXEDO

Enabling the Messaging Bridge

The TMQUEUE_BMQ and TMQFORWARD_BMQ servers are part of the BEA MessageQ kit and are installed when BEA MessageQ is installed. During the installation procedure, you are prompted to choose one of the following installation options for BEA MessageQ and TUXEDO integration:

install on top of BEA TUXEDO V6.4
install on top of BEA M3 2.1
install without BEA TUXEDO

If you choose to install on top of BEA TUXEDO V6.4 or BEA M3 2.1, the applicable files for the TMQUEUE_BMQ and TMQFORWARD_BMQ servers are installed on your system. If you install without BEA TUXEDO, the TMQUEUE_BMQ and TMQFORWARD_BMQ servers are not installed on your system. See the installation and configuration documentation specific to your platform for detailed installation and configuration instructions.

Once the TMQUEUE_BMQ and TMQFORWARD_BMQ servers are installed, the system administrator enables message enqueuing and dequeuing for the application by specifying the servers as application servers in the *SERVERS section of the TUXEDO ubbconfig file. See the TMQUEUE_BMQ and TMQFORWARD_BMQ reference pages in the BEA MessageQ Reference Manual for detailed information on the server configuration syntax.

Data Transformation Between BEA MessageQ and TUXEDO

One of the primary functions of the TMQUEUE_BMQ and TMQFORWARD_BMQ servers is to perform data and semantic transformations between the BEA MessageQ PAMS API and the TUXEDO ATMI API. This section describes how data is handled when it is exchanged between BEA MessageQ and TUXEDO. The data transformations are the same for the TMQUEUE_BMQ and TMQFORWARD_BMQ servers.

Data Types

BEA MessageQ passes data as static buffers or as FML32 buffers using the msg_area argument of the pams_put_msg function. TUXEDO handles a wide range of data types including CARRAY, STRING, and FML32 using the data argument of the tpenqueue function.

When a message is enqueued using tpenqueue, the TMQUEUE_BMQ server preserves TUXEDO data type information for use by a subsequent call by tpdequeue. If machines of different types perform the tpenqueue and tpdequeue calls, and the data type is not FML32 or CARRAY, the data is transformed to CARRAY and a message is written to the TUXEDO user log. (Machine types are specified in the TUXEDO ubbconfig file in the *MACHINE section using the TYPE attribute.)

When a message is enqueued using pams_put_msg and dequeued with tpdequeue, static buffer data is transformed to CARRAY, and FML32 buffers are passed without transformation.

When a message is dequeued using pams_get_msg(w), FML32 buffers are passed without transformation and all other data types are transformed to binary large objects.

Data Size and Length

BEA MessageQ defines the size and length of messages using the following arguments to pams_put_msg: msg_size, large_size, msg_area_len, len_data, and large_area_len. TUXEDO uses the len argument to tpenqueue to determine length.

BEA MessageQ limits the size of messages to a maximum of 4 MB. In addition, BEA MessageQ can be configured to set a smaller maximum message size. If BEA MessageQ is configured for a 4 MB maximum size, and a message larger than 4 MB is enqueued using tpenqueue, a TPEDIAGNOSTIC/QMESYSTEM error is generated. If BEA MessageQ is configured for a smaller maximum message size, and a message larger than the configured size is enqueued using tpenqueue, there is no way to detect the message size error.

When messages are dequeued using tpdequeue, the TMQUEUE_BMQ server handles buffer size discrepancies and returns a full, complete buffer to the calling application.

Timeouts

BEA MessageQ specifies a timeout per operation using the timeout argument of the pams_put_msg function. TUXEDO specifies system-wide blocking timeouts using the following flags: ctl.flags:TPQWAIT, flags:TPNOBLOCK, and flags:TPNOTIME.

When the TMQUEUE_BMQ server handles a message from a BEA MessageQ queue based on a call to tpenqueue or tpdequeue, the timeout is the value set by the TMQUEUE_BMQ command line option -t, or the default timeout if none is specified.

When a message is enqueued using pams_put_msg and is intended for a TUXEDO application, the timeout is the value set by timeout argument of the pams_put_msg function, within any limitations set by the BEA MessageQ delivery mode.

Priorities

BEA MessageQ specifies priority using the priority argument to the pams_put_msg function. TUXEDO specifies priority using the ctl.flags:TPQPRIORITY and ctl.priority flags. BEA MessageQ message priorities range from 0 to 99 with 99 being the highest priority. TUXEDO priorities range from 1 to 100 with 100 being the highest priority and the default being 50. BEA MessageQ requires that the priority argument of the pams_put_msg function be specified when the message is enqueued. TUXEDO uses the default priority if the control structure flag ctl.flags:TPQPRIORITY is not set.

Message priorities are either increased or decreased by one depending on where the message originates. Messages originating from TUXEDO are placed on the BEA MessageQ queue with a priority of n-1 where n is the priority assigned by TUXEDO. Messages originating from BEA MessageQ will dequeued by TUXEDO with a priority of n+1, where n is the priority assigned by BEA MessageQ.

Target, Queue Space and Queue Name

There are two areas that must be resolved when mapping the BEA MessageQ target and TUXEDO queue space and queue name:

TUXEDO Queue Space to BEA MessageQ Group Name

BEA MessageQ uses the target argument of the pams_put_msg function to specify the target queue address for a message. TUXEDO uses the qspace and qname arguments of the tpenqueue and tpdequeue functions to specify the target queue for a message

The TUXEDO queue space name must be the name of a service advertised by TMQUEUE_BMQ or TMQFORWARD_BMQ. The service name maps directly to a BEA MessageQ group. By default, TMQUEUE_BMQ and TMQFORWARD_BMQ automatically offer services named "TMQUEUE_BMQ" and "TMQFORWARD_BMQ" unless the -s command line option is specified. These default services map to the BEA MessageQ group to which they are attached, as specified by the -g command line option.

The function name to which services should be mapped in TMQUEUE. Each entry in the TUXEDO ubbconfig file for a TMQUEUE_BMQ or TMQFORWARD_BMQ server should be configured with a different alias for the default function name using the TUXEDO -s command line option. For example, one configuration of TMQUEUE may be named Payroll, while another is named Sales. This provides a way to precisely specify a BEA MessageQ entry point for a particular tpenqueue or tpdequeue call. If multiple instances of the same advertised service are running, TUXEDO performs load balancing and data dependent routing to determine which server handles the request.

The following example illustrates different TMQUEUE_BMQ configurations:

*GROUPS
TMQUEUE_BMQGRPHQMGR GRPNO=1
TMQUEUE_BMQGRPHQPLEBE GRPNO=2
TMQUEUE_BMQGRPREMOTENA GRPNO=3
TMQUEUE_BMQGRPREMOTEEUROPE GRPNO=4

*SERVERS
TMQUEUE_BMQ SRVGRP="TMQUEUE_BMQGRPHQMGR" SRVID=1000 RESTART=Y
GRACE=0 CLOPT="-s Payroll:TMQUEUE -s
Promote:TMQUEUE -- -b 5 -g 7"
TMQUEUE_BMQ SRVGRP="TMQUEUE_BMQGRPHQPLEBE" SRVID=1000 RESTART=Y
GRACE=0 CLOPT="-s Payroll:TMQUEUE -s
Promote:TMQUEUE -- -b 5 -g 10"
TMQUEUE_BMQ SRVGRP="TMQUEUE_BMQGRPREMOTENA" SRVID=2002 RESTART=Y
GRACE=0 CLOPT="-s Sales:TMQUEUE -- -b 5 -g 42"
TMQUEUE_BMQ SRVGRP="TMQUEUE_BMQGRPREMOTEEUROPE" SRVID=2002
RESTART=Y GRACE=0 CLOPT="-s Sales:TMQUEUE -- -b 12 -g 53"

*SERVICES
Payroll ROUTING="SALARYROUTE"
Payroll ROUTING="HAIRCOLORROUTE"

*ROUTING
SALARYROUTE FIELD=Salary BUFTYPE="FML32"
RANGES="MIN - 50000:TMQUEUE_BMQGRPPLEBE,50001
-MAX:TMQUEUE_BMQGRPHQMGR"
HAIRCOLORROUTE FIELD=Hair BUFTYPE="FML32"
RANGES="`Gray':TMQUEUE_BMQGRPHQMGR,*:TMQUEUE_BMQGRPPLEBE"

In this example, three queue space names (Payroll, Promote, and Sales) are defined for two busses to four different BEA MessageQ groups (7, 10, 42, and 53). Two servers offer the same aliases (Payroll and Promote) with data dependent routing performed using the Sales and Hair fields respectively. The two other servers offer the same alias (Sales) with routing determined by load balancing and availability.

TUXEDO Queue to BEA MessageQ Queue

Any BEA MessageQ queue can be accessed by TUXEDO through the TMQUEUE_BMQ and TMQFORWARD_BMQ servers. However, BEA MessageQ queues are accessed in different ways depending on whether they are named or unnamed queues. (For more information on BEA MessageQ naming capabilities, see Chapter 4, "Using Naming".)

BEA MessageQ named queues can be local (group-wide) or global (bus-wide). To address a locally named queue from TUXEDO:

  1. Configure the TMQUEUE_BMQ or TMQFORWARD_BMQ server to attach to the local group in which the named queue is defined.

  2. Configure routing information to handle multiple instances of the TMQUEUE_BMQ or TMQFORWARD_BMQ server with the same alias as shown in "TUXEDO Queue Space to BEA MessageQ Group Name" on page 1-23.

  3. Use the queue name as defined by BEA MessageQ as the second parameter for tpenqueue or tpdequeue.

To access an unnamed BEA MessageQ queue from TUXEDO, use an absolute queue identifier as the second parameter for tpenqueue or tpdequeue. The absolute queue identifier is a combination of the BEA MessageQ group identifier and queue identifier formatted as group_id.queue_id. For example, queue 1005 in group 3 is specified as "3.1005". When accessing a queue in the local group, either specify the group as 0 or drop the group identifier and delimiter. For example, queue 1005 in the local group is specified either as "0.1005" or "1005". Queue identifiers that do not use this syntax, or are outside the valid range of group or queue numbers are assumed to be queue names.

Delivery

When a message is enqueued using tpenqueue, the TMQUEUE_BMQ server uses the BEA MessageQ delivery mode of PDEL_MODE_WF_SAF (block until the message is stored in the local recovery journal). The exception to this occurs when the target queue is a temporary queue; in this case, the delivery mode PDEL_MODE_WF_MEM (block until message is stored in the target queue) is used.

If a confirmation delivery mode is required by the BEA MessageQ application, the queues attached to the TMQUEUE_BMQ server must be configured for explicit confirmation.

Messages handled by the TMQUEUE_BMQ server are recoverable, and message recovery services (MRS) must be enabled for the BEA MessageQ group. If MRS is not enabled, the attempt to enqueue the message will fail unless it is enqueued to a temporary queue where recoverable messaging is not required.

Undeliverable Messages

BEA MessageQ specifies the disposition of undeliverable messages according to an undeliverable message action (UMA). TUXEDO uses the ctl.flags:TPQFAILUREQ and ctl.failurequeue to specify a failure queue.

If a message is enqueued using tpenqueue and the ctl.flags:TPQFAILUREQ flag is set, the message is sent to BEA MessageQ with a UMA of PDEL_UMA_DJL (dead letter journal). If the target queue is a temporary queue, a UMA of PDEL_UMA_DLQ (dead letter queue) is used. The failure queue specified by ctl.flags:TPQFAILUREQ is preserved for use by tpdequeue. When BEA MessageQ dequeues a message enqueued by tpenqueue, the value of ctl.failurequeue is ignored.

When a TUXEDO application dequeues a message that was enqueued using tpenqueue, the value of ctl.failurequeue is returned to the application so that failure messages can be put on the failure queue. Failure queue names should be unique to avoid directing a failure message to the wrong queue.

Correlation Identifiers

BEA MessageQ and TUXEDO both support optional correlation identifiers stored as 32 character strings. No transformation is performed on either BEA MessageQ or TUXEDO correlation identifiers. When a response message is sent, the correlation identifier must be manually set.

Return Values

BEA MessageQ return values can be mapped to the TUXEDO tperrno and ctl.diagnostic values. The following table show the relationship between return values for calls to tpenqueue.

Table 1-1

MessageQ Return Value

TUXEDO tpperrno

(return value = -1)

TUXEDO ctl.diagnostic

PAMS__BADPARAM

TPEDIAGNOSTIC

QMESYSTEM

PAMS__BADPRIORITY

TPEDIAGNOSTIC

QMESYSTEM

PAMS__BADPROCNUM

TPEDIAGNOSTIC

QMEBADQUEUE

PAMS__BADRESPQ

TPEDIAGNOSTIC

QMEBADQUEUE

PAMS__EXCEEDQUOTA

TPEDIAGNOSTIC

QMESYSTEM

PAMS__MSGTOBIG

TPEDIAGNOSTIC

QMENOSPACE

PAMS__NOTACTIVE

TPEDIAGNOSTIC

QMESYSTEM

PAMS__REMQFAIL

TPEDIAGNOSTIC

QMESYSTEM

PAMS__STOPPED

TPEDIAGNOSTIC

QMESYSTEM

PAMS__SUCCESS

N/A, return value = 0

PAMS__TIMEOUT

TPEDIAGNOSTIC

QMESYSTEM

PAMS__UNATTACHEDQ

N/A, return value = 0

PAMS__DLJ_FAILED

TPEDIAGNOSTIC

QMESYSTEM

PAMS__DLJ_SUCCESS

TPEDIAGNOSTIC

QMESYSTEM

PAMS__NO_UMA

TPEDIAGNOSTIC

QMESYSTEM

Return Values for tpenqueue

The following table show the relationship between return values for calls to tpdequeue.

Table 1-2

MessageQ Return Value

TUXEDO tpperrno

(return value = -1)

TUXEDO ctl.diagnostic

PAMS__BADPRIORITY

TPEDIAGNOSTIC

QMESYSTEM

PAMS__INSQUEFAIL

TPEDIAGNOSTIC

QMESYSTEM

PAMS__MSGUNDEL

TPEDIAGNOSTIC

QMESYSTEM

PAMS__NETERROR

TPEDIAGNOSTIC

QMESYSTEM

PAMS__NOACCESS

TPEDIAGNOSTIC

QMESYSTEM

PAMS__NOACL

TPEDIAGNOSTIC

QMESYSTEM

PAMS__NOMOREMSG

TPEDIAGNOSTIC

QMENOMSG

PAMS__NOMRQRESRC

TPEDIAGNOSTIC

QMESYSTEM

PAMS__NOTDCL

TPEDIAGNOSTIC

QMESYSTEM

PAMS__PAMSDOWN

TPEDIAGNOSTIC

QMENOTOPEN

PAMS__REMQFAIL

TPEDIAGNOSTIC

QMESYSTEM

PAMS__STOPPED

TPEDIAGNOSTIC

QMESYSTEM

PAMS__SUCCESS

N/A, return value = 0

Return Values for tpdequeue

Other BEA MessageQ API Elements

The following arguments to BEA MessageQ PAMS API functions do not require a direct mapping to TUXEDO.

Other TUXEDO API Elements

The following arguments to TUXEDO ATMI API functions do not require a direct mapping to BEA MessageQ.