Created Documentation for Writing a CPP QMF console application
---------------------------------------------------------------

                 Key: QPID-2411
                 URL: https://issues.apache.org/jira/browse/QPID-2411
             Project: Qpid
          Issue Type: Improvement
          Components: Documentation
            Reporter: Andrew English
            Priority: Minor


I have pasted in my initial draft of the documentation for creating a QMF 
console application in C++.  If this is still needed, I will complete the 
sections on calling methods and asynchronous notifications.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd";>
<html><head>


  
    <link type="text/css" rel="stylesheet" 
href="qmf-python-console-tutorial_files/space.css">
    <style type="text/css">
      .footer {
        background-image:      
url('http://cwiki.apache.org/confluence/images/border/border_bottom.gif');
        background-repeat:     repeat-x;
        background-position:   left top;
        padding-top:           4px;
        color:                 #666;
        clear:                 both;
      }
     .left {
        padding-top: 5px;
        float : left;
        width : 15em;
      }
      .pagecontent {
         float: left;
         width: 70%;
      }
    </style>
    <script type="text/javascript" language="javascript">
      var hide = null;
      var show = null;
      var children = null;

      function init() {
        /* Search form initialization */
        var form = document.forms['search'];
        if (form != null) {
          form.elements['domains'].value = location.hostname;
          form.elements['sitesearch'].value = location.hostname;
        }

        /* Children initialization */
        hide = document.getElementById('hide');
        show = document.getElementById('show');
        children = document.all != null ?
                   document.all['children'] :
                   document.getElementById('children');
        if (children != null) {
          children.style.display = 'none';
          show.style.display = 'inline';
          hide.style.display = 'none';
        }
      }

      function showChildren() {
        children.style.display = 'block';
        show.style.display = 'none';
        hide.style.display = 'inline';
      }

      function hideChildren() {
        children.style.display = 'none';
        show.style.display = 'inline';
        hide.style.display = 'none';
      }
    </script>
    <title>Apache Qpid: Open Source AMQP Messaging - QMF Cpp Console 
Tutorial</title>
  <meta http-equiv="Content-Type" content="text/html; 
charset=UTF-8"></head><body
 onload="init()">
    <table width="100%" border="0" cellpadding="2" cellspacing="0">
      <tbody><tr class="topBar">
        <td class="topBarDiv" valign="middle" align="left" 
nowrap="nowrap">
          &nbsp;<a href="http://qpid.apache.org/index.html"; 
title="Apache Qpid">Apache Qpid</a>&nbsp;&gt;&nbsp;<a 
href="http://qpid.apache.org/index.html"; 
title="Index">Index</a>&nbsp;&gt;&nbsp;<a
 href="http://qpid.apache.org/developer-pages.html"; title="Developer 
Pages">Developer Pages</a>&nbsp;&gt;&nbsp;<a 
href="http://qpid.apache.org/qpid-management-framework.html"; title="Qpid
 Management Framework">Qpid Management Framework</a>&nbsp;&gt;&nbsp;<a 
href="" title="QMF Cpp Console Tutorial">QMF Cpp Console Tutorial</a>
        </td>
        <td valign="middle" align="right" nowrap="nowrap">
          <form name="search" action="http://www.google.com/search"; 
method="get">
            <input name="ie" value="UTF-8" type="hidden">
            <input name="oe" value="UTF-8" type="hidden">
            <input name="domains" value="qpid.apache.org" type="hidden">
            <input name="sitesearch" value="qpid.apache.org" 
type="hidden">
            <input name="q" maxlength="255" type="text">        
            <input name="btnG" value="Google Search" type="submit">
          </form>
        </td>
      </tr> 
    </tbody></table>

    <div id="PageContent">
        <div class="pageheader" style="padding: 6px 0px 0px;">
<div>
<table width="90%" border="0">
<tbody><tr>
<td align="left">
<a href="http://qpid.apache.org/";>
<img src="qmf-python-console-tutorial_files/qpid-logo.png" width="225" 
border="0" height="69"></a>
</td>
<td>
</td>
<td align="right">          <a href="http://www.apache.org/";>
            <img src="qmf-python-console-tutorial_files/asf-logo.png" 
