Microsoft KB Archive/176307

= INFO: MSMQ and MTS Design Programming Considerations =

Article ID: 176307

Article Last Modified on 8/19/1999

-

APPLIES TO


 * Microsoft Message Queue Server 1.0

-



This article was previously published under Q176307



SUMMARY
This article addresses programming and design considerations for using Microsoft Message Queue Server (MSMQ) with Microsoft Transaction Server (MTS) Transactions.

When you use MSMQ inside an MTS component, decide in advance if you need a single transaction for all MSMQ and MTS operations, use explicit flags for pTransaction, and use appropriate queue types.



MORE INFORMATION
 Queues are assigned a transactional property when created. This property is not modifiable later. MQCreateQueue API (or the Create method in ActiveX) does not detect MTS transaction context to set PROPID_Q_TRANSACTION. You need to supply this flag when creating a queue. Messages sent to a transactional queue can be sent to the Dead Letter Queue if there is no current transaction in the following scenario:

If the queue properties can be accessed at Send time, the call to Send rejects this operation due to a queue type mismatch. This is an application error that will not route the message to the corresponding Dead Letter Queue. If the queue properties can not be accessed at Send time, for example, when you are send directly to a remote location, then the Send fails later and will be in the Dead Letter Queue. Messages sent to a non-transactional queue can be sent to the XACT_DEAD LETTER_QUEUE if they are part of a transaction in the following scenario:

If the queue properties can be accessed at Send time, the call to Send rejects the operation due to queue type mismatch. This is an application error and the message will not route to the corresponding Dead Letter Queue. If the queue properties cannot be accessed at Send time, for example, when you are sending directly to remote location, then the Send fails later and will be found in XACT_DEAD_LETTER_QUEUE. A single MSMQ component can send both transactional and non-transactional messages.  When run under MTS, MSMQ code can detect and become part of the current MTS transaction. The determining factor is the pTransaction parameter in MSMQ Send/Receive calls.

For example, when using ActiveX Send/Receive methods in Visual Basic, it automatically checks if there is an MTS transaction (and will become part of that transaction) when you do not specify any value for pTransaction.

PTransaction
PTransaction is a MSMQTransaction object or one of the following constants:

MQ_NO_TRANSACTION: Specifies that the call is not part of a transaction.

MQ_MTS_TRANSACTION: Default. Specifies that the call is part of the current MTS transaction.

MQ_XA_TRANSACTION: Specifies that the call is part of an externally coordinated, XA-compliant transaction.

Using C API specify the behavior you need:
pTransaction

Must be a pointer to a transaction object, a constant, or NULL. The Transaction object can be obtained internally from MSMQ (by calling MQBeginTransaction), or externally from Microsoft Distributed Transaction Coordinator (DTC).

The constants include the following:

MQ_NO_TRANSACTION

Specifies that the call is not part of a transaction.

MQ_MTS_TRANSACTION

Specifies that the current MTS transaction is used to retrieve the message.

MQ_XA_TRANSACTION

Specifies that the call is part of an externally coordinated, XA- compliant transaction.

NOTE: NULL indicates the message is not retrieved as part of a transaction.

 Using explicit values of pTransaction you can send both transactional and non-transactional messages from a single component.

If the component is non-transactional before being put into an MTS package, and the component is marked with "Requires a Transaction" or "Requires a New Transaction," then the queue the messages are sent to must be transactional. This requires deletion and re-creation, or you need to adjust the flag passed to pTransaction parameter.

If you mark an MTS component as "Supports Transactions," it allows sending both types of messages to the same queue. It is necessary to add programming logic to create and use the appropriate queue at the right time.

You can determine if there is an MTS transaction in process and write conditional code using specific flags.

Refer to the IObjectContext.IsInTransaction method in MTS help file. Using DtcGetTransactionManager creates a transaction. This occurs regardless of whether the component is inside or outside MTS. The net effect is that transactional messages create a new DTC transaction even if run under MTS.</li></ol>

<div class="references_section">