Introduction

In MQ 8 Fixpack 4 a new channel type of AMQP was added to MQ in order to support the MQ Light messaging API. It supports a subset of the AMQP 1.0 specification.

Since launching MQ Light we have delivered client libraries for Node.js®, Ruby, Python® and Java®. However we often get asking about using MQ Light from .NET.

IBM hasn’t released an MQ Light API library for .NET but since AMQP 1.0 is an open specification it is possible to connect to an AMQP channel, using all of the features of MQ Light (at-most-once & at-least-once qualities of service, shared subscriptions, message properties etc.) using the Amqp.Net Lite library.

This article will show you how you can easily connect to MQ from .NET over AMQP channels. I will follow it up with further posts describing how to use other features of the MQ Light API.

There are two notable benefits of using the MQ Light API instead of the MQ’s traditional .NET classes:

  1. The simplicity of the API makes for a less complicated application with fewer lines of messaging code
  2. The MQ .NET classes are not currently supported in .NET Core so you need to use an alternative such as MQ Light.

 

Prerequisites

This article and the ones that follow assume 2 pre-requisites:

1) That you have the .NET runtime available to test sample applications
2) That you have an IBM MQ queue manager version 8.0.0.4 or later and have started the AMQP service and an AMQP channel.

I’m not going to cover setting up queue manager security (CONNAUTH, CHLAUTH, or the necessary OS users and authority records). If your application receives MQ 2035 errors you can determine the cause by viewing the queue manager’s AMQERR01.LOG file. Ideally you should have a local OS or LDAP user defined who has authority to connect to the queue manager and put & sub to the relevant topics. You should also have a channel auth rule defined to adopt that identity based on the TLS distinguished name of the client, their IP address, or their username.

The code

The Amqp.Net Lite website provides samples and API documentation for using the library. The samples can be easily modified to follow the guidelines below and attach to a queue manager.

To begin with we will look at attaching a subscriber to consume messages from an MQ topic. To test the subscriber we will then run another application that publishes messages to the same topic.

Firstly define where the MQ AMQP channel is running:

Address address = new Address(“amqp://localhost:5672”);

Create an AMQP connection to MQ:

Connection connection = new Connection(address, SaslProfile.Anonymous, null, null);

Notes: if you use the Connection constructor that takes a single Address argument the connection will fail or you will receive an MQ return code of 2035 Not Authorised. MQ supports 2 SASL mechanisms: anonymous and plain. You must specify one of these mechanisms so if you don’t wish to authenticate the application’s username and password pass SaslProfile.Anonymous into the Connection(…) constructor.

Start a new session on the connection:

Session session = new Session(connection);

Attach a link to the session for receiving messages from MQ:

ReceiverLink receiver = new ReceiverLink(session, “private:client1:public”, “public”);

Notes: The second parameter is the name of the link. This must be unique among all other links between the client and the queue manager. Other MQ Light clients use the naming convention “private:<client-id>:<topic-string>” so I have used the same convention here. “private” distinguishes client-specific subscriptions from shared subscriptions which we will see in a subsequent post. The third parameter is the name of the topic string to subscribe to. The MQ Light sample applications all use “public” as their default topic string so I’ve done the same but you can specify any topic string including “/” delimiters and wildcards e.g. “sports/#”.

Now enter an infinite loop performing a blocking receive call to wait for messages to arrive and printing them out. We will call accept() on each message to prevent the queue manager redelivering them:

while (true)

{ Message message = receiver.Receive(); if (message != null) { Console.WriteLine(“Received ” + message.Body.ToString()); receiver.Accept(message); } }

Checking the connection

When you run the application you can check the queue manager to ensure it has connected successfully. To check that your .Net application has successfully connected check the status of the AMQP channel using runmqsc:

DIS CHSTATUS(*) CHLTYPE(AMQP) CLIENTID(*) ALL
    16 : DIS CHSTATUS(*) CHLTYPE(AMQP) CLIENTID(*) ALL

AMQ8417: Display Channel Status details.
 CHANNEL(MY.AMQP.CHANNEL) CHLTYPE(AMQP)
 CLIENTID(69854723-ca09-45b7-8162-cfce07c7b1b3)
 STATUS(RUNNING) CONNAME(0:0:0:0:0:0:0:1)
 AMQPKA(0) MCAUSER(MUSR_MQADMIN)
 CLNTUSER( ) MSGSNT(0)
 MSGRCVD(0) LSTMSGDA( )
 LSTMSGTI( ) CHSTADA(2017-11-01)
 CHSTATI(15.11.10) PROTOCOL(AMQP)

Alternatively display connections to the queue manager:

DIS CHSTATUS(*) CHLTYPE(AMQP) CLIENTID(*)
   19 : DIS CHSTATUS(*) CHLTYPE(AMQP) CLIENTID(*)

AMQ8417: Display Channel Status details.
 CHANNEL(MY.AMQP.CHANNEL) CHLTYPE(AMQP)
 CLIENTID(69854723-ca09-45b7-8162-cfce07c7b1b3)
 STATUS(RUNNING) CONNAME(0:0:0:0:0:0:0:1)
 PROTOCOL(AMQP)

Checking the subscription

In both of the commands above you may notice that the CLIENTID is not “client1” as specified in the link name but is a unique identifier. This is because the default behaviour of the Amqp.Net Lite library is to auto generate a container name and it is the container name – not the client ID specified in link names – that MQ uses to identify the client. In a subsequent post we’ll look at how you can specify your own client ID.

To check that the application has successfully created a subscription to the topic string “public” display the subscriptions that are defined on the queue manager:

DISPLAY SUB(*) TOPICSTR
 4 : DISPLAY SUB(*) TOPICSTR

AMQ8096: IBM MQ subscription inquired.
 SUBID(414D5120514D34202020202020202020A162F05925748205)
 SUB(:private:d17f6054-657d-4947-8e66-7ef89d3cd131:public)
 TOPICSTR(public)
AMQ8096: IBM MQ subscription inquired.
 SUBID(414D5120514D3420202020202020202008CBED592544F207)
 SUB(QM4 SYSTEM.BROKER.INTER.BROKER.COMMUNICATIONS 414D51590101000000000000000000000000000000000000 SYSTEM.BROKER.ADMIN.STREAM MQ/QM4 /StreamSupport)
 TOPICSTR(SYSTEM.BROKER.ADMIN.STREAM/MQ/QM4                                             /StreamSupport)
AMQ8096: IBM MQ subscription inquired.
 SUBID(414D5120514D34202020202020202020FCCAED5911267E06)
 SUB(SYSTEM.DEFAULT.SUB)
 TOPICSTR()

Create a sender application

The steps for creating a sender application are the same as the receiver up until attaching the link.

Instead of creating a ReceiverLink to consume messages, create a SenderLink:

SenderLink sender = new SenderLink(session, “private:client2:public”, “public”);

Now create a message:

Message message = new Message(“Hello AMQP!”);
message.Properties = new Properties();
message.Properties.To = “amqp://localhost:5672”;

and send it over the link:

sender.Send(message);

You should see the “Hello AMQP!” message written to the console of the receiver application.

If you run multiple copies of the receiver each instance will get a copy of the message. You can also try running one of the MQ Light samples to send and receive messages between .Net and nodejs/Ruby/Python/Java apps.

In the next article we will look at how to specify your own client ID.

Leave a Reply