width="225" border="0" height="69"></a></td>
</tr>
</tbody></table>
</div>

      </div>

<!--


      <div class="pagesubheading" style="margin: 0px 10px 0px 10px;">
                    Added by <a href="/confluence/display/~tross">Ted Ross</a>, 
last edited by <a href="/confluence/display/~tross">Ted Ross</a> on Mar 03, 2009
                      &nbsp;(<a class="noprint" 
href="/confluence/pages/diffpages.action?pageId=108629&originalId=111632">view 
change</a>)
              
      </div>
-->

        <div class="left">
            
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                    
                                                
            <div class="panel" style="border: 1px solid rgb(32, 32, 
128);"><div class="panelContent" style="">
<h3><a name="Navigation-ApacheQpid"></a>Apache Qpid</h3>
<p> <a href="http://qpid.apache.org/index.html"; title="Index">Home</a><br>
 <a href="http://qpid.apache.org/download.html"; 
title="Download">Download</a><br>
 <a href="http://qpid.apache.org/getting-started.html"; title="Getting 
Started">Getting Started</a> <br>
 <a href="http://qpid.apache.org/documentation.html"; 
title="Documentation">Documentation</a><br>
 <a href="http://qpid.apache.org/mailing-lists.html"; title="Mailing 
Lists">Mailing Lists</a><br>
 <a href="http://issues.apache.org/jira/browse/qpid"; rel="nofollow">Issue
 Reporting</a><br>
 <a href="http://qpid.apache.org/faq.html"; title="FAQ">FAQ/How to</a></p>

<h3><a name="Navigation-Resources"></a>Resources</h3>
<p> <a href="http://qpid.apache.org/getting-involved.html"; 
title="Getting Involved">Getting Involved</a><br>
 <a href="http://qpid.apache.org/qpid-integrations.html"; title="Qpid 
Integrations">Qpid Integrated with..</a><br>
 <a href="http://qpid.apache.org/source-repository.html"; title="Source 
Repository">Source Repository</a><br>
 <a href="http://qpid.apache.org/building.html"; title="Building">Building
 Qpid</a><br>
 <a href="http://qpid.apache.org/developer-pages.html"; title="Developer 
Pages">Developer Pages</a><br>
 <a href="http://qpid.apache.org/qpid-management-framework.html"; 
title="Qpid Management Framework">QMF</a></p>

<h3><a name="Navigation-AboutQpid"></a>About Qpid</h3>
<p> <a href="http://qpid.apache.org/people.html"; title="People">People</a><br>
 <a href="http://qpid.apache.org/license.html"; title="License">License</a><br>
 <a href="http://qpid.apache.org/project-status.html"; title="Project 
Status">Project Status</a><br>
 <a href="http://qpid.apache.org/acknowledgments.html"; 
title="Acknowledgments">Acknowledgments</a></p>

<h3><a name="Navigation-AboutAMQP"></a>About AMQP</h3>
<p> <a 
href="http://qpid.apache.org/amqp-advanced-message-queueing-protocol.html";
 title="AMQP (Advanced Message Queueing Protocol)">What is AMQP ?</a><br>
 <a 
href="http://qpid.apache.org/amqp-advanced-message-queueing-protocol.html";
 title="AMQP (Advanced Message Queueing Protocol)">AMQP Specification 
Download</a></p>

<p><img src="qmf-python-console-tutorial_files/AMQP_logo_71px-small.jpg"
 align="absmiddle" border="0"></p>
</div></div>
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                                                                        
                        </div>

      <div class="pagecontent">
        <div class="wiki-content">
          <div>
<ul>
    <li><a 
href="#QMFCPPConsoleTutorial-PrerequisiteInstallQpidMessaging">Prerequisite
 - Install Qpid Messaging</a></li>
    <li><a 
href="#QMFCPPConsoleTutorial-SynchronousConsoleOperations">Synchronous
 Console Operations</a></li>
<ul>
    <li><a 
