Connect to WebSphere MQ through JMS API (JMS Adapter) - Forum - OpenEdge Development - Progress Community

Connect to WebSphere MQ through JMS API (JMS Adapter)

 Forum

Connect to WebSphere MQ through JMS API (JMS Adapter)

This question is answered

Hello, everybody! 

I'm trying to open, get, put, close WebSphere MQ queuе through JMS API. 

I want to connect to the queue manager, open a specific queue, put in her message, get the message and then close and disconnect. Earlier I connected to the MQ through MQ API

With the help of colleagues from this forum, I was able to write a program with the help of which I got the opportunity to put messages in the queue and pick them up. This program is very cumbersome. I made it in the OpenEdge 10.1B, using installed the WebSphere MQ client 7.5 and downloaded the manual "MQSeries Application Programming Interface". It was a test and this solution is not used in our product.

Now I'm using version 11.6.3. Having learned that since version 11.5.1 I can interact with WebSphere MQ without using the SonicMQ (I do not have licenses for this product), I became interested and decided to figure it out.

My task of interacting with WebSphere MQ queues is complicated by the fact that I have to access the queue from the server (not from the client, as in the program I wrote earlier). For these purposes, I plan to use purchased and installed on the database server PAS for OE. In any case, this is how I call the web services: the program on the client calls the application server on which the service call programs run.

So, I started to study the documentation "Messaging and ESB". I made the necessary changes in jmsProvider.properties and AdminServerPlugins.properties in In the %DLC%\properties path:

[PluginPolicy.Progress.SonicMQ]
    pluginclasspath=C:\Program Files\Progress\OpenEdge_11_6/sonic/MQ8.5/lib/sonic_Client.jar,C:\Program Files\Progress\OpenEdge_11_6/sonic/MQ8.5/lib/mgmt_client.jar,C:\Program Files\Progress\OpenEdge_11_6/java/progress.jar,C:\PROGRA~1\IBM\WEBSPH~1\java\lib\com.ibm.mqjms.jar
    classpath=C:\Program Files\Progress\OpenEdge_11_6/sonic/MQ8.5/lib/sonic_Client.jar,C:\Program Files\Progress\OpenEdge_11_6/java/progress.jar,C:\PROGRA~1\IBM\WEBSPH~1\java\lib\com.ibm.mqjms.jar
    jvmargs=-DsonicMQExtensions=false -DjmsProvider=WebSphereMQ

After that, I began to doubt: there is a WebSphere client on my workstation. But our users work with software using the Client Networking, hosted on a network resource. Probably I should install the WebSphere client on the network? After all, I must somehow run the SonicMQ adapter? On the server in Progress OpenEdge Management I chose the SonicMQ Adapter Resource. But nothing can be created here. Here I am stuck. Do I need to configure something on the server or just make changes to the properties files? Maybe I missed something (did not install it) during the installation of OpenEdge RDBMS?

Can anyone help me? Thanks.

Andrew.

