How to define type MQOD when calling WebSphere MQ API functi

Posted by Fuelfire on 22-Sep-2015 04:12

Good day, everyone! I'm trying to open WebSphere MQ queuе through API function. I want to connect to the queue manager, open a specific queue, put in her message, get the message and then close and disconnect. I installed the WebSphere MQ client 7.5 and downloaded the manual "MQSeries Application Programming Interface".

In the process of describing the procedures necessary for me I had a problem.

For example, the documentation for the opening queue looks like this:

MQOPEN Hconn, ObjDesc, Options, Hobj, CompCode, Reason
Declare the parameters as follows:
Dim Hconn As Long 'Connection handle'
Dim ObjDesc As MQOD 'Object descriptor'
Dim Options As Long 'Options that control the action of MQOPEN'
Dim Hobj As Long 'Object handle'
Dim CompCode As Long 'Completion code'
Dim Reason As Long 'Reason code qualifying CompCode'

As can be seen the parameter ObjDesc is of type MQOD.
MQOD, as specified in the manual, is a structure:

Type MQOD
StrucId As String*4 'Structure identifier'
Version As Long 'Structure version number'
ObjectType As Long 'Object type'
ObjectName As String*48 'Object name'
ObjectQMgrName As String*48 'Object queue manager name'
DynamicQName As String*48 'Dynamic queue name'
AlternateUserId As String*12 'Alternate user identifier'
RecsPresent As Long 'Number of object records present'
KnownDestCount As Long 'Number of local queues opened
'successfully'
UnknownDestCount As Long 'Number of remote queues opened'
'successfully'
InvalidDestCount As Long 'Number of queues that failed to open'
ObjectRecOffset As Long 'Offset of first object record
'from start of MQOD'
ResponseRecOffset As Long 'Offset of first response record from'
'start of MQOD'
ObjectRecPtr As String*32 'Address of first object record'
ResponseRecPtr As String*32 'Address of first response record'
AlternateSecurityID As String*40 'Alternate security identifier'
ResolvedQName As String*48 'Resolved queue name'
ResolvedQMgrName As String*48 'Resolved queue manager name'
End Type

How should I declare the type MQOD? When I compile my program I get error:

Could not find source class file MQOD.cls. (12625)
DLL datatype must be one of CHARACTER, BYTE, SHORT, UNSIGNED-SHORT, LONG, FLOAT, or DOUBLE (3383)

Here, a piece of program with certain procedures:

DEFINE VARIABLE QMgrName AS CHAR FORMAT "X(48)" NO-UNDO. /* Name of queue manager */
DEFINE VARIABLE Hconn AS HANDLE NO-UNDO. /* Connection handle */
DEFINE VARIABLE CompCode AS INT NO-UNDO. /* Completion code */
DEFINE VARIABLE Reason AS INT NO-UNDO. /* Reason code qualifying CompCode */

/*connecting to queue manager*/
PROCEDURE MQCONN EXTERNAL "mqic32.DLL":
    DEFINE INPUT  PARAMETER QName AS CHAR NO-UNDO.              /*Name of queue manager*/
    DEFINE OUTPUT PARAMETER Hconn AS LONG NO-UNDO.              /*Connection handle*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.    /*Completion code: MQCC_OK - Successful completion.
                                                                                                                                                                MQCC_WARNING - Warning (partial completion).
                                                                                                                                                                MQCC_FAILED - Call failed.*/
    DEFINE RETURN PARAMETER Reason AS LONG NO-UNDO.          /*Reason code qualifying CompCode*/
END PROCEDURE.

/*opening queue*/
PROCEDURE MQOPEN EXTERNAL "mqic32.DLL":
    DEFINE INPUT PARAMETER Hconn AS LONG NO-UNDO.                             /*Connection handle*/
    DEFINE INPUT-OUTPUT PARAMETER ObjDesc AS MQOD NO-UNDO.  /*Object descriptor*/
    DEFINE INPUT PARAMETER OPTIONS AS LONG NO-UNDO.                      /*Options that control the action of MQOPEN*/
    DEFINE OUTPUT PARAMETER Hobj AS LONG NO-UNDO.                           /*Object handle*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.             /*Completion code*/
    DEFINE RETURN PARAMETER Reason AS LONG NO-UNDO.                   /*Reason code qualifying CompCode*/