href="#QMFCPPConsoleTutorial-CreatingaQMFConsoleSessionandAttachingtoaBroker">Creating
 a QMF Console Session and Attaching to a Broker</a></li>
    <li><a href="#QMFCPPConsoleTutorial-AccessingManagedObjects">Accessing
 Managed Objects</a></li>
<ul>
    <li><a 
href="#QMFCPPConsoleTutorial-ViewingPropertiesandStatisticsofanObject">Viewing
 Properties and Statistics of an Object</a></li>
    <li><a href="#QMFCPPConsoleTutorial-InvokingMethodsonanObject">Invoking
 Methods on an Object</a></li>
</ul>
</ul>
    <li><a 
href="#QMFPythonConsoleTutorial-AsynchronousConsoleOperations">Asynchronous
 Console Operations</a></li>
<ul>
    <li><a 
href="#QMFPythonConsoleTutorial-CreatingaConsoleClasstoReceiveAsynchronousData">Creating
 a Console Class to Receive Asynchronous Data</a></li>
    <li><a href="#QMFPythonConsoleTutorial-ReceivingEvents">Receiving 
Events</a></li>
    <li><a href="#QMFPythonConsoleTutorial-ReceivingObjects">Receiving 
Objects</a></li>
    <li><a 
href="#QMFPythonConsoleTutorial-AsynchronousMethodCallsandMethodTimeouts">Asynchronous
 Method Calls and Method Timeouts</a></li>
</ul>
    <li><a 
href="#QMFPythonConsoleTutorial-DiscoveringwhatKindsofObjectsareAvailable">Discovering
 what Kinds of Objects are Available</a></li>
</ul></div>

<h1><a 
name="QMFPythonConsoleTutorial-PrerequisiteInstallQpidMessaging"></a>Prerequisite
 - Install Qpid Messaging</h1>

<p>QMF uses AMQP Messaging (QPid) as its means of communication.  To use
 QMF, Qpid messaging must be installed somewhere in the network.  Qpid 
can be downloaded as source from Apache, is packaged with a number of 
Linux distributions, and can be purchased from commercial vendors that 
use Qpid.  Please see <a href="http://qpid.apache.org/download.html"; 
title="Download">Download</a> for information as to where to get Qpid 
Messaging.</p>

<p>Qpid Messaging includes a message broker (qpidd) which typically runs
 as a daemon on a system.  It also includes client bindings in various 
programming languages.  The C++-language client library includes the source for 
the
QMF console libraries needed for this tutorial.</p>

<p>Please note that Qpid Messaging has two broker implementations.  One 
is implemented in C++ and the other in Java.  At press time, QMF is 
supported only by the C++ broker.</p>

<p>If the goal is to get the tutorial examples up and running as quickly
 as possible, all of the Qpid components can be installed on a single 
system (even a laptop).  For more realistic deployments, the broker can 
be deployed on a server and the client/QMF libraries installed on other 
systems.</p>

<h1><a name="QMFCPPConsoleTutorial-SynchronousConsoleOperations"></a>Synchronous
 Console Operations</h1>

<p>The C++ console API for QMF can be used in a synchronous style, an
 asynchronous style, or a combination of both.  Synchronous operations 
are conceptually simple and are well suited for user-interactive tasks. 
 All operations are performed in the context of a C++ function call. 
 If communication over the message bus is required to complete an 
operation, the function call blocks and waits for the expected result 
(or timeout failure) before returning control to the caller.</p>

<h2><a 
name="QMFCPPConsoleTutorial-CreatingaQMFConsoleSessionandAttachingtoaBroker"></a>Creating
 a QMF Console Session and Attaching to a Broker</h2>

<p>For the purposes of this tutorial, code examples will be shown in snippets 
revelant to the current task.</p>

<p>We will begin by including the required libraries.  If the QMF libraries are 
installed in the lib directory, they 
can be referenced when building and linking the application:</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>
g++ -c -I/usr/include/qpid-boost qmfagent.cpp -o qmfagent.o
g++ -lqpidclient -lqmfconsole ./qmfagent.o  -o qmfagent
</pre>
</div></div>

