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">
<a href="http://qpid.apache.org/index.html"
title="Apache Qpid">Apache Qpid</a> > <a
href="http://qpid.apache.org/index.html"
title="Index">Index</a> > <a
href="http://qpid.apache.org/developer-pages.html" title="Developer
Pages">Developer Pages</a> > <a
href="http://qpid.apache.org/qpid-management-framework.html" title="Qpid
Management Framework">Qpid Management Framework</a> > <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
(<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 <qpid/console/SessionManager.h>
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 << "Failed to connect: " << error.what() <<
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 < objects.size(); i++)
{
std::string queueName = objects[i].attrString("name");
std::cout << "name: " << queueName << std::endl;
qmf::Object obj = objects[i];
std::cout << "tostring: " << obj << 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 << "Attribute: " << vIter->first << "
Value: " << vIter->second->str() << 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 << "Name: " << name << std::endl;
bool autoDelete;
autoDelete = obj.attrBool("autoDelete");
std::cout << "autoDelete: " << autoDelete << 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 << "msgDepth: " << msgDepth << 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
© 2004-2008 The Apache Software Foundation.
(<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:[email protected]