END PROCEDURE.

How to create a class for such a complex data type as MQOD? Thanks.

Posted by Garry Hall on 22-Sep-2015 08:22

If I understand it correctly, this is taking a pointer to a MQOD object. You will need to define a MEMPTR of the appropriate size for the MQOD object, populate it as necessary, and pass it as the parameter. The type of the parameter should be MEMPTR.

All Replies

Posted by Garry Hall on 22-Sep-2015 06:48

The ABL supports only primitive types when calling into a shared object/DLL. Your MQOD parameter for MQOPEN would be a LONG/INT64 (depending on platform). Basically, a pointer is being passed (i.e. passing the object by reference), so you need to pass a datatype that can contain the entire pointer. You should look for a C/C++ sample instead of a VB sample.

Posted by Fuelfire on 22-Sep-2015 08:08

Here is C invocation:

MQOPEN (Hconn, &ObjDesc, Options, &Hobj, &CompCode,
&Reason);
Declare the parameters as follows:
MQHCONN Hconn; /* Connection handle */
MQOD ObjDesc; /* Object descriptor */
MQLONG Options; /* Options that control the action of MQOPEN */
MQHOBJ Hobj; /* Object handle */
MQLONG CompCode; /* Completion code */
MQLONG Reason; /* Reason code qualifying CompCode */

Cobol, PL and others are the same.

Posted by Garry Hall on 22-Sep-2015 08:22

If I understand it correctly, this is taking a pointer to a MQOD object. You will need to define a MEMPTR of the appropriate size for the MQOD object, populate it as necessary, and pass it as the parameter. The type of the parameter should be MEMPTR.

Posted by Fuelfire on 22-Sep-2015 08:25

Thanks a lot, Garry. I will explore the use of MEMPTR.

Posted by Fuelfire on 25-Sep-2015 02:39

I wrote the program and set up an environment variable MQSERVER. When I try to connect to queue manager I get an error 2058 (Queue manager name not valid or not known).

I tried to put a message to a queue using the WebSphere utility amqsputc. Using the same values of the host server, the port channel, the queue manager and the queue, I was able to put a message in the queue. What could be wrong? MQ administrator also gave me the name of the user to connect. I created the same local user and invoke the console as this user. When I called cmd under my account, I get an error 2035 (Not authorized for access).

I do not know how to run p-file under desired user. I tried to do it  using "RUN AS", but the error remains the same .. I'm confused.

/*Usual sequence is:
MQ Connect (queue manager name)
   MQ Open (queue name)
   MQ Put / Get (message)
   MQ Close (q)
 MQ Disconnect (qm)
 */
 
&SCOPED-DEFINE MQCC_OK 0
&SCOPED-DEFINE MQRC_NONE 0
&SCOPED-DEFINE MQOO_INPUT_EXCLUSIVE 4
&SCOPED-DEFINE MQOO_OUTPUT 16
&SCOPED-DEFINE MaxMsgLength 104 857 600
&SCOPED-DEFINE DLL-LIB mqic32.dll
&SCOPED-DEFINE MQCO_NONE 0

DEFINE VARIABLE QMgrName AS CHAR FORMAT "X(48)" NO-UNDO. /* Name of queue manager */

DEFINE VARIABLE Hconn AS INT64 NO-UNDO. /* Connection handle */
DEFINE VARIABLE CompCode AS INT64 NO-UNDO. /* Completion code */
DEFINE VARIABLE Reason AS INT64 NO-UNDO. /* Reason code qualifying CompCode */