In the source, they should be included as follows:

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>#include &lt;qpid/console/SessionManager.h&gt;
        
namespace qmf = qpid::console;
</pre>
</div></div>

<p>We must now create a <em>Session</em> object to manage this QMF 
console session.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::SessionManager sessMgr;
</pre>
</div></div>

<p>If no arguments are supplied to the creation of <em>Session</em>, it 
defaults to synchronous-only operation.  It also defaults to 
user-management of connections.  More on this in a moment.</p>

<p>We will now establish a connection to the messaging broker.  If the 
broker daemon is running on the local host, simply use the following:</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::Broker* broker = sessMgr.addBroker();
</pre>
</div></div>

<p>If the messaging broker is on a remote host, supply the URL to the 
broker in the <em>addBroker</em> function call.  Here's how to connect 
to a local broker using the URL.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::Broker* broker = sessMgr.addBroker("amqp://localhost");
</pre>
</div></div>

<p>A <em>ConnectionSettings</em> object can also be passed to the 
<em>addBroker</em> function call.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf_::SessionManager sessMgr;
qc::ConnectionSettings settings;

settings.host = host;
settings.port = port;
qmf::Broker* broker = sessMgr.addBroker(settings);
</pre>
</div></div>

<p>The call to <em>addBroker</em> is synchronous and will return only 
after the connection has been successfully established or has failed.  
If a failure occurs, <em>addBroker</em> will raise an exception.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>try
{
        qmf::Broker* broker = sessMgr.addBroker("amqp://localhost:1000");
}
catch(const std::exception& error) 
{
        std::cout &lt;&lt; "Failed to connect: " &lt;&lt; error.what() &lt;&lt; 
std::endl;
}

</pre>
</div></div>

<p>This operation fails because there is no Qpid Messaging broker 
listening on port 1000 (the default port for qpidd is 5672).</p>

<p>If preferred, the QMF session can manage the connection for you.  In 
this case, <em>addBroker</em> returns immediately and the session 
attempts to establish the connection in the background.  This will be 
covered in detail in the section on asynchronous operations.</p>

<h2><a name="QMFCPPConsoleTutorial-AccessingManagedObjects"></a>Accessing
 Managed Objects</h2>

<p>The C++ console API provides access to remotely managed objects 
via a <em>proxy</em> model.  The API gives the client an object that 
serves as a proxy representing the "real" object being managed on the 
agent application.  Operations performed on the proxy result in the same
 operations on the real object.</p>

<p>The following examples assume prior knowledge of the kinds of objects
 that are actually available to be managed.  There is a section later in
 this tutorial that describes how to discover what is manageable on the 
QMF bus.</p>

<p>Proxy objects are obtained by calling the <em>Session.getObjects</em>
 function.</p>

<p>To illustrate, we'll get a list of objects representing queues in the
 message broker itself.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::Object::Vector objects;
sessMgr.getObjects(objects, "queue");
</pre>
</div></div>

<p>We can also specify a specific broker when querying.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::Broker* broker = sessMgr.addBroker("amqp://localhost:5672");
qmf::Object::Vector objects;
sessMgr.getObjects(objects, "queue", broker);
</pre>
</div></div>

<p><em>queues</em> is an array of proxy objects representing real queues
 on the message broker.  A proxy object can be printed to display a 
description of the object.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>for(unsigned int i = 0; i &lt; objects.size(); i++)
{
        std::string queueName = objects[i].attrString("name");
        std::cout &lt;&lt; "name: " &lt;&lt; queueName &lt;&lt; std::endl;
        
        qmf::Object obj = objects[i];
        std::cout &lt;&lt; "tostring: " &lt;&lt; obj &lt;&lt; std::endl;
}

name: qmfc-a3159ef6-17c5-461f-a27d-7c79fcc132fc
tostring: org.apache.qpid.broker:queue[0-21-1-0-179] 
0-0-1-0-1152921504606846979:qmfc-a3159ef6-17c5-461f-a27d-7c79fcc132fc
</pre>
</div></div>

<h3><a 
name="QMFPythonConsoleTutorial-ViewingPropertiesandStatisticsofanObject"></a>Viewing
 Attributes of an Object</h3>

