Service consumer NET consumer

Our .NET consumer will be implemented as a "fat client" .NET assembly created in C# in a similar manner to that used in previous scenarios. This assembly will use the MQ Classes for .NET to create a properly formatted request message and put it to a queue. Code will also be provided to obtain the response from the queue.

1. Create a new .NET solution. To do this, open Microsoft Visual Studio.NET and create a New Project. Use the Windows Application template from the New Project dialog so that we are creating a Windows application based on Windows.Forms. You will need to select a name and location; we chose FatClientConsumerAsynch. Once you click OK, your Windows.Forms project will be created with a blank dialog.

2. As depicted in Figure 5-8 on page 247, we added a few text boxes to contain input values (called tbArg1 and tbArg2) and the result (called tbResul t) and also added a button which we called OurButton, in which we will implement our code.

Wpf Adorner
Figure 5-8 The Windows Form for our .NET fat client consumer

3. The first step in implementing the code is to create a reference to the MQ Classes for .NET so we can use them. There are two steps to this process. First, add a project reference within Solution Explorer by right-clicking References under the project we just created and selecting Add Reference

4. In the resulting dialog under the .NET tab, choose to browse for a DLL and select the amqmdnet.dll under <WebSphere_MQ_Root>\bin.

5. Once the button is placed on the form, double-clicking it will bring up the code that will be executed when the button is pushed. For the sake of keeping our example as simple as possible, we have chosen to implement all our code here.

6. Add a using statement at the top of the C# code, beneath the existing using statements, as shown in Figure 5-9 on page 248.

After executing these steps, your project should look something like Figure 5-9. Note the using statement on the left and the amqmdnet reference in the Solution Explorer.

Figure 5-9 References required for the use of MQ Classes for .NET

Putting messages via MQ Classes for .NET

Now we are ready to create code to put the request messages that will drive our calculator service provider. In order to do this, complete the following steps:

1. Create an instance of MQQueueManager. This object abstracts the WebSphere MQ Queue Manager with which we are interacting to obtain access to queues. Creation of this object is slightly different depending on whether you are using the default Queue Manager, or whether the application is running on an MQSeries® Client or an MQSeries Server. See the documentation for more details. The code to create this object for us was as follows:

// MQQueueManager instance

MQQueueManager mqQMgr;

// use default queue manager mqQMgr = new MQQueueManager("redbookQM");

2. Once a new instance of the MQQueueManager object has been created, we can open the queue of our choice. WebSphere MQ requires you to specify the actions you intend to take upon a queue when opening it and defines the constants used to do so. These constants are exposed via the MQ Classes for .NET through the MQ.MQC public interface. For more information, see the WebSphere MQ documentation and the service pack documentation. The code we used to open our queue, called "inQ" for output (writing messages), is as follows:

MQQueue mqQueue; // MQQueue instance

String queueName; // Name of queue to use queueName = "redbookQ";

mqQueue = mqQMgr.AccessQueue( queueName, // the name of the queue MQC.MQOO_OUTPUT // open queue for output

+ MQC.MQOO_FAIL_IF_QUIESCING ); // don't if MQM stopping

3. Once we have opened the queue, we are ready to create our message. We simply created a string from the text values of tbArg1 .text and tbArg2. The MQ Classes for .NET abstract the message into an object as well as the MQ Put Message Options. For more information on the Put Message Options, see the WebSphere MQ documentation. The steps involved here are to create a string message, declare its length, create an instance of the message object, load the string message into that object, create Put Message Options and set them as desired. Once this is complete, we are ready to put our message. The code to prepare our message looks like this:

// declare variables and objects required

MQMessage mqMsg; // MQMessage instance

MQPutMessageOptions mqPutMsgOpts; // MQPutMessageOptions instance int msgLen; // Message length

String message; // Message buffer

// create message message = tbArgl.Text + "," + tbArg2.Text;// create message msgLen = message.Length;// set message length mqMsg = new MQMessage();// new message instance mqMsg.WriteString( message );// load message w/payload mqMsg.Format = MQC.MQFMT_STRING;// declare format mqMsg.ReplyToQueueManagerName = "QM1";// send replies to this QM mqMsg.ReplyToQueueName = "replyQ";// send replies to this queue mqPutMsgOpts = new MQPutMessageOptions();// declare options

