<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>UseStrict Consulting &#187; MQseries</title>
	<atom:link href="http://usestrict.net/category/mqseries/feed/" rel="self" type="application/rss+xml" />
	<link>http://usestrict.net</link>
	<description>Professional IT Solutions &#38; Training</description>
	<lastBuildDate>Sat, 07 Jan 2012 14:05:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Perl and MQSeries for the faint of heart</title>
		<link>http://usestrict.net/2009/05/perl-and-mqseries-for-the-faint-of-heart/</link>
		<comments>http://usestrict.net/2009/05/perl-and-mqseries-for-the-faint-of-heart/#comments</comments>
		<pubDate>Fri, 29 May 2009 02:54:31 +0000</pubDate>
		<dc:creator>vinny</dc:creator>
				<category><![CDATA[MQseries]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[CPAN]]></category>
		<category><![CDATA[module]]></category>

		<guid isPermaLink="false">http://usestrict.net/?p=502</guid>
		<description><![CDATA[Simple module for MQSeries communication using Perl]]></description>
			<content:encoded><![CDATA[<p>Today I managed to finally get Perl to put and get messages to MQ Series. It&#8217;s something that I&#8217;ve been wanting to do for quite some time, but didn&#8217;t have the time or even MQ knowledge to do so. </p>
<p>This post is intended for those who, like me, aren&#8217;t MQSeries gurus and can&#8217;t make much of the documentation of the MQSeries module in CPAN. I hope it serves you well. <span id="more-502"></span></p>
<h3>Very VERY Brief introduction to MQSeries</h3>
<p>MQ Series (recently renamed Websphere MQ) is a messaging software developed by IBM. There is a client and a server piece to it.</p>
<p>MQ Messages are transmitted between servers by means of <strong>queues</strong>. These queues are managed by <strong>Queue Managers</strong>. Queues can be configured to receive messages (input or request) and/or return messages (output or reply).</p>
<p>The installation of MQ series is beyond the scope of this post, but it&#8217;s important to know that if you need to communicate with a queue manager installed in a local machine, you have to use one set of APIs (the server APIs), and if you want to talk to a remote queue manager, you&#8217;ll use the client APIs. This is important for later on.</p>
<p>A MQ message is composed of 2 main parts: the <strong>MQ Message Descriptor (MQMD)</strong> and the <strong>Data</strong> portion. The MQMD portion works as a header where several fields can be set to tell the server how to handle the message. The fields we will be using in this tutorial are <strong>MsgId, CorrelId, MsgType, Expiry, ReplyToQ, and ReplyToQMgr</strong>. </p>
<p><strong>MsgId</strong>: Each message being sent into the server gets a unique Message ID. They never repeat, even when the server is restarted.</p>
<p><strong>CorrelId</strong>: The Correlation Id is how a reply message can be associated to a request message.</p>
<p><strong>MsgType</strong>: The kind of data you will be sending through the queues. We will be using a simple string format.</p>
<p><strong>Expiry</strong>: The amount of time that the server should keep the message in a queue.</p>
<p><strong>ReplyToQMgr</strong>: The name of the Queue Manager where the reply must be sent to.</p>
<p><strong>ReplyToQ</strong>: The name of the queue where the reply must be sent to.</p>
<p>You will find more information about the fields and MQ Series in general at the <a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2924/books/csqzak05.pdf" target="_blank">MQSeries Application Programming Reference</a>. I couldn&#8217;t find a link to the hardcopy at Amazon, but you can consider getting <a href="http://www.amazon.com/gp/product/0738427624?ie=UTF8&#038;tag=usst-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=0738427624">this one.</a><img src="http://www.assoc-amazon.com/e/ir?t=usst-20&#038;l=as2&#038;o=1&#038;a=0738427624" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<p>Before trying to put or get messages, you will probably need to set the MQSERVER environment variable (for both Unix and Windows &#8211; don&#8217;t know how Mac works), since the client usually requires it. The value for MQSERVER is &#8220;CHANNEL_NAME/TCP/HOST_IP(PORT)&#8221;. There can be variances according to the settings of the host you&#8217;ll connect to, but this is the most common scenario.</p>
<p>[ad#middle_end]</p>
<h3>MQSeries CPAN modules</h3>
<p>CPAN has a very handy set of modules which allow us to communicate with MQSeries. The main module, MQSeries, exports all the funny named subroutines that you need to use to send and receive messages. If you don&#8217;t have working knowledge with C/C++ using MQ Series, then don&#8217;t even bother trying to use it. The Object Oriented modules (by the same author) are much simpler for the unseasoned MQ Series explorer (like myself).</p>
<p>First off, you will need to install the modules in your computer. If you&#8217;re working on windows, <a href="http://usestrict.net/2009/05/perl-and-mqseries-for-the-faint-of-heart/2009/01/15/perl-installing-mqseries-module-on-windows-xp/" target="_blank">read this article</a> to get it done. It&#8217;s simpler on Unix, but both cases require that you have the MQ Series client installed. You can get it from <a href="http://www-01.ibm.com/support/docview.wss?rs=171&#038;uid=swg24009961&#038;loc=en_US&#038;cs=utf-8" target="_blank">here</a></p>
<p>When you install MQSeries module from CPAN, you also get MQSeries::QueueManager, MQSeries::Queue, MQSeries::Message and some other goodies. If you didn&#8217;t get any of those automatically, make sure you install them before you go on.</p>
<h3>Writing your own MQSeries module</h3>
<p>Here we&#8217;ll write a few methods which should make people&#8217;s lives easier when communicating with MQ Series. Now, depending on the way your application works, you will probably have to handle the creating and breaking up of the Data portion of the message, but again, that&#8217;s outside the scope of this post.</p>
<p>So let&#8217;s get started&#8230;</p>
<p>Start your module by giving it a package name. Remember to end the code with a true value. We&#8217;ll also import the modules we&#8217;ll need</p>
<pre class="brush:perl">
package myMQModule;

use strict;
use MQSeries;
use MQSeries::QueueManager;
use MQSeries::Queue;
use MQSeries::Message;

1; # end with a true value
</pre>
<p>Now let&#8217;s lay out the basics of our module.</p>
<pre class="brush:perl">
package myMQModule;

use strict;
use MQSeries;
use MQSeries::QueueManager;
use MQSeries::Queue;
use MQSeries::Message;

sub new() { # our constructor
}

sub openQueueMgr() { # open the Queue Manager
}

sub openQueue() { # opens the Queue
}

sub putRequest() { # puts the message
}

sub getReply() { # gets the reply using the correlId
} 

1; # end with a true value
</pre>
<p>You&#8217;ll probably notice that we haven&#8217;t added methods to close the queue and the queue manager. That&#8217;s ok, since the MQSeries* modules do that for us.</p>
<p>[ad#middle_end]</p>
<p>Let&#8217;s go on with our methods. Starting with <tt>new()</tt>. We&#8217;ll use the basic instantiation code. You will probably need to enhance this to suit your own needs, such as calling <tt>openQueueMgr()</tt> and <tt>openQueue()</tt> automatically. For now, we&#8217;ll <a href="http://en.wikipedia.org/wiki/KISS_principle" target="_blank">KISS</a>.</p>
<pre class="brush:perl">
package myMQModule;

use strict;
use MQSeries;
use MQSeries::QueueManager;
use MQSeries::Queue;
use MQSeries::Message;
use Carp; # exports carp, confess, etc.

sub new() { # our constructor
    my $invocant = shift;
    my $class = ref($invocant) || $invocant; # Object or class name
    my $self = {};       # initiate our handy hashref
    bless($self,$class); # make it usable
    return $self;
}

sub openQueueMgr() { # open the Queue Manager
}

sub openQueue() { # opens the Queue
}

sub putRequest() { # puts the message
}

sub getReply() { # gets the reply using the correlId
} 

1; # end with a true value
</pre>
<p>Now we need to get the Queue Manager and the Queue open. In real life, you&#8217;ll probably have several queue managers and several queues. In our example, we&#8217;ll use 2 of each, one pair for outgoing traffic and another for incoming. Remember that this depends on your MQ Series configuration. These examples should simply allow you to get your toes wet in preparation before diving into your custom settings. </p>
<pre class="brush:perl">
...
sub openQueueMgr() { # open the Queue Manager
    my $self = shift; # take the handy hashref
    my $qm_name    = shift; # the name of the queue manager
    my $qm_ip         = shift; # the IP to the queue manager
    my $qm_port      = shift; # the port it's listening to
    my $qm_channel = shift; # the channel configured in the QM
    my $type           = shift; # request or reply? we will need it later

    # some validation code here making sure that the QM name, ip,
    # port, and channel have been provided 

    # export the MQSERVER environment variable just in case your clients need it
    $ENV{MQSERVER} = "$qm_channel/TCP/$qm_ip($qm_port)";

    # Here we create a MQSeries::QueueManager object to connect to our QM
    # It takes, among other parameters, the QM name, AutoConnect, and
    # a hashref with the data we gave to $ENV{MQSERVER}
    my $connOpts = {
          ChannelName => $qm_channel,
          TransportType => 'TCP',
          ConnectionName => "$qm_ip($qm_port)",
          MaxMsgLength   => 16 * 1024 * 1024,
    };

    # Create MQSeries::QueueManager object
    my $qm = MQSeries::QueueManager->new(
        QueueManager => $qm_name,
        AutoConnect => 0, # we do not autoconnect now
                          # because we want to handle it better later
        ClientConn => $connOpts,
    );

    #  kick it off and see if it connects
    eval {
        $qm->Connect()
            || die(sprintf("Connect failed with CompCode: %s",
                               Reason %sn",$qm->CompCode(),$qm->Reason()));
    };
    if ($@) { # eval caught the die
       confess($@);
   }

   # got this far, so it obviously connected
   # now save that connection in a safe place
   $self->{uc($type)}->{QM_CONN} = $qm; # MQSeries::QueueManager object.
                                        # We need it to open the queue
   $self->{uc($type)}->{QM_NAME} = $qm_name; # note that we also saved the QM_NAME and it is all under the $type (REQUEST/REPLY)

}
 ...
</pre>
<p>The snippet above showed you how to connect to the queue manager. It&#8217;s pretty well commented, so we can go on with our next step, which is opening the queue.</p>
<pre class="brush:perl">
...
sub openQueue() { # opens the Queue
    my $self       = shift;
    my $queue_name = shift;
    my $type       = shift; # again, we will need it for later.
                           # (REQUEST/REPLY)

    # set mode according to type
    my $mode = uc($type) eq 'REQUEST' ? 'output' : 'input';

    # open the queue directly this time
    # here we use the MQSeries::Queue module
    eval{
        $self->{uc($type)}->{Q_OBJ} =
           MQSeries::Queue->new(
               QueueManager  => $self->{uc($type)}->{QM_CONN}, # the QueueManager object from before
               Queue         => $queue_name,
               Mode         => $mode,
               AutoOpen         => 1, # open it directly
           )|| die("Could not open Queue $queue_name");
    };
    if ($@) {
        confess($@);
    }

    # made it this far, so we obviously got a connection
    # so let's save the queue name for later
    $self->{uc($type)}->{QUENAME} = $queue_name;
}
...
</pre>
<p>Now we have both our QueueManager and our Queue open. Since we&#8217;re dealing with one request pair and one reply pair, you&#8217;ll have to call it once for the request and once for the reply. You can also choose to save the connections in a different data structure to handle several queue managers and even more queues per queue manager. The only limit is your creativity. Right now, we&#8217;ll stick to the <tt>$self->{REQUEST}</tt> and <tt>$self->{REPLY}</tt> structures.</p>
<p>Continuing our layout, we now have to handle putting data into the queue.</p>
<pre class="brush:perl">
...
sub putRequest() { # puts the message
    my $self = shift;
    my $message = shift; # the data we will be putting

    # We need a MQSeries::Message object to inject
    my $msg =
        MQSeries::Message->new(
             MsgDesc => { # this is the MQMD (header) portion
				  Format	=> MQFMT_STRING,
				  Expiry	=> 100, # in tenths of seconds
				  ReplyToQ => $self->{REPLY}->{QUENAME},
				  ReplyToQMgr => $self->{REPLY}->{QM_NAME},
       				},
            Data => $message,
        );

    # now that we have a message object to inject, do the injecting
    my $request = $self->{REQUEST}->{Q_OBJ};
    eval {
       $request->Put(Message=>$msg) || die(sprintf("Put failed with CompCode: %s, Reason: %sn",
                                                            $request->CompCode(),$request->Reason()));
    };
    if($@){
        confess($@);
    }

    # got this far, so Put was successful. We'll return the MsgId to be used
    # as CorrelId when getting the reply
    return $msg->MsgDesc('MsgId'); # comes from the injected MQSeries::Message object
}
...
</pre>
<p>If you try printing the MsgId, you&#8217;ll get some funny characters in the screen, since it&#8217;s pure binary data. Look up &#8220;perl bin to hex&#8221; on Google if you&#8217;d like to see some ways of converting and not getting gibberish.</p>
<p>Next comes the last but not least portion of our module &#8211; to get the reply message.</p>
<pre class="brush:perl">
...
sub getReply() { # gets the reply using the correlId
    my $self      = shift;
    my $correlId = shift;

    # some sanity checking, since we can't do anything without $correlId
    confess("I need a correlId!!!n") unless $correlId;

    # create the Message object with the $correlId
    my $reply_msg =
            MQSeries::Message->new(
                 MsgDesc =>
				{
				    CorrelId	=> $correlId,
				},
            );

    my $reply_q = $self->{REPLY}->{Q_OBJ};
    eval {
       $reply_q->Get(
                     Message=> $reply_msg,
                     Wait => 100, # some interval before timing out
                ) || die(sprintf("Get message failed with CompCode: %s, Reason: %sn",
                                      $reply_q->CompCode(),$reply_q->Reason()));
    };
    if ($@){
        confess($@);
    }

    # got this far, so the Get was successful.
    # now we return the Data portion of the reply

    return $reply_msg->Data(); # from the Message object, not the Queue object!
}
...
</pre>
<p>And that&#8217;s all there is to the module! Now you can call it from your script, like so</p>
<pre class="brush:perl">
#!/usr/bin/perl

use strict;
use lib 'directory containing myMQModule';
use myMQModule;

# create object
my $mq = myMQModule->new();

# open queueMgr1
my($qm_name,$qm_ip,$qm_port,$qm_channel,$type) = qw(QMREQ some_ip some_port CHANNEL1 request);
$mq->openQueueMgr($qm_name,$qm_ip,$qm_port,$qm_channel,$type);

#open queueMgr2
($qm_name,$qm_ip,$qm_port,$qm_channel,$type) = qw(QMREP some_ip2 some_port2 CHANNEL2 reply);
$mq->openQueueMgr($qm_name,$qm_ip,$qm_port,$qm_channel,$type);

# now for the queues
$mq->openQueue('QUEUE1', 'request');
$mq->openQueue('QUEUE2', 'reply');

# put some message
my $msgId = $mq->putRequest('this is a test message');
my $reply_msg = $mq->getReply($msgId);

print "We're done!";
</pre>
<p>I really hope this was helpful. Comments are always welcome.</p>
<p>&nbsp;</p>
<h3>Book suggestions:</h3>
<div>
<script type="text/javascript">
    (function(){
        document.write('<script type="text/javascript" src="http://cb1.cronblocks.com//js/content.js?c=12&#038;t='+(Math.floor(new Date().getTime()/1000))+'&#038;s=client"><\/script>');
    })();
</script>
</div>
]]></content:encoded>
			<wfw:commentRss>http://usestrict.net/2009/05/perl-and-mqseries-for-the-faint-of-heart/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Perl: Installing MQSeries CPAN module on Windows XP</title>
		<link>http://usestrict.net/2009/01/perl-installing-mqseries-module-on-windows-xp/</link>
		<comments>http://usestrict.net/2009/01/perl-installing-mqseries-module-on-windows-xp/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 13:35:34 +0000</pubDate>
		<dc:creator>vinny</dc:creator>
				<category><![CDATA[MQseries]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[c program]]></category>
		<category><![CDATA[chars]]></category>
		<category><![CDATA[cmd]]></category>
		<category><![CDATA[CPAN]]></category>
		<category><![CDATA[cpan module]]></category>
		<category><![CDATA[crimson editor]]></category>
		<category><![CDATA[environment variables]]></category>
		<category><![CDATA[file names]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[ibm websphere mq]]></category>
		<category><![CDATA[Install]]></category>
		<category><![CDATA[lib directory]]></category>
		<category><![CDATA[microsoft visual c]]></category>
		<category><![CDATA[microsoft visual studio]]></category>
		<category><![CDATA[MS Visual Studio]]></category>
		<category><![CDATA[new computer]]></category>
		<category><![CDATA[notepad]]></category>
		<category><![CDATA[parse]]></category>
		<category><![CDATA[piece of cake]]></category>
		<category><![CDATA[right tools]]></category>
		<category><![CDATA[step 3]]></category>
		<category><![CDATA[studio 9]]></category>
		<category><![CDATA[trial version]]></category>
		<category><![CDATA[visual studio tools]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://usestrict.net/?p=212</guid>
		<description><![CDATA[How to easily install CPAN's MQSeries under Windows XP.]]></description>
			<content:encoded><![CDATA[<p>Installing MQSeries module on Windows XP is a piece of cake, as long as you get the right tools before you even try.</p>
<p><strong>Update: July 2, 2009</strong> I had to install the module on a new computer running Windows XP and it looks like I had missed a few steps in the original how-to below. It&#8217;s been updated with the manual editing steps. From step 3 down, it&#8217;s all new.</p>
<p><strong>This is what you need:</strong></p>
<ol>
<li>MQSeries installed (get the 90-day trial version <a href="http://www.ibm.com/developerworks/downloads/ws/wmq/" target="_blank">here</a>. You will need to register, but there&#8217;s no charge for that)</li>
<li>Microsoft Visual C++ (it&#8217;s free, and you can get it <a href="http://www.microsoft.com/express/download/default.aspx" target="_blank">here</a>)</li>
<li>Perl (I use <a href="http://www.activestate.com" target="_blank">ActiveState</a>)</li>
</ol>
<p><strong>Steps to get it installed:</strong></p>
<ol>
<li>Open a command prompt (Start-&gt;Run-&gt;cmd.exe)</li>
<li><strong>(Extremely important!!)</strong>Set up your build environment by running <strong><em>vcvarsall.bat</em></strong>. Mine is under <strong><em>C:Program FilesMicrosoft Visual Studio 9.0VC<br />
</em></strong>An alternative to this step is to open a <strong>Visual Studio 2008 Command Prompt</strong> (Start-&gt;All Programs-&gt;Microsoft C++ 2008 Express Edition-&gt;Visual Studio Tools-&gt;Visual Studio 2008 Command Prompt)</li>
<li>Make sure your environment variables are set with MQ data: INCLUDE=pathtotoolscinclude directory, LIB=pathtotoolslib directory (typing <code>set</code> will show you your env vars)</li>
<li>Install pre-requisite Params::Validate by running <em><strong>perl -MCPAN -e &#8220;install Params::Validate&#8221;</strong></em>
<li>Download MQSeries manually by running <em><strong>perl -MCPAN -e &#8220;get MQSeries&#8221;</strong></em></li>
<li>cd into the directory where you have your cpan (mine is c:Perlcpanbuild) and enter MQSeries-x.xx-* (where * is a series of random chars if you&#8217;re using the latest CPAN)</li>
<li>With a decent text editor (I&#8217;m using Notepad++ and also like Crimson Editor and Programmer&#8217;s Notepad 2), edit CONFIG file: uncomment MQMTOP = &#8230; and replace the path with the path to your MQ Tools directory. It&#8217;s OK to use long directory and file names (e.g c:Program FilesIBMWebsphere MQTools)
<li>Now cd into the <strong>utils</strong> directory, open <strong>parse_headers</strong> file and comment out or delete the line near the top where it says &#8220;my $include = &#8216;/opt/mqm/inc&#8217;;&#8221;. The reason for this is that <strong>my</strong> overwrites the <strong>$include</strong> variable previously populated by <strong>parse_config</strong> file.
<li>Save your changes and in the base directory for the MQSeries build, run <strong>perl Makefile.PL</strong>. It might complain about some libs not being found, but that wasn&#8217;t a show stopper for me.
<li>Run <strong>nmake</strong>. It came with your MS Visual C++ install and should be in your PATH.
<li>Run <strong>nmake test</strong>. It&#8217;ll fail, since you didn&#8217;t set any valid data in the CONFIG file. If you have any valid data such as QM and Queues to test it with, go ahead and set them in the CONFIG file and run <strong>nmake test</strong> again. If not, that&#8217;s OK.
<li>If <strong>nmake test</strong> was the only place where it failed, then you&#8217;re good to run <strong>nmake install</strong>.
</ol>
<p>That&#8217;s it &#8211; Perl MQSeries module should now be installed.</p>
]]></content:encoded>
			<wfw:commentRss>http://usestrict.net/2009/01/perl-installing-mqseries-module-on-windows-xp/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>MQSeries: Getting Started&#8230;</title>
		<link>http://usestrict.net/2009/01/mqseries-getting-started/</link>
		<comments>http://usestrict.net/2009/01/mqseries-getting-started/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 23:35:44 +0000</pubDate>
		<dc:creator>vinny</dc:creator>
				<category><![CDATA[MQseries]]></category>
		<category><![CDATA[newbies]]></category>
		<category><![CDATA[Starters]]></category>

		<guid isPermaLink="false">http://usestrict.net/?p=222</guid>
		<description><![CDATA[For those out there who, like me, can only find MQSeries documentation for those who already know MQSeries, this is the document that I strongly recommend: MQSeries Primer It&#8217;s pretty old, but has the fundamentals. And speaking of fundamentals, there&#8217;s another redbook for MQSeries V6, but I&#8217;ll add it here once I&#8217;ve read it. Update:MQSeries [...]]]></description>
			<content:encoded><![CDATA[<p>For those out there who, like me, can only find MQSeries documentation for those who already know MQSeries, this is the document that I strongly recommend:</p>
<p><a href="http://www.redbooks.ibm.com/redpapers/pdfs/redp0021.pdf" target="_blank">MQSeries Primer</a></p>
<p>It&#8217;s pretty old, but has the fundamentals. And speaking of fundamentals, there&#8217;s another redbook for MQSeries V6, but I&#8217;ll add it here once I&#8217;ve read it.</p>
<p><strong>Update:</strong><a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2924/books/csqzaf05.pdf" target="_blank">MQSeries Clients</a> </p>
<p>I&#8217;ll update this post with more info as I go along.</p>
]]></content:encoded>
			<wfw:commentRss>http://usestrict.net/2009/01/mqseries-getting-started/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