<p>Let us now focus our attention on one of the queue objects.</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::Object obj = objects[i];
</pre>
</div></div>

<p>The attributes of an object are stored in a map.</p>

<p>We can iterate through the attributes of an object:</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>qmf::Object::AttributeMap attributes = obj.getAttributes();
for(qmf::Object::AttributeMap::const_iterator vIter = attributes.begin(); vIter 
!= attributes.end(); vIter++)
{
        std::cout &lt;&lt; "Attribute: " &lt;&lt; vIter->first &lt;&lt; " 
Value: " &lt;&lt; vIter->second->str() &lt;&lt; std::endl;
}

Attribute: arguments Value: {}
Attribute: autoDelete Value: T
Attribute: bindingCount Value: 4
Attribute: bindingCountHigh Value: 4
Attribute: bindingCountLow Value: 4
Attribute: byteDepth Value: 912
Attribute: bytePersistDequeues Value: 0
Attribute: bytePersistEnqueues Value: 0
Attribute: byteTotalDequeues Value: 30371
Attribute: byteTotalEnqueues Value: 31283
Attribute: byteTxnDequeues Value: 0
Attribute: byteTxnEnqueues Value: 0
Attribute: consumerCount Value: 1
Attribute: consumerCountHigh Value: 1
Attribute: consumerCountLow Value: 1
Attribute: durable Value: F
Attribute: exclusive Value: T
Attribute: messageLatencyAverage Value: 0
Attribute: messageLatencyMax Value: 0
Attribute: messageLatencyMin Value: 0
Attribute: messageLatencySamples Value: 0
Attribute: msgDepth Value: 3
Attribute: msgPersistDequeues Value: 0
Attribute: msgPersistEnqueues Value: 0
Attribute: msgTotalDequeues Value: 72
Attribute: msgTotalEnqueues Value: 75
Attribute: msgTxnDequeues Value: 0
Attribute: msgTxnEnqueues Value: 0
Attribute: name Value: qmfc-bfd3ec18-8222-488f-8c3d-221029145106
Attribute: unackedMessages Value: 0
Attribute: unackedMessagesHigh Value: 0
Attribute: unackedMessagesLow Value: 0
Attribute: vhostRef Value: 0-0-1-0-1152921504606846979
</pre>
</div></div>

<p>A more convenient way to access attributes is by using the attribute 
of the proxy object directly:</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>std::string name;
name = obj.attrString("name");
std::cout &lt;&lt; "Name: " &lt;&lt; name &lt;&lt; std::endl;
bool autoDelete;
autoDelete = obj.attrBool("autoDelete");
std::cout &lt;&lt; "autoDelete: " &lt;&lt; autoDelete &lt;&lt; std::endl;

Name: qmfc-e9d8f830-ac50-4377-b38c-7b0ffa1d86d2
autoDelete: 1

</pre>
</div></div>

<p>Statistics are accessed in the same way:</p>

<div class="preformatted panel" style="border-width: 1px;"><div 
class="preformattedContent panelContent">
<pre>int msgDepth;
msgDepth = obj.attrInt("msgDepth");
std::cout &lt;&lt; "msgDepth: " &lt;&lt; msgDepth &lt;&lt; std::endl;

msgDepth: 0

</pre>
</div></div>

<p>The proxy objects do not automatically track changes that occur on 
the real objects.  For example, if the real queue enqueues more bytes, 
viewing the <em>byteTotalEnqueues</em> statistic will show the same 
number as it did the first time.  To get updated data on a proxy object,
 query the <em>SessionManager</em> again.</p>

        </div>

<!--
        -->

      </div>

    <div class="footer">
      Apache Qpid, Enterprise AMQP Messaging    
      &nbsp;
      © 2004-2008 The Apache Software Foundation.
      &nbsp;
        (<a 
href="http://cwiki.apache.org/confluence/pages/editpage.action?pageId=108629";>edit
 this page</a>)
    </div>
  </div></body></html>

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:dev-subscr...@qpid.apache.org

Reply via email to