4. Once the message is created, you simply call the Put method on our Queue object, passing the Message object and the Put Options object into it.

// put message on queue mqQueue.Put( mqMsg, mqPutMsgOpts ); tbResult.Text = "Message has been sent...";

5. Lastly, any of the previous calls could generate an error from WebSphere MQ. The MQ Classes for .NET encapsulate errors and throw them to you as an MQException object. We can utilize a try/catch block to handle these errors. To do this, we wrap all of the above code in a try { ... } and create a catch { ... } block that looks like this:

catch (MQException mqe) {

// stop if failed tbResult.Text = "The following MQ error occurred: " + mqe.Message;

6. Now build the assembly by clicking Build -> Build Solution and you are done with the side of the consumer that puts requests.

The individual bullets above show the lines of code required to implement each logical step in our process of putting a message. Although we have implemented everything under a single method for simplicity, it is obviously possible (not to mention desirable) to separate these functions into places that make more sense for the reuse of objects.

Getting messages via MQ Classes for .NET

We will now cover getting the response messages that will be generated by the requests. The following steps are required:

1. Let's create a new button on our form and name it GetResul t. Once that is completed, double-click it to automatically create a GetResult_Cl ick method.

2. Create an instance of MQQueueManager. This is exactly the same as was done under "Putting messages via MQ Classes for .NET" on page 248. Since this object can be shared, a good alternative to doing this under both methods would be to create this object under form construction rather than in each method. In order to do this, simply make the object definition global in scope and create the new instance after the InitializeComponent( ); statement in the Form1( ) constructor.

3. Invoke the AccessQueue( ) method on our MQQueueManager object to create a new MQQueue object and open the queue for input. Our code looks like this:

MQQueue mqQueue; // MQQueue instance

String queueName; // name of queue to use queueName = "replyQ" // name of the queue to open mqQueue = mqQMgr.AccessQueue( queueName,

MQC.MQOO_INPUT_AS_Q_DEF // open queue for input + MQC.MQOO_FAIL_IF_QUIESCING ); // but not if MQM stopping

4. Create a message object to hold the message we are about to get off of the queue. The message object is of type MQMessage. We define an object of this type and then create a new instance of it:

// create message

MQMessage mqMsg; // MQMessage instance mqMsg = new MQMessage();

5. Create a MQGetMessageOptions object to define how we are going to get these messages. The MQGetMessageOptions object abstracts the MQ Get Message Options. For a full description of the capabilities, see the WebSphere MQ documentation. Here, we use the Get Message Options to set a Waitlnterval for our Get. This tells WebSphere MQ how long we would like to wait for a new message assuming one is not immediately available.

MQGetMessageOptions mqGetMsgOpts; // MQGetMessageOptions instance mqGetMsgOpts = new MQGetMessageOptions();

mqGetMsgOpts.WaitInterval = 3000; // 3 second limit for waiting

6. Now we are ready to get our message. We do so, we invoke the Get( ) method on the queue object we created, passing both the newly created message object and the newly created Get Message Options.

mqQueue.Get( mqMsg, mqGetMsgOpts );

7. If a string message was returned, it is accessed via the ReadString( ) method on the message object we created. We display it for the user:

tbResult.Text = mqMsg.ReadString(mqMsg.MessageLength);

8. As before, errors are thrown as an MQException and caught via a try/catch block. Unlike before, errors can actually be normal. One "normal" error is No Message Avail able, which simply means that no messages were on the queue to be read. So, we surround the above code in a try { ... } and implement a catch { ... } to evaluate what happened in the event of an error. As before, the MQC:

catch (MQException mqe) {

// report reason, if any if ( mqe.Reason == MQC.MQRC_NO_MSG_AVAILABLE ) {

// special report for normal end tbResult.Text = "No message to read.";

// general report for other reasons tbResult.Text = "MQ returned error: " + mqe.Message;

9. If you test your application at this point, you will see that the returned value shown in the window is wrong; it shows RFH. What happened is that WebSphere put a JMS message in the reply queue and the .NET Classes for MQ do not recognize the JMS message format. The solution is to write your own message formatter using the API and parse the message. Replace and insert the following code after the // create message line in step 4 on page 251.

// create message mqMsg = new MQMessage();// create new message object mqMsg.Format=MQC.MQFMT_RF_HEADER_2; // mqMsg.Encoding = 273; // mqMsg.CharacterSet = 819; //

// great Get Message Options & set them mqGetMsgOpts = new MQGetMessageOptions();

mqGetMsgOpts.WaitInterval = 3000; // 3 second limit for waiting

// get the message mqQueue.Get( mqMsg, mqGetMsgOpts );

tbResult.Text+=mqMsg.MessageLength+"\r\n"; String str=mqMsg.ReadString(4); // "RFH " UInt32 ui32=uint_reverse(mqMsg.ReadUInt32()); // version ui32=uint_reverse(mqMsg.ReadUInt32()); // length of header ui32=mqMsg.ReadUInt32(); // encoding ui32=mqMsg.ReadUInt32(); // coded char set str=mqMsg.ReadString(8); // format "MQSTR " ui32=mqMsg.ReadUInt32(); // flags ui32=mqMsg.ReadUInt32Q; // NameValueCCSID

ui32=uint_reverse(mqMsg.ReadUInt32()); // sNameValueCCSID length str=mqMsg.ReadStri ng((int)ui32) ;

ui32=uint_reverse(mqMsg.ReadUInt32()); // sJMSfolder length str=mqMsg.ReadString((int)ui32) ; // message content str=mqMsg.ReadString(mqMsg.MessageLength); tbResult.Text="Resul ts: "+str+"\r\n";

Once you are done with the client, compile it and it is ready to run.

10.The code in the previous step requires an additional function, insert it somewhere at the top of the code.

private static uint uint_reverse(uint i) { byte[] temp = BitConverter.GetBytes(i); Array.Reverse(temp);

uint returnVal = BitConverter.ToUInt32(temp, 0); return(returnVal);

Sending a JMS message from .NET

If you would like to send a JMS message from the .NET client using the MQ classes for .NET, then you have to generate the message yourself using the MQ classes, just as the sample did when receiving the message. The following sample is a code excerpt for sending a JMS message from .NET.

Example 5-3 Sending JMS message mqMsg = new MQMessage(); // message formating settings mqMsg.Format=MQC.MQFMT_RF_HEADER_2; // mqMsg.Encoding = 273; // mqMsg.CharacterSet = 819; // // message header strings

String sNameValueCCSID="<mcd><Msd>jms_text</Msd></mcd> "; // this has to be nx4 bytes long

String sJMSfolder="<jms><Dst>queue:///default</Dst></jms> "; // this has to be nx4 bytes long ui nt i HeaderLength=(uint)(44+sNameValueCCSID.Length+sJMSfolder.Length);

// assembling the message

UTF8Encoding utf8e=new UTF8Encoding();

mqMsg.WriteBytes(utf8e.GetBytes("RFH ")); // RFH

mqMsg.WriteUInt32(uint_reverse(2)); // version mqMsg.WriteUInt32(uint_reverse(iHeaderLength)); // length of header mqMsg.WriteUInt32(uint_reverse(273)); // encoding mqMsg.WriteUInt32(uint_reverse(1208)); // coded char set ID

mqMsg.Wri teBytes(utf8e.GetBytes("MQSTR ")); //format mqMsg.WriteUInt32(uint_reverse(0)); // flags mqMsg.WriteUInt32(uint_reverse(1208)); // NameValueCCSID (UTF8)

mqMsg.Wri teUInt32(uint_reverse(ui nt_reverse((ui nt)sNameValueCCSID.Length)));

mqMsg.Wri teBytes(utf8e.GetBytes(sNameValueCCSID));

mqMsg.Wri teUInt32(uint_reverse((uint)sJMSfolder.Length));

mqMsg.Wri teBytes(utf8e.GetBytes(sJMSfolder));

// your message content mqMsg.WriteBytes(utf8e.GetBytes("A simple text message from .NET."));

// sending the message mqPutMsgOpts = new MQPutMessageOptions();

mqQueue.Put( mqMsg, mqPutMsgOpts );

} catch (MQException mqe) { // report the error

System.Console.WriteLine( "MQQueue::Put ended with " + mqe.Message );

Was this article helpful?

0 0

Post a comment