DEFINE VARIABLE ObjDesc AS MEMPTR NO-UNDO.
DEFINE VARIABLE Hobj AS INT NO-UNDO.
DEFINE VARIABLE MsgDesc AS MEMPTR NO-UNDO.
DEFINE VARIABLE GetMsgOpts AS MEMPTR NO-UNDO.
DEFINE VARIABLE PutMsgOpts AS MEMPTR NO-UNDO.
DEFINE VARIABLE Buffer_ AS CHAR NO-UNDO.                         /*Area to contain the message data*/
DEFINE VARIABLE DataLength AS INT NO-UNDO.

/*connect*/
PROCEDURE MQCONN EXTERNAL "{&DLL-LIB}" CDECL PERSISTENT:
    DEFINE INPUT  PARAMETER QName AS CHAR NO-UNDO.              /*Name of queue manager*/
    DEFINE OUTPUT PARAMETER Hconn AS LONG NO-UNDO.              /*Connection handle*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.    /*Completion code: MQCC_OK - Successful completion.
                                                                                                                                                                MQCC_WARNING - Warning (partial completion).
                                                                                                                                                                MQCC_FAILED - Call failed.*/
    DEFINE OUTPUT PARAMETER Reason AS LONG NO-UNDO.          /*Reason code qualifying CompCode*/
END PROCEDURE.
/*open*/
PROCEDURE MQOPEN EXTERNAL "{&DLL-LIB}" CDECL PERSISTENT:
    DEFINE INPUT PARAMETER Hconn AS LONG NO-UNDO.                             /*Connection handle*/
    DEFINE INPUT-OUTPUT PARAMETER ObjDesc AS MEMPTR NO-UNDO.  /*Object descriptor*/
    DEFINE INPUT PARAMETER OPTIONS_ AS LONG NO-UNDO.                      /*Options that control the action of MQOPEN*/
    DEFINE OUTPUT PARAMETER Hobj AS LONG NO-UNDO.                           /*Object handle*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.             /*Completion code*/
    DEFINE OUTPUT PARAMETER Reason AS LONG NO-UNDO.                   /*Reason code qualifying CompCode*/
END PROCEDURE.
/*get message*/
PROCEDURE MQGET EXTERNAL "{&DLL-LIB}" CDECL PERSISTENT:
    DEFINE INPUT PARAMETER Hconn AS LONG NO-UNDO.                           /*Connection handle*/
    DEFINE INPUT PARAMETER Hobj AS LONG NO-UNDO.                              /*Object handle*/
    DEFINE INPUT-OUTPUT PARAMETER MsgDesc AS MEMPTR NO-UNDO.  /*message descriptor*/
    DEFINE INPUT-OUTPUT PARAMETER GetMsgOpts AS MEMPTR NO-UNDO.  /*Options that control the action of MQGET*/
    DEFINE INPUT PARAMETER BufferLength AS LONG NO-UNDO.                        /*Length in bytes of the Buffer area*/
    DEFINE OUTPUT PARAMETER Buffer_ AS CHAR NO-UNDO.                         /*Area to contain the message data*/
    DEFINE OUTPUT PARAMETER DataLength AS LONG NO-UNDO.             /*Length of the message*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.             /*Completion code*/
    DEFINE OUTPUT PARAMETER Reason AS LONG NO-UNDO.                   /*Reason code qualifying CompCode*/
END PROCEDURE.
/*put the message*/
PROCEDURE MQPUT EXTERNAL "{&DLL-LIB}" CDECL PERSISTENT:
    DEFINE INPUT PARAMETER Hconn AS LONG NO-UNDO.                           /*Connection handle*/
    DEFINE INPUT PARAMETER Hobj AS LONG NO-UNDO.                              /*Object handle*/
    DEFINE INPUT-OUTPUT PARAMETER MsgDesc AS MEMPTR NO-UNDO.  /*message descriptor*/
    DEFINE INPUT-OUTPUT PARAMETER PutMsgOpts AS MEMPTR NO-UNDO.  /*Options that control the action of MQPUT*/
    DEFINE INPUT PARAMETER BufferLength AS LONG NO-UNDO.                        /*Length in bytes of the Buffer area*/
    DEFINE INPUT PARAMETER Buffer_ AS CHAR NO-UNDO.                         /*Area to contain the message data*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.             /*Completion code*/
    DEFINE OUTPUT PARAMETER Reason AS LONG NO-UNDO.                   /*Reason code qualifying CompCode*/
