HOWTO: Using MSMQ Within an MTS Component in Visual Basic
ID: Q175726
|
The information in this article applies to:
-
Microsoft Message Queue Server version 1.0
-
Microsoft Transaction Server 1.0
-
Microsoft Visual Basic Standard and Enterprise Editions for Windows, version 5.0
SUMMARY
This article describes using Microsoft Message Queue Server (MSMQ) from
within Microsoft Transaction Server (MTS) components written with Visual
Basic. The two MSMQ transactional operations available are the Message Send
and Receive operations.
MSMQ send operations can be included in MTS transactions. This action
causes the Send operation to be either committed or rolled back along with
the MTS transaction. As a result the message is not actually sent until the
transaction commits. To include the Send operation in a transaction, use
the MQ_MTS_TRANSACTION constant as the Transaction parameter of the
MSMQMessage.Send method from within a transactional MTS component. MSMQ
enlists the Send operation in the MTS transaction. The destination queue
must be a transactional queue. Note that MQ_MTS_TRANSACTION is the default
value of the optional Transaction parameter on Send/Receive; thus, it can
be omitted to obtain MTS transaction behavior.
Transactional messages can be sent only to a transactional destination
queue. If the MTS component is not participating in a transaction, the Send
operation described above fails. This is because the message would be
non-transactional, and you cannot send a non- transactional message to a
transactional queue. You cannot always predict whether a component will
participate in a transaction. Therefore, it is important to verify that the
component is participating in the transaction and to use MQ_MTS_TRANSACTION
in the MSMQMessage.Send to a transactional queue only if it is
participating. If it is not participating, use the MQ_NO_TRANSACTION
or MQ_SINGLE_MESSAGE constant with the appropriate queue type.
The component is participating in the transaction if it is marked as
"Requires [new] Transactions" in MTS Explorer. The component is not
participating in the transaction if it is marked as "Does Not Support
Transactions."
When the MTS component is marked as "Supports Transaction," it also
participates in a transaction if its caller participates. To send from
such a component, you must dynamically check for the current transaction
existence (use method ObjectContext.IsInTransaction)and use an appropriate
Transaction flag and destination queue.
For a local MSMQ transactional queue receive operation, specifying
MQ_MTS_TRANSACTION works regardless of whether the component is
transactional or not. The receive operation is included in a transaction
only if the component is transactional.
MORE INFORMATION
The following Visual Basic code demonstrates sending an MSMQ message
containing a string from within an MTS component. The MTS context object is
used to commit or abort the transaction. The context object's
IsInTransaction() method is used to determine whether or not the component
is transactional.
Public Function MQSend(strSend As String) As String
Dim qinfoSend As New MSMQQueueInfo
Dim qSend As MSMQQueue
Dim qmesMessage As New MSMQMessage
On Error GoTo SendError
Dim ctxObject As ObjectContext
Set ctxObject = GetObjectContext
' Add code for database updates if needed.
qinfoSend.PathName = ".\Localx"
Set qSend = qinfoSend.Open(MQ_SEND_ACCESS, MQ_DENY_NONE)
qmesMessage.Body = strSend
qmesMessage.Label = "VB Sample Message"
'Since you must send to a transactional MSMQ queue in order to
'participate in a transaction, you must check to see if the component
'is transactional and be sure to make the send operation
'transactional in either case.
If (ctxObject.IsInTransaction) Then
qmesMessage.Send qSend, MQ_MTS_TRANSACTION
Else
qmesMessage.Send qSend, MQ_SINGLE_MESSAGE
End If
qSend.Close
ctxObject.SetComplete
Set ctxObject = Nothing
Exit Function
SendError:
ctxObject.SetAbort
Set ctxObject = Nothing
MQSend = "SendFailure"
End Function
The following Visual Basic code demonstrates receiving an MSMQ message
containing a string from within an MTS component. The MTS context object is
used to commit or abort the transaction.
Public Function MQReceive(strReceive As String) As String
Dim qinfoRcv As New MSMQQueueInfo
Dim qRcv As MSMQQueue
Dim qmesMessage As MSMQMessage
On Error GoTo RcvError
Dim ctxObject As ObjectContext
Set ctxObject = GetObjectContext
' Add code for database updates if needed.
qinfoRcv.PathName = ".\Localx"
Set qRcv = qinfoRcv.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE)
Set qmesMessage = qRcv.Receive(Transaction:=MQ_MTS_TRANSACTION,
ReceiveTimeout:=0)
' or since MQ_MTS_TRANSACTION is the default, simply:
' Set qmesMessage = qRcv.Receive(ReceiveTimeout:=0)
If (Not qmesMessage Is Nothing) Then
strReceive = qmesMessage.Body
MQReceive = "MessageReceived"
Else
MQReceive = "NoMessage"
End If
qRcv.Close
ctxObject.SetComplete
Set ctxObject = Nothing
Exit Function
RcvError:
ctxObject.SetAbort
Set ctxObject = Nothing
MQReceive = "ReceiveFailure"
End Function
REFERENCES
For more details on using a single queue for send/receive and to avoid
queue and component type mismatch, see the following Knowledge Base
article:
Q174387 "INFO: Using a Single MSMQ Queue for an MTS Component"
Additional query words:
viper falcon
Keywords : kbcode kbMSMQ kbMSMQ100 kbMTS kbMTS100 kbVBp500 MQProg MQVB kbVB500
Version : WINDOWS:5.0; winnt:1.0
Platform : WINDOWS winnt
Issue type : kbhowto