2
votes

I have the following code to get queue information, which throws a 2232 error when done as part of a transaction:

Dim specificQMConnProperties As Hashtable = CType(queueManagerConnectionProperties.Clone(), Hashtable)
specificQMConnProperties.Add(MQC.HOST_NAME_PROPERTY, qmgrHostNameOrIP)
specificQMConnProperties.Add(MQC.PORT_PROPERTY, qmgrPort)
specificQMConnProperties.Add(MQC.CHANNEL_PROPERTY, qmgrChannel)
Dim qmgr As MQQueueManager = Nothing
Try
    qmgr = New MQQueueManager(qmgrName, specificQMConnProperties)
Catch ex As MQException
    Select Case ex.ReasonCode
        Case 2059, 2538
            ' qmgr or host not available
            Return nothing
        Case Else
            ' continue
    End Select
End Try

If qmgr IsNot Nothing Then
Try
    ' use PCF to get queue information.
    Dim agent As New PCFMessageAgent(qmgr)
    Dim request As New PCFMessage(CMQCFC.MQCMD_INQUIRE_Q)
    request.AddParameter(MQC.MQCA_Q_NAME, queueName)

    Dim responses As PCFMessage() = Nothing

    Try
        ' connected
        responses = agent.Send(request)
    Catch pcfex As PCFException
        LogException(pcfex, {queue}, "Exception checking queue availability via PCF. Assuming false")
        Return Nothing
    End Try

    If responses IsNot Nothing AndAlso responses.Any() Then
        LogDebug("Checking queue availability for " & queue.ToString() & " returned a PCF result.")
        return responses
    Else
        LogError("No result returned from PCF Message request on " & queue.ToString())
        Return Nothing
    End If
Catch ex As MQException
    LogException(ex, {queue})
    Return False
End Try
End If

The error occurs on the line responses = agent.Send(request), as follows:

Completion Code: 2, Reason Code: 2232(2232=MQRC_UNIT_OF_WORK_NOT_STARTED) at IBM.WMQ.MQDestination.Put(MQMessage message, MQPutMessageOptions pmo) at IBM.WMQ.PCF.PCFAgent.Send(Int32 command, PCFParameter[] parameters) at IBM.WMQ.PCF.PCFMessageAgent.Send(PCFMessage request, Boolean check) at IBM.WMQ.PCF.PCFMessageAgent.Send(PCFMessage request) at MyMethod

The rest of my transaction connection options (e.g. for message get or put) have Or MQC.MQGMO_SYNCPOINT appended - but I can't see how to set the connection options for a PCF message. Can anyone assist?

To be clear, I don't really care if it is sent as part of the transaction, but because a Transactionscope is open, I get this error.

--Edit--

I've added the code for the queue manager connection at the top.

2
Any reason why you want to run PCF commands under a transaction?Shashi
well it's more that it's part of a flow of commands that are run under transaction - the result of the PCF command determines which of a few options take place - so get, PCF, put here or put there; for example.simonalexander2005
To be clear, I don't really care if it is sent as part of the transaction, but because a Transactionscope is open, I get this error.simonalexander2005

2 Answers

3
votes

The fact that you are getting this error, suggests that either you are reusing the connection to the queue manager that you are using for your other puts and gets and so it is tripping over the transactional scope used for that connection, or that even a new connection that is made is picking up the transactional scope of your environment.

PCFAgent can have it's own connection The PCFAgent and PCFMessageAgent will maintain its own connection to the queue manager and thus avoid the transactional scope on your existing connection.

I suspect the qmgr in your code is an MQQueueManager instance although we can't see the code in your question that created it? If you instead use PCFMessageAgent to make a new connection to the queue manager, it will have its own connection and thus its own transactional scope.

See class PCFMessageAgent for more details, but in short there are three constructors you should be aware of, and I believe you are using the first.

  • PCFMessageAgent(MQQueueManager qmanager)

    Initializes a new PCFMessageAgent with an existing queue manager connection.

  • PCFMessageAgent(java.lang.String qmanager)

    Initializes a new PCFMessageAgent with a bindings connection to a queue manager.

  • PCFMessageAgent(java.lang.String host, int port, java.lang.String channel)

    Initializes a new PCFMessageAgent with a client connection to a queue manager.

Ignoring Transactional Scope Alternatively, you can wrap your call to PCFMessageAgent in a new transactional scope using an option to suppress the transactional scope of the environment as detailed in another StackOverflow question: Ignore TransactionScope for specific query

using (var scope = new TransactionScope(TransactionScopeOption.Suppress))
{
    /* Your PCFMessageAgent code in here */

}

This is, unfortunately, the problem with using wrappers such as PCFAgent, you only get access to some of the things you could configure if you wrote it all yourself.

1
votes

This is just weird. How in the world do you think the queue manager's Command Server can process your PCF command if it is under a UOW (Unit of Work)? Your PCF message (put to the Command Server's queue) is invisible until you do a commit.

I don't know why you need to inquire on a queue after a get but the only way this will work is if it is outside a UOW.