END PROCEDURE.
/*close*/
PROCEDURE MQCLOSE EXTERNAL "{&DLL-LIB}" CDECL PERSISTENT:
    DEFINE INPUT PARAMETER Hconn AS LONG NO-UNDO.                           /*Connection handle*/
    DEFINE INPUT-OUTPUT PARAMETER Hobj AS LONG NO-UNDO.         /*Object handle*/
    DEFINE INPUT PARAMETER OPTIONS_ AS LONG NO-UNDO.                   /*Options that control the action of MQCLOSE*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG NO-UNDO.           /*Completion code*/
    DEFINE OUTPUT PARAMETER Reason AS LONG NO-UNDO.                  /*Reason code qualifying CompCode*/
END PROCEDURE.
/*disconnect*/
PROCEDURE MQDISC EXTERNAL "{&DLL-LIB}" CDECL PERSISTENT:
    DEFINE INPUT-OUTPUT PARAMETER Hconn AS LONG.        /*Connection handle*/
    DEFINE OUTPUT PARAMETER CompCode AS LONG.             /*êîä âûïîëíåíèÿ*/
    DEFINE OUTPUT PARAMETER Reason AS LONG.                   /*Reason code qualifying CompCode*/
END PROCEDURE.

ASSIGN QMgrName = "UNIQM".

/*Connect to certain queue manager*/
RUN MQCONN (QMgrName,
                  OUTPUT Hconn,
                  OUTPUT CompCode,
                  OUTPUT Reason).

IF ((CompCode = {&MQCC_OK} ) AND (Reason = {&MQRC_NONE}))
THEN DO:
    MESSAGE "+++ MQCONN() ended OK!" VIEW-AS ALERT-BOX.
END.
ELSE DO: /* report reason and exit */
    MESSAGE "--- MQCONN() ended with Completion Code "
        (IF CompCode = -1 THEN "MQCC_UNKNOWN" ELSE (IF CompCode = 0 THEN "MQCC_OK" ELSE (IF CompCode = 1 THEN "MQCC_WARNING" ELSE "MQCC_FAILED")))
        "~nReason code " STRING(Reason) VIEW-AS ALERT-BOX.
    LEAVE.
END.

/*Open a query*/
RUN MQOPEN (HConn,
                  INPUT-OUTPUT ObjDesc,
                  /*{&MQOO_INPUT_EXCLUSIVE},*/
                  {&MQOO_OUTPUT},
                  OUTPUT Hobj,
                  OUTPUT CompCode,
                  OUTPUT Reason).

Posted by Fuelfire on 25-Sep-2015 03:59

I forgot to mention that if the program is run by my account, an 2035 error occurs  (Not authorized for access). But if I run desktop under my account and run the Progress program MQCONN returns 2058 error.

I conclude that WebSphere don't understand the user under which the program runs. I don't know how to transfer the user in MQCONNX programmatically.

Posted by Bill Wood on 08-Mar-2016 12:40

This is probably too late to particularly worry about for this thread, but starting in OpenEdge 11.5.1,  Progress OpenEdge provides a generic Java Message Service (JMS) adapter for messaging. This generic JMS adapter can operate with any JMS-compliant vendor, including SonicMQ, IBM WebSphereMQ, and ActiveMQ.    

You can get more information in the product documentation, or look at the whitepaper on Community at

 community.progress.com/.../1986

Further updates happened in 11.6.1 to support all modes: Client Connect, Broker Connect, and Server Connect.

This thread is closed