All Replies
  • We need to provide Connection factory name for JNDI approach, otherwise we can use queue manager name if everything is running in single machine. In your case, we need to use connection factory name in setBrokerURL.

    Thanks,

    Anand.

  • I read this article and suggested that a number of parameters such as the channel name is already defined in the AMQCLCHL.TAB. I decided to regenerate .bindings file without specifying CCDTURL:

    DEF CF(RemoteCF) + QMGR(UNIQM) + TRAN(CLIENT) + CHAN(SWIFTMQ.SVRCONN) + HOST(vplmq12) + PORT(1422)

    Then I compiled and packed my class. I restarted AdminService and run this program:

    /* ***************************  Main Block  *************************** */
    DEFINE VARIABLE QueueManager AS CHAR NO-UNDO.
    DEFINE VARIABLE QueueName AS CHAR NO-UNDO.
    DEFINE VARIABLE CMessage AS CHAR NO-UNDO.
    
    ASSIGN QueueManager = "UNIQM"
                    QueueName = "TEST.Q"
                    CMessage = "Hello from DepoNet!!!".
    
    DEFINE VARIABLE ptpsession AS HANDLE.
    DEFINE VARIABLE messageH AS HANDLE.
    DEFINE VARIABLE lDebug AS LOGICAL.
    
    /* Creates a session object. */
    RUN jms/jmssession.p PERSISTENT SET ptpsession ("-H localhost -S 3620 -AppService AD.sonicMQ1 -DirectConnect"). 
    
    /* Set user credentials. */
     
    RUN setBrokerURL      IN ptpsession ("RemoteCF").
    
    RUN setUser           IN ptpsession (INPUT "swiftmq").
    
    RUN setPassword       IN ptpsession (INPUT "swiftmq").
    
    /* Connect to the broker. */
    RUN beginSession IN ptpsession.
    
    /* Create a text message */
    RUN createTextMessage IN ptpsession (OUTPUT messageH).
    
    RUN setText IN messageH (CMessage).
    
    /* Publish the message on the "REQUEST" topic */
    RUN sendToQueue IN ptpsession (QueueName, messageH, ?, ?, ?).   
    RUN deleteMessage IN messageH.
    RUN deleteSession IN ptpsession.
    
    MESSAGE "SENT!" VIEW-AS ALERT-BOX.
    RETURN "0".
    

    My message was sent successfully!

    In the documentation and in other examples, the name of the queue manager is transferred to the procedure setBrokerURL. In my case, everything works, if I pass the name of the connection factory. This is normal?

  • Anand, thank you so much! Did not see your previous message.

    1) In which case should I use CCDTURL for generation the .bindings file?

    2) How can I generate a .bindings file for multiple queues?

     Great thanks!

  • Anand, I have one more question (third): when my PASOE run Get.p my program freezes and does not respond. I think the reason is that the application server does not know how to work with "WAIT-FOR u1 OF THIS-PROCEDURE."

    How to avoid an infinite loop?

    Get.p

  • Hi Fuelfire,

    Generally, we use .bindings file to connect WebSphereMQ remotely using JNDI approach. While creating .bindings file we need to specify the location of TAB file using CCDTURL as it contains the information about the connection factory.

    We generate the .bindings file with TAB file and in the connection factory at server side we will create multiple queues to hold the messages.

    Hope this helps!!

    Thanks,
    Anand.

  • Hi, Anand! I have problems with receiving messages :-(

    I modified test_get.p this way:

    /*------------------------------------------------------------------------
        File        : Get.p
        Purpose     : 
    
        Syntax      :
    
        Description : 
    
        Author(s)   : 
        Created     : Wed Mar 22 17:06:44 MSK 2017
        Notes       :
      ----------------------------------------------------------------------*/
    
    /* ***************************  Definitions  ************************** */
    
    BLOCK-LEVEL ON ERROR UNDO, THROW.
    
    /* ********************  Preprocessor Definitions  ******************** */
    
    
    /* ***************************  Main Block  *************************** */
    DEFINE VAR QueueManager AS CHAR NO-UNDO.
    DEFINE VAR QueueName AS CHAR NO-UNDO.
    DEFINE VAR CMessage AS CHAR NO-UNDO.
    
    DEFINE VARIABLE ptpsession AS HANDLE.
    DEFINE VARIABLE consumerH AS HANDLE.
    DEFINE VARIABLE stillWaiting AS LOGICAL NO-UNDO INITIAL TRUE.
    
    ASSIGN QueueManager = "RemoteCF"
                    QueueName = "TEST.Q".
    
    /* Creates a session object. */
    RUN jms/jmssession.p PERSISTENT SET ptpsession ("-H localhost -S 3620 -AppService AD.sonicMQ1 -DirectConnect").
    
    RUN setBrokerURL      IN ptpsession (INPUT QueueManager).
    
    /* Set user credentials. */
    RUN setUser           IN ptpsession (INPUT "swiftmq").
    RUN setPassword       IN ptpsession (INPUT "swiftmq").
    
    /* Connect to the broker. */
    RUN beginSession IN ptpsession.
    
    /* Subscribe to the Sample.Q1 queue. Messages are handled by the "messageHandler" internal procedure. */
    RUN createMessageConsumer IN ptpsession (THIS-PROCEDURE,   /* This proc will handle it */
                                             "messageHandler", /* name of internal procedure */
                                             OUTPUT consumerH).
      
    /* Do not create a new message for each received message */
    RUN setReuseMessage IN consumerH.
    
    RUN receiveFromQueue IN ptpsession (QueueName,                      /* name of queue */
                                                                    ?,                                      /* No message selector */
                                                                    consumerH) NO-ERROR. /* Handles incoming messages*/
       
    /* Start receiving messages              */
    RUN startReceiveMessages IN ptpsession.
    
    RUN waitForMessages IN ptpsession ("inWait", THIS-PROCEDURE, ?).
    RUN deleteSession IN ptpsession.
    /* Wait forever to receive messages since "u1" is never applied. 
    WAIT-FOR u1 OF THIS-PROCEDURE.*/
    MESSAGE cMessage VIEW-AS ALERT-BOX.
    RETURN "0".
    
    PROCEDURE messageHandler:
        DEFINE INPUT PARAMETER messageH AS HANDLE.
        DEFINE INPUT PARAMETER msgConsumerH AS HANDLE.
        DEFINE OUTPUT PARAMETER replyH AS HANDLE.
       
        /* Creates a reply message. The reply is published automatically when
        control returns to the ABL-JMS implementation.
        */
        ASSIGN CMessage = DYNAMIC-FUNCTION('getText':U IN messageH).
            
        RUN deleteMessage IN messageH.       
        ASSIGN stillWaiting = FALSE.    
    
    END.
    
    FUNCTION inWait RETURNS LOGICAL:
            RETURN stillWaiting.
    END.
    

    But when I run the program - it hangs. I do not understand where I made a mistake. Let me remind you that I want to call the program for receiving messages from the application server (PASOE).

    When I interrupt execution of program I see in sonicMQ1.server.log:

    S-0011>(Mar 31, 2017 10:16:29:436) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc:     Startup Parameters:
        jmsServerName: 
        Point-To-Point     
        brokerURL: RemoteCF
        user: swiftmq
        password: swiftmq
        clientID: null
        pingInterval: 
        transactedPublish: false
        transactedReceive: false
        singleMessageAck: false
        symbiontAdapter: false
        jmsDomain: true
    
    S-0011>(Mar 31, 2017 10:16:29:436) S-0011: receive message queue size set to 10
    S-0011>(Mar 31, 2017 10:16:29:437) S-0011: browse message queue size set to 500
    S-0011>(Mar 31, 2017 10:16:29:437) : In SessionContainer()
    S-0011>(Mar 31, 2017 10:16:29:441) : Looking up ConnectionFactory in JNDI Object Store
    S-0011>(Mar 31, 2017 10:16:29:442) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: Using connection values: 26,null,true,,true,false,-1,-1,false,0,false,false,,10000,0,30,false,60,0,20,0,,swiftmq,swiftmq,depotest2,localhost
    S-0011>(Mar 31, 2017 10:16:29:628) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: A JMS session has been created. (9291)
    Thread-30>(Mar 31, 2017 10:16:29:636) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: receive(): Request to receive from: TEST.Q. 
    Thread-31>(Mar 31, 2017 10:16:29:636) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: getNextMessage(): Client requests next message.
    Thread-30>(Mar 31, 2017 10:16:29:640) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: createListener(): Message listener is set.
    Thread-30>(Mar 31, 2017 10:16:29:641) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: start(): Starting message reception.
    Thread-30>(Mar 31, 2017 10:16:29:642) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: start(): Message reception started.
    S-0019>(Mar 31, 2017 10:30:33:797) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: stop(): Stopping message reception.
    S-0019>(Mar 31, 2017 10:30:33:802) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: stop(): Message reception stopped.
    S-0019>(Mar 31, 2017 10:30:33:802) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: Client was disconnected without calling deleteSession()! (9294)
    Thread-31>(Mar 31, 2017 10:30:33:802) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: getNextMessage(): Sending SHUTDOWN message  to the client.
    S-0019>(Mar 31, 2017 10:30:33:805) 172.25.197.193::sonicMQ1::3620::2a52856389d3b6a3:-6eb6a82c:15b23327852:-7fdc: The JMS session has been closed. (9295)
  • Hi Fuelfire,

    Please find the attached sample pcode to produce and consume the messages.

    8688.sample.zip

    Thank,

    Anand.

  • Anand, thank you. I read in the manual that I must use waitForMessages when in AppServer environment and in batch application. Well, I modified the programs.

    4214.Archive.rar

    Hope it helps somebody.

    In case I specify in this procedure "?" for a time interval, and there are no messages in the queue, my program starts to wait for it and stops responding. 

    RUN waitForMessages IN ptpsession ("inWait", THIS-PROCEDURE, ?).

    I decided to set the interval in 5 seconds to make the program complete.

    RUN waitForMessages IN ptpsession ("inWait", THIS-PROCEDURE, 5).

    If there are no messages in the queue, the program actually ends in 5 seconds.. But!!! I noticed such strange behavior: in the event that I put one message in the queue (and it's in the queue really one), I can get it not once but 5, 9 times. 

    The message is not picked up from the queue at once. I do not understand why. If I call the procedure like this:

    RUN waitForMessages IN ptpsession ("inWait", THIS-PROCEDURE, ?).

    I get the message the first time..

    I could stay on this variant, but then I should understand when to interrupt the execution of the program in case there are no messages in the queue.

    Thanks!

  • I'll correct myself. It does not matter what time interval in waitForMessages:?, 5, 10. For some reason, not the first time the last message of the queue is read. I receive the last message a few times before it is really removed from the queue. This is problem.

  • Has anyone encountered such problem?

  • Hello, everybody! I will try to show the the problem on example.

    Here, the program for message receiving:

    /* ***************************  Main Block  *************************** */
    DEFINE VAR QueueManager AS CHAR NO-UNDO.
    DEFINE VAR QueueName AS CHAR NO-UNDO.
    DEFINE VAR CMessage AS CHAR INITIAL "" NO-UNDO.
    DEFINE VARIABLE cErr AS CHAR FORMAT "X(255)" NO-UNDO.
    
    DEFINE VARIABLE ptpsession AS HANDLE.
    DEFINE VARIABLE consumerH AS HANDLE.
    DEFINE VARIABLE stillWaiting AS LOGICAL NO-UNDO INITIAL TRUE.
    
    ASSIGN QueueManager = "RemoteCF"
                    QueueName = "TEST.Q".
    
    /* Creates a session object. */
    RUN jms/jmssession.p PERSISTENT SET ptpsession ("-H localhost -S 3620 -AppService AD.sonicMQ1 -DirectConnect") NO-ERROR.
    IF ERROR-STATUS:ERROR
    THEN DO:
                ASSIGN cErr = ERROR-STATUS:GET-MESSAGE(1).
                RETURN "1".            
    END.
    
    RUN setBrokerURL      IN ptpsession (INPUT QueueManager) NO-ERROR.
    IF ERROR-STATUS:ERROR
    THEN DO:
                ASSIGN cErr = ERROR-STATUS:GET-MESSAGE(1).
                RETURN "1".            
    END.
    
    /* Set user credentials. */
    RUN setUser           IN ptpsession (INPUT "swiftmq").
    RUN setPassword       IN ptpsession (INPUT "swiftmq").
    
    /* Connect to the broker. */
    RUN beginSession IN ptpsession NO-ERROR.
    IF ERROR-STATUS:ERROR
    THEN DO:
                ASSIGN cErr = ERROR-STATUS:GET-MESSAGE(1).
                RETURN "1".            
    END.
    
    /* Subscribe to the Sample.Q1 queue. Messages are handled by the "messageHandler" internal procedure. */
    RUN createMessageConsumer IN ptpsession (THIS-PROCEDURE,   /* This proc will handle it */
                                             "messageHandler", /* name of internal procedure */
                                             OUTPUT consumerH).
      
    /* Do not create a new message for each received message */
    RUN setReuseMessage IN consumerH.
    
    RUN receiveFromQueue IN ptpsession (QueueName,                      /* name of queue */
                                                                    ?,                                      /* No message selector */
                                                                    consumerH) NO-ERROR. /* Handles incoming messages*/
    IF ERROR-STATUS:ERROR
    THEN DO:
                ASSIGN cErr = ERROR-STATUS:GET-MESSAGE(1).
                RETURN "1".            
    END.
       
    /* Start receiving messages              */
    RUN startReceiveMessages IN ptpsession.
    
    RUN waitForMessages IN ptpsession ("inWait", THIS-PROCEDURE, 5) NO-ERROR.
    IF ERROR-STATUS:ERROR
    THEN DO:
                ASSIGN cErr = ERROR-STATUS:GET-MESSAGE(1).
                MESSAGE cErr VIEW-AS ALERT-BOX.
                RETURN "1".            
    END.
    
    RUN deleteSession IN ptpsession.
    
    MESSAGE cMessage VIEW-AS ALERT-BOX.
    RETURN "0".
    
    PROCEDURE messageHandler:
        DEFINE INPUT PARAMETER messageH AS HANDLE.
        DEFINE INPUT PARAMETER msgConsumerH AS HANDLE.
        DEFINE OUTPUT PARAMETER replyH AS HANDLE.
       
        /* Creates a reply message. The reply is published automatically when
        control returns to the ABL-JMS implementation.
        */
        ASSIGN CMessage = DYNAMIC-FUNCTION('getText':U IN messageH).
            
        RUN deleteMessage IN messageH.       
        ASSIGN stillWaiting = FALSE.    
    
    END.
    
    FUNCTION inWait RETURNS LOGICAL:
            RETURN stillWaiting.
    END.
    

    When I run this program, I get the last message in the queue several times. If I delete string 

    RUN deleteSession IN ptpsession.

    I get the last message once (and it's correct). But there is a line
    Client was disconnected without calling deleteSession()! (9294)
    in the soniqMQ1.server.log.
    That is, if I do not delete the session, the program works correctly. This is normal?

  • Hello, everybody! I did several tests and now the problem is more or less clear. In the event that messages are received through the application server (I use PASOE), there is a problem when the message is received, but it remains in the queue. So I get some messages several times. If you receive messages directly from the client, then everything is OK!

    In accordance with the regulations, I must communicate with the WebSphere MQ in the "server-server" scheme. Therefore, a working solution: connecting to the Sonic adapter directly from the client is not acceptable. Has anyone encountered a similar problem?