|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
Active X AccessQueue returns null, sometimes... |
« View previous topic :: View next topic » |
Author |
Message
|
dunesand |
Posted: Mon Mar 22, 2004 9:03 am Post subject: Active X AccessQueue returns null, sometimes... |
|
|
 Acolyte
Joined: 17 Nov 2003 Posts: 65 Location: Cambridgeshire, UK
|
Hey there...
I'm using c# .Net with CSD03 (an unfortunate requirement), and decided to go through the Active X API channel.
On my machine, XP with Websphere MQ 5.3.0 and fixpack CSD 03, the following code snippet works a treat in both debug and release.
Code: |
//
// create the queue
IMQQueue200 queue = null;
if ( queue == null )
{
queue = (IMQQueue200) m_xQueueManager.AccessQueue( m_szQueue,
(int)MQ.MQOO_OUTPUT + (int)MQ.MQOO_FAIL_IF_QUIESCING,
"", "", "" );
}
if ( queue == null )
{
m_szExceptionError = "Error occurred in the ibmMQ Send : The queue, '" + m_szQueue + "', could not be accessed.";
return eResult.RES_ERROR;
}
if ( !queue.IsOpen )
{
m_szExceptionError = "Error occurred in the ibmMQ Send : The queue, '" + m_szQueue + "', was correctly accessed, but is not open.";
return eResult.RES_ERROR;
}
|
But when I install my program on another box with the same setup (2000 or XP with CSD03) one message can be posted to a queue, then I get the queue (that has its name contained in m_szQueue) could not be accessed (i.e., from this code that the queue returned from IMQQueueManager200::AccessQueue is "null" )
The reason name given is MQRC_HCONN_ERROR, but why would the connection handle suddenly become invalid after one post?
1. Why are these results different on two apparently identical machines?
2. Why is this happening?
3. How do i fix it (and if upgrading from CSD03 isn't an option because of big company politics and bureaucracy?)
Thanks for your help!
Daniel |
|
Back to top |
|
 |
jefflowrey |
Posted: Mon Mar 22, 2004 9:15 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
You can't run the FixPack 05 .Net assembly on a FixPack 03 machine.
If you need to use .Net with FixPack 03, then you need to use the (obsoleted by FixPack 05) .Net support pack - that is not as full featured or supported. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
dunesand |
Posted: Tue Mar 23, 2004 12:31 am Post subject: |
|
|
 Acolyte
Joined: 17 Nov 2003 Posts: 65 Location: Cambridgeshire, UK
|
Thanks for the reply, but I'm not using the .Net API, rather I'm using the Active X control (MQAX200).
I've created an interop for the this for .Net and am using c#.
Dan. |
|
Back to top |
|
 |
dunesand |
Posted: Tue Mar 23, 2004 12:59 am Post subject: |
|
|
 Acolyte
Joined: 17 Nov 2003 Posts: 65 Location: Cambridgeshire, UK
|
I'm using multithreading, and MQAX doesn't allow connection handles to be shared across threads. Fantastic... |
|
Back to top |
|
 |
JasonE |
Posted: Tue Mar 23, 2004 2:53 am Post subject: |
|
|
Grand Master
Joined: 03 Nov 2003 Posts: 1220 Location: Hursley
|
That would certainly account for those problems. You can use multiple threads but each needs to connect (and each hconn needs to open the q's etc). Watch out for the other activex issue relating to the MQSession object, ie there is one which is shared so checking return codes is not straightforward.
Quote: |
When checking the ActiveX COM MQSession CompCode and ReasonCode. The user should be aware that there is only ever one Session object. This object is updated after each MQ call. For a multithreaded application this may cause a problem. On receiving an error the CompCode and ReasonCode may be updated by the next MQ call on a different thread.
This only applies to the Session object. Other MQ objects are not shared in the system so hold a unique CompCode and ReasonCode. One way to handle this is to change the VB application to continue after an error and inspect the VB variable Err. Err is thread/appartment/process safe so the values stored e.g. Err.Description can be relied upon.
The user should make the MQ call, read the Description and parse the Description to extract the CompCode and ReasonCode. A pair of subroutines is available to read this value, and extract the value, before clearing the error condition.
example code:
Private Sub CheckMQSeries(ByRef CC As Long, ByRef RC As Long)
Dim ErrObj As String ' Set Object error
Dim ErrCC As String ' Set CC
Dim ErrRC As String ' Set RC
Dim Text As String ' Set Error Descriptor (1)
Dim Ignore As String ' For text to ignore
Dim StrPos As Long ' Position of MQSeries identifier
Const MQSERIES = "MQAX200" ' MQSeries identifier
Text = Err.Description ' Copy error description
StrPos = InStr(Text, MQSERIES) ' Check its MQ identifier
If (StrPos > 0) Then ' Yes - its MQ
BreakAt " ", Text, ErrObj ' Set Object error
BreakAt " = ", Text, Ignore
BreakAt ", ", Text, ErrCC ' Set CC
BreakAt " = ", Text, Ignore
BreakAt ", ", Text, ErrRC ' Set RC
' BreakAt " = ", text, Ignore ' Set Error Descriptor (1)
CC = Val(ErrCC) ' Convert CC String to Long
RC = Val(ErrRC) ' Convert RC String to Long
Err.Clear ' Clear MQ error description
Else
CC = 0 ' No MQ error
RC = 0 ' No MQ error
End If
End Sub
'*******************************************************************************
'* Subroutine BreakAt()
'*
'* Suggested use:
'* BreakAt " ", Text, Before ' Split text, returning after/before text
'* BreakAt ", ", Text, Before ' Split text at next match
'*
'* Used by CheckMQSeries() subroutine
'*******************************************************************************
Private Sub BreakAt(ByVal Match As String, _
ByRef Text As String, _
ByRef Before As String)
Dim MatchLen As Long ' Length of 'match'
Dim StrPos As Long ' Position of 'match'
Before = "" ' Assume nothing
MatchLen = Len(Match) ' Something to 'match'?
If (MatchLen > 0) Then
StrPos = InStr(Text, Match) ' Something to 'breakAt'
If (StrPos > 0) Then ' Yes - 'break' text
Before = Left(Text, StrPos - 1)
Text = Mid(Text, StrPos + MatchLen)
End If
End If
End
|
|
|
Back to top |
|
 |
dunesand |
Posted: Tue Mar 23, 2004 3:03 am Post subject: |
|
|
 Acolyte
Joined: 17 Nov 2003 Posts: 65 Location: Cambridgeshire, UK
|
Jason,
Thanks for your reply.
I've already got a model that worked great with the .Net API in CSD05, and am trying to use antoher method with CSD03 where it just takes a little massaging to get it working.
Basically there are interface objects (where an interface can be an ibm mq, msmq, file, odbc etc...), and each object has it's own connection instance to it's interface type.
An ibm mq object is first initialised with a name for the qmgr and queue. The manager (and session obj if applicable) are created, then a interface either listens for incoming data (messages), or gets called to send messages. It's in these send and receive that the queue instances are created and get and put is called.
I've tried Kolban's MQSeries.Net as well, and this also appears to have problems. I'll move onto MA7P now...
Is there any way Kolban's API can be used? When I called
Code: |
new MQQueueManager() |
in the initialisation for the second object created (on another thread) an exception is thrown with 2002 (already connected), which I don't really get as it should be creating a new connection for that object. I assume this means the API uses one static connection for each queue manager / queue that is accessed?
Are there other ideas you could suggest? The other (long way round) option would be to create a COM object that hooks into the C/C++ libraries, then access this COM, that way I know where the connections are being established and can make them thread safe from the start. But in providing time scales for this solution, it's been deemed other system architectural changes will take precidence (i.e. wiggle it back to CSD05 somehow - fine with me)
Thanks for your time.
Daniel. |
|
Back to top |
|
 |
dunesand |
Posted: Tue Mar 23, 2004 3:58 am Post subject: |
|
|
 Acolyte
Joined: 17 Nov 2003 Posts: 65 Location: Cambridgeshire, UK
|
In my send (as with receive) method, I create the queue via AccessQueue(...) on the queue manager, that was created by this same thread via m_xSession.AccessQueueManager("").
But I still get a HCONN_ERROR?
m_xSession is a static member of the object, to ensure it is only created once.
I also clear the error codes if an error is reported immediately after an error occurs (ThreadSafeErrorReport) and the rc and cc are saved locally.
Code: |
//
// create the queue
IMQQueue200 queue = null;
if ( queue == null )
{
if ( !m_xQueueManager.IsConnected )
m_xQueueManager.Connect();
queue = (IMQQueue200) m_xQueueManager.AccessQueue( m_szQueue,
(int)MQAX200.MQ.MQOO_OUTPUT + (int)MQAX200.MQ.MQOO_FAIL_IF_QUIESCING,
"", "", "" );
}
if ( queue == null )
{
ThreadSafeErrorReport ( "Error occurred in the ibmMQ Send : The queue, '" + m_szQueue + "', could not be accessed. " );
return eResult.RES_ERROR;
}
|
|
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|