summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorJonathan Robie <jonathan@apache.org>2010-01-23 16:39:14 +0000
committerJonathan Robie <jonathan@apache.org>2010-01-23 16:39:14 +0000
commit83b3d97aabaf5d6f1ba672080c936de2743186ed (patch)
tree86f702297d8b751c02e951c41cf2349cab5d9a2f /doc
parent772484f911db95bbc0c1ac599ed72b2ee143bec0 (diff)
downloadqpid-python-83b3d97aabaf5d6f1ba672080c936de2743186ed.tar.gz
"Feature complete" for first internal draft, each file is valid DocBook.
Next step: Make the whole thing valid DocBook as one document. 1. Rebalance of part, chapter, and section elements. 2. References among parts git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@902438 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'doc')
-rw-r--r--doc/book/src/AMQP .NET Messaging Client.xml87
-rw-r--r--doc/book/src/AMQP C++ Messaging Client.xml40
-rw-r--r--doc/book/src/AMQP Python Messaging Client.xml41
-rw-r--r--doc/book/src/AMQP Ruby Messaging Client.xml19
-rw-r--r--doc/book/src/Book.xml4
-rw-r--r--doc/book/src/Excel AddIn.xml148
-rw-r--r--doc/book/src/NET User Guide.xml1362
-rw-r--r--doc/book/src/PythonBrokerTest.xml77
-rw-r--r--doc/book/src/WCF.xml116
-rw-r--r--doc/book/src/schemas.xml1
10 files changed, 1893 insertions, 2 deletions
diff --git a/doc/book/src/AMQP .NET Messaging Client.xml b/doc/book/src/AMQP .NET Messaging Client.xml
new file mode 100644
index 0000000000..301bf0fcf9
--- /dev/null
+++ b/doc/book/src/AMQP .NET Messaging Client.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>
+ Apache Qpid : AMQP .NET Messaging Client
+ </title>
+ <para>
+ Currently the .NET code base provides two client libraries that
+ are compatible respectively with AMQP 0.8 and 0.10. The 0.8 client
+ is located in <filename>qpid\dotnet</filename> and the 0.10 client
+ in: <filename>qpid\dotnet\client-010</filename>.
+ </para>
+ <para>
+ You will need an AMQP broker to fully use those client libraries.
+ Use M4 or later C++ broker for AMQP 0.10 or Java broker for AMQP
+ 0.8/0.9.
+ </para>
+ <section role="h3" id="AMQP.NETMessagingClient-UserGuides">
+ <title>
+ User Guides
+ </title>
+
+ <xi:include href="NET%20User%20Guide.xml"/>
+ <xi:include href="Excel%20AddIn.xml"/>
+ <xi:include href="WCF.xml"/>
+ </section>
+
+ <section role="h3" id="AMQP.NETMessagingClient-Examples">
+ <title>
+ Examples
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <ulink url="http://svn.apache.org/viewvc/qpid/trunk/qpid/dotnet/client-010/examples/"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <!--h3-->
+ </section>
+
+<!--
+
+ <section role="h3" id="AMQP.NETMessagingClient-DeveloperGuidelines">
+ <title>
+ Developer Guidelines
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <xref linkend="qpid_Developer-20Pages"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>Coding Standards </para>
+ </listitem>
+ <listitem>
+ <para>How Tos
+ <itemizedlist>
+ <listitem>
+ <para>
+ <xref linkend="qpid_Build-20.NET-20Client"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <xref linkend="qpid_Releasing"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <xref linkend="qpid_Run-20tests"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <xref linkend="qpid_Setup-20.Net-20Client-20on-20Windows"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ -->
+
+
+</chapter>
diff --git a/doc/book/src/AMQP C++ Messaging Client.xml b/doc/book/src/AMQP C++ Messaging Client.xml
new file mode 100644
index 0000000000..4ec9bde0cf
--- /dev/null
+++ b/doc/book/src/AMQP C++ Messaging Client.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid : AMQP C++ Messaging Client
+ </title>
+ <section role="h3" id="AMQPCPPMessagingClient-UserGuides">
+ <title>
+ User Guides
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <ulink url="http://qpid.apache.org/docs/api/cpp/html/index.html">C++ Client API (AMQP 0-10)</ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="AMQPCPPMessagingClient-Examples">
+ <title>
+ Examples
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <ulink url="https://svn.apache.org/repos/asf/qpid/trunk/qpid/cpp/examples/">AMQP C++ Client Examples </ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <ulink url="https://svn.apache.org/repos/asf/qpid/trunk/qpid/cpp/examples/README.txt">Running the AMQP C++ Client Examples </ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <!--h3-->
+ </section>
+
+
+</chapter>
diff --git a/doc/book/src/AMQP Python Messaging Client.xml b/doc/book/src/AMQP Python Messaging Client.xml
new file mode 100644
index 0000000000..0fd4dfa297
--- /dev/null
+++ b/doc/book/src/AMQP Python Messaging Client.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid : AMQP Python Messaging Client
+ </title>
+ <section role="h3" id="AMQPPythonMessagingClient-UserGuides">
+ <title>
+ User Guides
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <ulink url="http://qpid.apache.org/docs/api/python/html/index.html">Python Client API Guide</ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="AMQPPythonMessagingClient-Examples">
+ <title>
+ Examples
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <ulink url="https://svn.apache.org/repos/asf/qpid/trunk/qpid/python/examples/">AMQP Python Client Examples </ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <ulink url="https://svn.apache.org/repos/asf/qpid/trunk/qpid/python/examples/README">Running the AMQP Python Client Examples </ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <!--h3-->
+ </section>
+
+ <xi:include href="PythonBrokerTest.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+</chapter>
diff --git a/doc/book/src/AMQP Ruby Messaging Client.xml b/doc/book/src/AMQP Ruby Messaging Client.xml
new file mode 100644
index 0000000000..f4ade96e51
--- /dev/null
+++ b/doc/book/src/AMQP Ruby Messaging Client.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid : AMQP Ruby Messaging Client
+ </title>
+ <para>
+ The Ruby Messaging Client currently has little documentation and
+ few examples.
+ </para>
+ <section role="h3" id="AMQPRubyMessagingClient-Examples">
+ <title>
+ Examples
+ </title>
+ <para>
+ <ulink url="https://svn.apache.org/repos/asf/qpid/trunk/qpid/ruby/examples">AMQP Ruby Messaging Client Examples</ulink>
+ </para>
+ <!--h3-->
+ </section>
+</chapter>
diff --git a/doc/book/src/Book.xml b/doc/book/src/Book.xml
index b592399009..f82faa9b5a 100644
--- a/doc/book/src/Book.xml
+++ b/doc/book/src/Book.xml
@@ -21,11 +21,11 @@
<part>
<title>AMQP Messaging Clients Clients</title>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP%20Java%20JMS%20Messaging%20Client.xml"/>
-<!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP%20C++%20Messaging%20Client.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP%20C++%20Messaging%20Client.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP%20.NET%20Messaging%20Client.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP%20Python%20Messaging%20Client.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP%20Ruby%20Messaging%20Client.xml"/>
--->
+
</part>
<part>
<title>Appendices</title>
diff --git a/doc/book/src/Excel AddIn.xml b/doc/book/src/Excel AddIn.xml
new file mode 100644
index 0000000000..ee29cb1373
--- /dev/null
+++ b/doc/book/src/Excel AddIn.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid : Excel AddIn
+ </title>
+ <section role="h1" id="ExcelAddIn-ExcelAddIn">
+ <title>
+ Excel AddIn
+ </title>
+ <para>
+ Qpid .net comes with Excel AddIns that are located in:
+ </para>
+ <para>
+ <filename>&lt;project-root&gt;\qpid\dotnet\client-010\addins</filename>
+ </para>
+
+ <para>
+ There are currently three projects:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>ExcelAddIn</term>
+ <listitem>
+ <para>An RTD excel Addin</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>ExcelAddInProducer
+ </term>
+ <listitem>
+ <para>A sample client to demonstrate the RTD AddIn</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>ExcelAddInMessageProcessor
+ </term>
+ <listitem>
+ <para>A sample message processor for the RTD AddIn</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <section role="h2" id="ExcelAddIn-QpidRDTAddIn">
+ <title>
+ Qpid RDT AddIn
+ </title>
+ <section role="h3" id="ExcelAddIn-DeployingtheRTDAddIn">
+ <title>
+ Deploying the RTD
+ AddIn
+ </title>
+ <para>
+ Excel provides a function called RTD (real-time data) that lets
+ you specify a COM server via its ProgId here "Qpid" so that you
+ can push qpid messages into Excel.
+ </para>
+ <para>
+ The provided RTD AddIn consumes messages from one queue and
+ process them through a provided message processor.
+ </para>
+ <para>
+ For using the Qpid RTD follows those steps:
+ </para>
+
+ <procedure>
+ <step><para>
+ Copy the configuration Excel.exe.config into <filename>Drive\Program Files\Microsoft Office\Office12</filename>.
+ </para></step>
+ <step><para>
+ Edit <filename>Excel.exe.xml</filename> and set the targeted Qpid broker host, port
+ number, username and password.
+ </para></step>
+ <step> <para>
+ Select the cell or cell range to contain the RTD information
+ </para></step>
+ <step><para>
+ Enter the following formula <command>=rtd("Qpid",,"myQueue")</command>. Where
+ MyQueue is the queue from which you wish to receive messages from.
+ </para></step>
+ </procedure>
+ <para>
+ Note: The Qpid RTD is a COM-AddIn that must be registered with
+ Excel. This is done automatically when compiling the Addin with
+ visual studio.
+ </para>
+ <!--h3-->
+ </section>
+
+
+ <section role="h3" id="ExcelAddIn-Definingamessageprocessor">
+ <title>
+ Defining a message processor
+ </title>
+
+ <para>
+ The default behavior of the RDT AddIn is to display the message
+ payload. This could be altered by specifying your own message
+ processor.
+ A Message processor is a class that implements the API
+ <command>ExcelAddIn.MessageProcessor</command>. For example, the provided processor
+ in <filename>client-010\addins\ExcelAddInMessageProcessor</filename> displays the
+ message body and the the header price when specified.
+ </para>
+ <para>
+ To use you own message processor follows those steps:
+ </para>
+ <procedure>
+ <step><para>Write your own message processor that extends ExcelAddIn.MessageProcessor</para></step>
+ <step><para>Edit Excel.exe.config and uncomment the entries:</para>
+ <programlisting>
+&lt;add key="ProcessorAssembly"
+value="&lt;path&gt;\qpid\dotnet\client-010\addins\ExcelAddInMessageProcessor\bin\Debug\ExcelAddInMessageProcessor.dll"/&gt;
+ </programlisting>
+ <programlisting>
+ &lt;add key="ProcessorClass"
+ value="ExcelAddInMessageProcessor.Processor"/&gt;
+ </programlisting>
+ <itemizedlist>
+ <listitem>
+ <para>ProcessorAssembly is the path on the Assembly that contains
+ your processor class
+ </para>
+ </listitem>
+ <listitem>
+ <para>ProcessorClass is your processor class name
+ </para>
+ </listitem>
+ </itemizedlist>
+ </step>
+ <step><para>run excel and define a rtd function</para></step>
+ </procedure>
+ <para>
+ Note: the provided ExcelAddInProducer can be used for
+ testing the provided message processor. As messages are
+ sent to queue1 the following rtd function should be used
+ <command>=rtd("Qpid",,"queue1")</command>.
+ </para>
+
+ <!--h3-->
+ </section>
+
+ <!--h2-->
+ </section>
+
+ <!--h1-->
+ </section>
+
+</chapter>
diff --git a/doc/book/src/NET User Guide.xml b/doc/book/src/NET User Guide.xml
new file mode 100644
index 0000000000..3d9f96b344
--- /dev/null
+++ b/doc/book/src/NET User Guide.xml
@@ -0,0 +1,1362 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid: Open Source AMQP Messaging - .NET User Guide
+ </title>
+ <section role="h1" id="NETUserGuide-Tutorial">
+ <title>
+ Tutorial
+ </title>
+ <para>
+ This tutorial consists of a series of examples using the three
+ most commonly used exchange types - Direct, Fanout and
+ Topic
+ exchanges. These examples show how to write applications that use
+ the most common messaging paradigms.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>direct</para>
+ <para>In the direct examples, a message producer writes to the direct
+ exchange, specifying a routing key. A message consumer reads
+ messages from a named queue. This illustrates clean separation
+ of concerns - message producers need to know only the exchange
+ and the routing key, message consumers need to know only which
+ queue to use on the broker.
+ </para>
+ </listitem>
+ <listitem>
+ <para>fanout</para>
+ <para>The fanout examples use a fanout exchange and do not use
+ routing keys. Each binding specifies that all messages for a
+ given exchange should be delivered to a given queue.
+ </para>
+ </listitem>
+ <listitem>
+ <para>pub-sub</para>
+ <para>In the publish/subscribe examples, a publisher
+ application writes messages to an exchange, specifying a
+ multi-part key. A subscriber application subscribes to
+ messages that match the relevant parts of these keys, using a
+ private queue for each subscription.
+ </para>
+ </listitem>
+ <listitem>
+ <para>request-response</para>
+ <para>In the request/response examples, a simple service accepts
+ requests from clients and sends responses back to them. Clients
+ create their own private queues and corresponding routing keys.
+ When a client sends a request to the server, it specifies its
+ own routing key in the reply-to field of the request. The
+ server uses the client's reply-to field as the routing key for
+ the response.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <section role="h2" id="NETUserGuide-RunningtheExamples">
+ <title>
+ Running the
+ Examples
+ </title>
+ <para>
+ Before running the examples, you need to unzip the file
+ Qpid.NET-net-2.0-M4.zip, the following tree is created:
+ </para>
+
+
+ <programlisting>
+&lt;home&gt;
+ |-qpid
+ |-lib (contains the required dlls)
+ |-examples
+ |- direct
+ | |-example-direct-Listener.exe
+ | |-example-direct-Producer.exe
+ |- fanout
+ | |-example-fanout-Listener.exe
+ | |-example-fanout-Producer.exe
+ |- pub-sub
+ | |-example-pub-sub-Listener.exe
+ | |-example-pub-sub-Publisher.exe
+ |- request-response
+ |-example-request-response-Client.exe
+ |-example-request-response-Server.exe
+ </programlisting>
+
+
+ <para>
+ Make sure your PATH contains the directory
+ &lt;home&gt;/qpid/lib
+ The examples can be run by executing the provided exe files:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/examplefolder
+$ example-...-.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ where [hostname] is the qpid broker host name
+ (default is localhost) and [portnumber] is the port number on which the
+ qpid broker is accepting connection (default is 5672).
+ </para>
+ <!--h2-->
+ </section>
+
+ <section role="h2" id="NETUserGuide-CreatingandClosingSessions">
+ <title>
+ Creating
+ and Closing Sessions
+ </title>
+
+ <para>
+ All of the examples have been written using the Apache Qpid .NEt
+ 0.10 API. The examples use the same skeleton code to initialize
+ the program, create a session, and clean up before exiting:
+ </para>
+
+
+ <programlisting>
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+...
+
+ private static void Main(string[] args)
+ {
+ string host = args.Length &gt; 0 ? args[0] : "localhost";
+ int port = args.Length &gt; 1 ? Convert.ToInt32(args[1]) : 5672;
+ Client connection = new Client();
+ try
+ {
+ connection.connect(host, port, "test", "guest", "guest");
+ ClientSession session = connection.createSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+
+ connection.close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+...
+ </programlisting>
+ <!--h2-->
+ </section>
+
+ <section role="h2" id="NETUserGuide-WritingDirectApplications">
+ <title>
+ Writing
+ Direct Applications
+ </title>
+
+ <para>
+ This section describes two programs that implement direct
+ messaging using a Direct exchange:
+ • org.apache.qpid.example.direct.Producer (from
+ example-direct-producer) publishes messages to the amq.direct
+ exchange, using the routing key routing_key.
+ •org.apache.qpid.example.direct.Listener (from
+ example-direct-Listener) uses a message listener to receive
+ messages from the queue named message_queue.
+ </para>
+ <section role="h3" id="NETUserGuide-RunningtheDirectExamples">
+ <title>
+ Running the
+ Direct Examples
+ </title>
+ <para>
+ 1) Make sure your PATH contains the directory
+ &lt;home&gt;/qpid/lib
+ </para>
+ <para>
+ 2) Make sure that a qpid broker is running:
+ </para>
+
+
+ <programlisting>
+$ ps -eaf | grep qpidd
+ </programlisting>
+
+
+ <para>
+ If a broker is running, you should see the qpidd process in the
+ output of the above
+ command.
+ </para>
+ <para>
+ 3) Read the messages from the message queue using direct
+ listener, as follows:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-direct-Listener.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-direct-Listener.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ This program is waiting for messages to be published, see next
+ step:
+ </para>
+ <para>
+ 4) Publish a series of messages to the amq.direct exchange by
+ running direct producer, as follows:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-direct-Producer.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-direct-Producer.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ This program has no output; the messages are routed to the
+ message queue, as instructed by the binding.
+ </para>
+ <para>
+ 5) Go to the windows where you are running your listener. You
+ should see the following output:
+ </para>
+
+
+ <programlisting>
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
+ </programlisting>
+
+
+ <para>
+ Now we will examine the code for each of these programs. In each
+ section, we will discuss only
+ the code that must be added to the skeleton shown in Section
+ "Creating and Closing Sessions".
+ </para>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="NETUserGuide-ReadingMessagesfromtheQueue">
+ <title>
+ Reading
+ Messages from the Queue
+ </title>
+
+ <para>
+ The program , listener.cs, is a message listener that receives
+ messages from a queue.
+ </para>
+ <para>
+ First it creates a queue named message_queue, then binds it to
+ the amq.direct exchange using the binding key routing_key.
+ </para>
+
+
+ <programlisting>
+//--------- Main body of program --------------------------------------------
+// Create a queue named "message_queue", and route all messages whose
+// routing key is "routing_key" to this newly created queue.
+session.queueDeclare("message_queue");
+session.exchangeBind("message_queue", "amq.direct", "routing_key");
+ </programlisting>
+
+
+ <para>
+ The queue created by this program continues to exist after the
+ program exits, and any message whose routing key matches the key
+ specified in the binding will be routed to the corresponding
+ queue by the broker. Note that the queue could have been be
+ deleted using the following code:
+ </para>
+
+
+ <programlisting>
+session.queueDelete("message_queue");
+ </programlisting>
+
+
+ <para>
+ To create a message listener, create a class derived from
+ IMessageListener, and override the messageTransfer method,
+ providing the code that should be executed when a message is
+ received.
+ </para>
+
+
+ <programlisting>
+public class MessageListener : IMessageListener
+{
+ ......
+ public void messageTransfer(IMessage m)
+ {
+ .....
+}
+ </programlisting>
+
+
+ <para>
+ The main body of the program creates a listener for the
+ subscription; attaches the listener to a message queue; and
+ subscribe to the queue to receive messages from the queue.
+ </para>
+
+
+ <programlisting>
+lock (session)
+{
+ // Create a listener and subscribe it to the queue named "message_queue"
+ IMessageListener listener = new MessageListener(session);
+ session.attachMessageListener(listener, "message_queue");
+ session.messageSubscribe("message_queue");
+ // Receive messages until all messages are received
+ Monitor.Wait(session);
+}
+ </programlisting>
+
+
+ <para>
+ The MessageListener's messageTransfer() function is called
+ whenever a message is received. In this example the message is
+ printed and tested to see if it is the final message. Once the
+ final message is received, the messages are acknowledged.
+ </para>
+
+
+ <programlisting>
+BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+byte[] body = new byte[m.Body.Length - m.Body.Position];
+reader.Read(body, 0, body.Length);
+ASCIIEncoding enc = new ASCIIEncoding();
+string message = enc.GetString(body);
+ Console.WriteLine("Message: " + message);
+// Add this message to the list of message to be acknowledged
+_range.add(m.Id);
+if( message.Equals("That's all, folks!") )
+{
+ // Acknowledge all the received messages
+ _session.messageAccept(_range);
+ lock(_session)
+ {
+ Monitor.Pulse(_session);
+ }
+}
+ </programlisting>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="NETUserGuide-PublishingMessagestoaDirectExchange">
+ <title>
+ Publishing
+ Messages to a Direct Exchange
+ </title>
+ <para>
+ The second program in the direct example, Producer.cs, publishes
+ messages to the amq.direct exchange using the routing key
+ routing_key.
+ </para>
+ <para>
+ First, create a message and set a routing key. The same routing
+ key will be used for each message we send, so you only need to
+ set this property once.
+ </para>
+
+
+ <programlisting>
+IMessage message = new Message();
+// The routing key is a message property. We will use the same
+// routing key for each message, so we'll set this property
+// just once. (In most simple cases, there is no need to set
+// other message properties.)
+message.DeliveryProperties.setRoutingKey("routing_key");
+ </programlisting>
+
+
+ <para>
+ Now send some messages:
+ </para>
+
+
+ <programlisting>
+// Asynchronous transfer sends messages as quickly as
+// possible without waiting for confirmation.
+for (int i = 0; i &lt; 10; i++)
+{
+ message.clearData();
+ message.appendData(Encoding.UTF8.GetBytes("Message " + i));
+ session.messageTransfer("amq.direct", message);
+}
+ </programlisting>
+
+
+ <para>
+ Send a final synchronous message to indicate termination:
+ </para>
+
+
+ <programlisting>
+// And send a syncrhonous final message to indicate termination.
+message.clearData();
+message.appendData(Encoding.UTF8.GetBytes("That's all, folks!"));
+session.messageTransfer("amq.direct", "routing_key", message);
+session.sync();
+ </programlisting>
+ <!--h3-->
+ </section>
+
+ <!--h2-->
+ </section>
+
+
+ <section role="h2" id="NETUserGuide-WritingFanoutApplications">
+ <title>
+ Writing
+ Fanout Applications
+ </title>
+
+ <para>
+ This section describes two programs that illustrate the use of a
+ Fanout exchange.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Listener.cs makes a unique queue private for each instance of
+ the listener, and binds that queue to the fanout exchange. All
+ messages sent to the fanout exchange are delivered to each
+ listener's queue.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Producer.cs publishes messages to the fanout exchange. It
+ does not use a routing key, which is not needed by the fanout
+ exchange.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <section role="h3" id="NETUserGuide-RunningtheFanoutExamples">
+ <title>
+ Running the
+ Fanout Examples
+ </title>
+
+ <para>
+ 1) Make sure your PATH contains the directory
+ &lt;home&gt;/qpid/lib
+ </para>
+ <para>
+ 2) Make sure that a qpid broker is running:
+ </para>
+
+
+ <programlisting>
+$ ps -eaf | grep qpidd
+ </programlisting>
+
+
+ <para>
+ If a broker is running, you should see the qpidd process in the
+ output of the above
+ command.
+ </para>
+ <para>
+ 3) In separate windows, start one or more fanout listeners as
+ follows:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-fanout-Listener.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-fanout-Listener.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ The listener creates a private queue, binds it to the amq.fanout
+ exchange, and waits for messages to arrive on the queue. When the
+ listener starts, you will see the following message:
+ </para>
+
+
+ <programlisting>
+Listening
+ </programlisting>
+
+
+ <para>
+ This program is waiting for messages to be published, see next
+ step:
+ </para>
+ <para>
+ 4) In a separate window, publish a series of messages to the
+ amq.fanout exchange by running fanout producer, as follows:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-fanout-Producer.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-fanout-Producer.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ This program has no output; the messages are routed to the
+ message queue, as prescribed by the binding.
+ </para>
+ <para>
+ 5) Go to the windows where you are running listeners. You should
+ see the following output for each listener:
+ </para>
+
+
+ <programlisting>
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
+ </programlisting>
+
+
+ <para>
+ Now we will examine the code for each of these programs. In each
+ section, we will discuss only
+ the code that must be added to the skeleton shown in Section
+ "Creating and Closing Sessions".
+ </para>
+
+ <!--h3-->
+ </section>
+
+ <!--h2-->
+ </section>
+
+ <section role="h2" id="NETUserGuide-ConsumingfromaFanoutExchange">
+ <title>
+ Consuming from a
+ Fanout Exchange
+ </title>
+
+ <para>
+ The first program in the fanout example, Listener.cs, creates a
+ private queue, binds it to the amq.fanout exchange, and waits for
+ messages to arrive on the queue, printing them out as they
+ arrive. It uses a Listener that is identical to the one used in
+ the direct example:
+ </para>
+
+
+ <programlisting>
+ public class MessageListener : IMessageListener
+ {
+ private readonly ClientSession _session;
+ private readonly RangeSet _range = new RangeSet();
+ public MessageListener(ClientSession session)
+ {
+ _session = session;
+ }
+
+ public void messageTransfer(IMessage m)
+ {
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string message = enc.GetString(body);
+ Console.WriteLine("Message: " + message);
+ // Add this message to the list of message to be acknowledged
+ _range.add(m.Id);
+ if (message.Equals("That's all, folks!"))
+ {
+ // Acknowledge all the received messages
+ _session.messageAccept(_range);
+ lock (_session)
+ {
+ Monitor.Pulse(_session);
+ }
+ }
+ }
+ }
+ </programlisting>
+
+
+ <para>
+ The listener creates a private queue to receive its messages and
+ binds it to the fanout exchange:
+ </para>
+
+
+ <programlisting>
+string myQueue = session.Name;
+session.queueDeclare(myQueue, Option.EXCLUSIVE, Option.AUTO_DELETE);
+session.exchangeBind(myQueue, "amq.fanout", "my-key");
+ </programlisting>
+
+
+ <para>
+ Now we create a listener and subscribe it to the queue:
+ </para>
+
+
+ <programlisting>
+lock (session)
+{
+ Console.WriteLine("Listening");
+ // Create a listener and subscribe it to my queue.
+ IMessageListener listener = new MessageListener(session);
+ session.attachMessageListener(listener, myQueue);
+ session.messageSubscribe(myQueue);
+ // Receive messages until all messages are received
+ Monitor.Wait(session);
+}
+ </programlisting>
+
+
+ <section role="h3" id="NETUserGuide-PublishingMessagestotheFanoutExchange">
+ <title>
+ Publishing
+ Messages to the Fanout Exchange
+ </title>
+
+ <para>
+ The second program in this example, Producer.cs, writes messages
+ to the fanout queue.
+ </para>
+
+
+ <programlisting>
+// Unlike topic exchanges and direct exchanges, a fanout
+// exchange need not set a routing key.
+IMessage message = new Message();
+// Asynchronous transfer sends messages as quickly as
+// possible without waiting for confirmation.
+for (int i = 0; i &lt; 10; i++)
+{
+ message.clearData();
+ message.appendData(Encoding.UTF8.GetBytes("Message " + i));
+ session.messageTransfer("amq.fanout", message);
+}
+
+// And send a syncrhonous final message to indicate termination.
+message.clearData();
+message.appendData(Encoding.UTF8.GetBytes("That's all, folks!"));
+session.messageTransfer("amq.fanout", message);
+session.sync();
+ </programlisting>
+
+ <!--h3-->
+ </section>
+
+ <!--h2-->
+ </section>
+
+ <section role="h2" id="NETUserGuide-WritingPublish-2FSubscribeApplications">
+ <title>
+ Writing
+ Publish/Subscribe Applications
+ </title>
+
+ <para>
+ This section describes two programs that implement
+ Publish/Subscribe messaging using a topic exchange.
+ </para>
+ <para>
+ • Publisher.cS sends messages to the amq.topic exchange,
+ using the multipart routing keys usa.news, usa.weather,
+ europe.news, and europe.weather.
+ • Listener.cs creates private queues for news, weather,
+ usa, and europe, binding them to the amq.topic exchange using
+ bindings that match the corresponding parts of the multipart
+ routing keys.
+ </para>
+ <para>
+ In this example, the publisher creates messages for topics like
+ news, weather, and sports that happen in regions like Europe,
+ Asia, or the United States. A given consumer may be interested in
+ all weather messages, regardless of region, or it may be
+ interested in news and weather for the United States, but
+ uninterested in items for other regions. In this example, each
+ consumer sets up its own private queues, which receive precisely
+ the messages that particular consumer is interested in.
+ </para>
+ <section role="h3" id="NETUserGuide-RunningthePublishSubscribeExamples">
+ <title>
+ Running
+ the Publish-Subscribe Examples
+ </title>
+ <para>
+ 1) Make sure your PATH contains the directory
+ &lt;home&gt;/qpid/lib
+ </para>
+ <para>
+ 2) Make sure that a qpid broker is running:
+ </para>
+
+
+ <programlisting>
+$ ps -eaf | grep qpidd
+ </programlisting>
+
+
+ <para>
+ If a broker is running, you should see the qpidd process in the
+ output of the above
+ command.
+ </para>
+ <para>
+ 3) In separate windows, start one or more topic subscribers as
+ follows:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-pub-sub--Listener.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-pub-sub-Listener.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ You will see output similar to this:
+ </para>
+
+
+ <programlisting>
+Listening for messages ...
+Declaring queue: usa
+Declaring queue: europe
+Declaring queue: news
+Declaring queue: weather
+ </programlisting>
+
+
+ <para>
+ Each topic consumer creates a set of private queues, and binds
+ each queue to the amq.topic exchange together with a binding that
+ indicates which messages should be routed to the queue.
+ </para>
+ <para>
+ 4) In another window, start the topic publisher, which publishes
+ messages to the amq.topic exchange, as follows:
+ </para>
+
+
+ <programlisting>
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-pub-sub-Producer.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-pub-sub-Producer.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ This program has no output; the messages are routed to the
+ message queues for each topic_consumer as specified by the
+ bindings the consumer created.
+ </para>
+ <para>
+ 5) Go back to the window for each topic consumer. You should see
+ output like this:
+ </para>
+
+
+ <programlisting>
+Message: Message 0 from usa
+Message: Message 0 from news
+Message: Message 0 from weather
+Message: Message 1 from usa
+Message: Message 1 from news
+Message: Message 2 from usa
+Message: Message 2 from news
+Message: Message 3 from usa
+Message: Message 3 from news
+Message: Message 4 from usa
+Message: Message 4 from news
+Message: Message 5 from usa
+Message: Message 5 from news
+Message: Message 6 from usa
+Message: Message 6 from news
+Message: Message 7 from usa
+Message: Message 7 from news
+Message: Message 8 from usa
+Message: Message 8 from news
+Message: Message 9 from usa
+....
+Message: That's all, folks! from weather
+Shutting down listener for control
+Message: That's all, folks! from europe
+Shutting down listener for control
+ </programlisting>
+
+
+ <para>
+ Now we will examine the code for each of these programs. In each
+ section, we will discuss only
+ the code that must be added to the skeleton shown in Section
+ "Creating and Closing Sessions".
+ </para>
+ <!--h3-->
+ </section>
+
+
+ <section role="h3" id="NETUserGuide-PublishingMessagestoaTopicExchange">
+ <title>
+ Publishing
+ Messages to a Topic Exchange
+ </title>
+
+ <para>
+ The first program in the publish/subscribe example, Publisher.cs,
+ defines two new functions: one that publishes messages to the
+ topic exchange, and one that indicates that no more messages are
+ coming.
+ </para>
+ <para>
+ The publishMessages function publishes a series of five messages
+ using the specified routing key.
+ </para>
+
+
+ <programlisting>
+private static void publishMessages(ClientSession session, string routing_key)
+{
+ IMessage message = new Message();
+ // Asynchronous transfer sends messages as quickly as
+ // possible without waiting for confirmation.
+ for (int i = 0; i &lt; 10; i++)
+ {
+ message.clearData();
+ message.appendData(Encoding.UTF8.GetBytes("Message " + i));
+ session.messageTransfer("amq.topic", routing_key, message);
+ }
+}
+ </programlisting>
+
+
+ <para>
+ The noMoreMessages function signals the end of messages using the
+ control routing key, which is reserved for control messages.
+ </para>
+
+
+ <programlisting>
+private static void noMoreMessages(ClientSession session)
+{
+ IMessage message = new Message();
+ // And send a syncrhonous final message to indicate termination.
+ message.clearData();
+ message.appendData(Encoding.UTF8.GetBytes("That's all, folks!"));
+ session.messageTransfer("amq.topic", "control", message);
+ session.sync();
+}
+ </programlisting>
+
+
+ <para>
+ In the main body of the program, messages are published using
+ four different routing keys, and then the end of messages is
+ indicated by a message sent to a separate routing key.
+ </para>
+
+
+ <programlisting>
+publishMessages(session, "usa.news");
+publishMessages(session, "usa.weather");
+publishMessages(session, "europe.news");
+publishMessages(session, "europe.weather");
+
+noMoreMessages(session);
+ </programlisting>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="NETUserGuide-ReadingMessagesfromtheQueue">
+ <title>
+ Reading
+ Messages from the Queue
+ </title>
+
+ <para>
+ The second program in the publish/subscribe example, Listener.cs,
+ creates a local private queue, with a unique name, for each of
+ the four binding keys it specifies: usa.#, europe.#, #.news, and
+ #.weather, and creates a listener.
+ </para>
+
+
+ <programlisting>
+Console.WriteLine("Listening for messages ...");
+// Create a listener
+prepareQueue("usa", "usa.#", session);
+prepareQueue("europe", "europe.#", session);
+prepareQueue("news", "#.news", session);
+prepareQueue("weather", "#.weather", session);
+ </programlisting>
+
+
+ <para>
+ The prepareQueue() method creates a queue using a queue name and
+ a routing key supplied as arguments it then attaches a listener
+ with the session for the created queue and subscribe for this
+ receiving messages from the queue:
+ </para>
+
+
+ <programlisting>
+// Create a unique queue name for this consumer by concatenating
+// the queue name parameter with the Session ID.
+Console.WriteLine("Declaring queue: " + queue);
+session.queueDeclare(queue, Option.EXCLUSIVE, Option.AUTO_DELETE);
+
+// Route messages to the new queue if they match the routing key.
+// Also route any messages to with the "control" routing key to
+// this queue so we know when it's time to stop. A publisher sends
+// a message with the content "That's all, Folks!", using the
+// "control" routing key, when it is finished.
+
+session.exchangeBind(queue, "amq.topic", routing_key);
+session.exchangeBind(queue, "amq.topic", "control");
+
+// subscribe the listener to the queue
+IMessageListener listener = new MessageListener(session);
+session.attachMessageListener(listener, queue);
+session.messageSubscribe(queue);
+ </programlisting>
+ <!--h3-->
+ </section>
+ <!--h2-->
+ </section>
+
+ <section role="h2" id="NETUserGuide-WritingRequest-2FResponseApplications">
+ <title>
+ Writing
+ Request/Response Applications
+ </title>
+
+ <para>
+ In the request/response examples, we write a server that accepts
+ strings from clients and converts them to upper case, sending the
+ result back to the requesting client. This example consists of
+ two programs.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Client.cs is a client application that sends messages to the
+ server.
+ • Server.cs is a service that accepts messages, converts
+ their content to upper case, and sends the result to the
+ amq.direct exchange, using the request's reply-to property as
+ the routing key for the response.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <section role="h3" id="NETUserGuide-RunningtheRequest-2FResponseExamples">
+ <title>
+ Running
+ the Request/Response Examples
+ </title>
+ <para>
+ 1) Make sure your PATH contains the directory
+ &lt;home&gt;/qpid/lib
+ </para>
+ <para>
+ 2) Make sure that a qpid broker is running:
+ </para>
+
+
+ <programlisting>
+$ ps -eaf | grep qpidd
+ </programlisting>
+
+
+ <para>
+ If a broker is running, you should see the qpidd process in the
+ output of the above
+ command.
+ </para>
+ <para>
+ 3) Run the server.
+ </para>
+ <para>
+ $ cd &lt;home&gt;/qpid/examples/direct
+ </para>
+
+
+ <programlisting>
+ With cygwin:
+ </programlisting>
+
+
+ <para>
+ $ ./example-request-response-Server.exe [hostname] [portnumber]
+ </para>
+
+
+ <programlisting>
+ or with mono:
+ </programlisting>
+
+
+ <para>
+ $ mono ./example-request-response-Server.exe [hostname] [portnumber]
+ </para>
+
+
+ <programlisting>
+ You will see output similar to this:
+ </programlisting>
+
+
+ <para>
+ Waiting for requests
+ </para>
+
+
+ <programlisting>
+4) In a separate window, start a client:
+
+$ cd &lt;home&gt;/qpid/examples/direct
+ </programlisting>
+
+
+ <para>
+ With cygwin:
+ </para>
+
+
+ <programlisting>
+$ ./example-request-response-Client.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ or with mono:
+ </para>
+
+
+ <programlisting>
+$ mono ./example-request-response-Client.exe [hostname] [portnumber]
+ </programlisting>
+
+
+ <para>
+ You will see output similar to this:
+ </para>
+
+
+ <programlisting>
+Activating response queue listener for: clientSystem.Byte[]
+Waiting for all responses to arrive ...
+Response: TWAS BRILLIG, AND THE SLITHY TOVES
+Response: DID GIRE AND GYMBLE IN THE WABE.
+Response: ALL MIMSY WERE THE BOROGROVES,
+Response: AND THE MOME RATHS OUTGRABE.
+Shutting down listener for clientSystem.Byte[]
+Response: THAT'S ALL, FOLKS!
+ </programlisting>
+
+
+ <para>
+ 4) Go back to the server window, the output should be similar to
+ this:
+ </para>
+
+
+ <programlisting>
+Waiting for requests
+Request: Twas brillig, and the slithy toves
+Request: Did gire and gymble in the wabe.
+Request: All mimsy were the borogroves,
+Request: And the mome raths outgrabe.
+Request: That's all, folks!
+ </programlisting>
+
+
+ <para>
+ Now we will examine the code for each of these programs. In each
+ section, we will discuss only the code that must be added to the
+ skeleton shown in Section "Creating and Closing Sessions".
+ </para>
+ <!--h3-->
+ </section>
+
+
+ <section role="h3" id="NETUserGuide-TheClientApplication">
+ <title>
+ The Client
+ Application
+ </title>
+
+ <para>
+ The first program in the request-response example, Client.cs,
+ sets up a private response queue to receive responses from the
+ server, then sends messages the server, listening to the response
+ queue for the server's responses.
+ </para>
+
+
+ <programlisting>
+string response_queue = "client" + session.getName();
+// Use the name of the response queue as the routing key
+session.queueDeclare(response_queue);
+session.exchangeBind(response_queue, "amq.direct", response_queue);
+
+// Create a listener for the response queue and listen for response messages.
+Console.WriteLine("Activating response queue listener for: " + response_queue);
+IMessageListener listener = new ClientMessageListener(session);
+session.attachMessageListener(listener, response_queue);
+session.messageSubscribe(response_queue);
+ </programlisting>
+
+
+ <para>
+ Set some properties that will be used for all requests. The
+ routing key for a request is request.
+ The reply-to property is set to the routing key for the client's
+ private queue.
+ </para>
+
+
+ <programlisting>
+IMessage request = new Message();
+request.DeliveryProperties.setRoutingKey("request");
+request.MessageProperties.setReplyTo(new ReplyTo("amq.direct", response_queue));
+ </programlisting>
+
+
+ <para>
+ Now send some requests...
+ </para>
+
+
+ <programlisting>
+string[] strs = {
+ "Twas brillig, and the slithy toves",
+ "Did gire and gymble in the wabe.",
+ "All mimsy were the borogroves,",
+ "And the mome raths outgrabe.",
+ "That's all, folks!"
+ };
+foreach (string s in strs)
+{
+ request.clearData();
+ request.appendData(Encoding.UTF8.GetBytes(s));
+ session.messageTransfer("amq.direct", request);
+}
+ </programlisting>
+
+
+ <para>
+ And wait for responses to arrive:
+ </para>
+
+
+ <programlisting>
+Console.WriteLine("Waiting for all responses to arrive ...");
+Monitor.Wait(session);
+ </programlisting>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="NETUserGuide-TheServerApplication">
+ <title>
+ The Server
+ Application
+ </title>
+
+ <para>
+ The second program in the request-response example, Server.cs,
+ uses the reply-to property as the routing key for responses.
+ </para>
+ <para>
+ The main body of Server.cs creates an exclusive queue for
+ requests, then waits for messages to arrive.
+ </para>
+
+
+ <programlisting>
+const string request_queue = "request";
+// Use the name of the request queue as the routing key
+session.queueDeclare(request_queue);
+session.exchangeBind(request_queue, "amq.direct", request_queue);
+
+lock (session)
+{
+ // Create a listener and subscribe it to the request_queue
+ IMessageListener listener = new MessageListener(session);
+ session.attachMessageListener(listener, request_queue);
+ session.messageSubscribe(request_queue);
+ // Receive messages until all messages are received
+ Console.WriteLine("Waiting for requests");
+ Monitor.Wait(session);
+}
+ </programlisting>
+
+
+ <para>
+ The listener's messageTransfer() method converts the request's
+ content to upper case, then sends a response to the broker, using
+ the request's reply-to property as the routing key for the
+ response.
+ </para>
+
+
+ <programlisting>
+BinaryReader reader = new BinaryReader(request.Body, Encoding.UTF8);
+byte[] body = new byte[request.Body.Length - request.Body.Position];
+reader.Read(body, 0, body.Length);
+ASCIIEncoding enc = new ASCIIEncoding();
+string message = enc.GetString(body);
+Console.WriteLine("Request: " + message);
+
+// Transform message content to upper case
+string responseBody = message.ToUpper();
+
+// Send it back to the user
+response.clearData();
+response.appendData(Encoding.UTF8.GetBytes(responseBody));
+_session.messageTransfer("amq.direct", routingKey, response);
+ </programlisting>
+
+ <!--h3-->
+ </section>
+ <!--h2-->
+ </section>
+ <!--h1-->
+ </section>
+
+
+ </chapter>
diff --git a/doc/book/src/PythonBrokerTest.xml b/doc/book/src/PythonBrokerTest.xml
new file mode 100644
index 0000000000..06c62167c6
--- /dev/null
+++ b/doc/book/src/PythonBrokerTest.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid : PythonBrokerTest
+ </title>
+ <section role="h2" id="PythonBrokerTest-PythonBrokerSystemTestSuite">
+ <title>
+ Python Broker System Test Suite
+ </title>
+ <para>
+ This is a suite of python client tests that exercise and verify
+ broker functionality. Python allows us to rapidly develop client
+ test scenarios and provides a 'neutral' set of tests that can run
+ against any AMQP-compliant broker.
+ </para>
+ <para>
+ The python/tests directory contains a collection of python
+ modules, each containing several unittest classes, each
+ containing a set of test methods that represent some test
+ scenario. Test classes inherit qpid.TestBas from
+ qpid/testlib.py, it inherits unittest.TestCase
+ but adds some qpid-specific setUp/tearDown and
+ convenience functions.
+ </para>
+ <para>
+ TODO: get pydoc generated up to qpid wiki or website
+ automatically?
+ </para>
+ <section role="h3" id="PythonBrokerTest-Runningthetests">
+ <title>
+ Running the tests
+ </title>
+ <para>
+ Simplest way to run the tests:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Run a broker on the default port
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ ./run_tests
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ For additional options: ./run_tests --help
+ </para>
+ <!--h3-->
+ </section>
+
+ <section role="h3" id="PythonBrokerTest-Expectedfailures">
+ <title>
+ Expected failures
+ </title>
+ <para>
+ Until we complete functionality, tests may fail because the
+ tested functionality is missing in the broker. To skip
+ expected failures in the C++ or Java brokers:
+ </para>
+ <programlisting>
+./run_tests -I cpp_failing.txt
+./run_tests -I java_failing.txt
+ </programlisting>
+ <para>
+ If you fix a failure, please remove it from the corresponding
+ list.
+ </para>
+
+ <!--h3-->
+ </section>
+
+ <!--h2-->
+ </section>
+
+</chapter>
diff --git a/doc/book/src/WCF.xml b/doc/book/src/WCF.xml
new file mode 100644
index 0000000000..a5a7f3d844
--- /dev/null
+++ b/doc/book/src/WCF.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xmlns:html="http://www.w3.org/1999/xhtml">
+ <title>
+ Apache Qpid : WCF
+ </title>
+ <section role="h1" id="WCF-Introduction">
+ <title>
+ Introduction
+ </title>
+
+ <para>
+ WCF (<emphasis>Windows Communication Foundation)</emphasis> unifies the .Net
+ communication capabilities into a single, common, general Web
+ service oriented framework. A good WCF tutorial can be found
+ <ulink url="http://www.netfxharmonics.com/2008/11/Understanding-WCF-Services-in-Silverlight-2#WCFSilverlightIntroduction">here</ulink>.
+ </para>
+ <para>
+ WCF separates how service logic is written from how services
+ communicate with clients. Bindings are used to specify the
+ transport, encoding, and protocol details required for clients
+ and services to communicate with each other. Qpid provide a WCF
+ binding: org.apache.qpid.wcf.model.QpidBinding. WCF Services that
+ use the Qpid binding communicate through queues that are
+ dynamically created on a Qpid broker.
+ </para>
+ <!--h1-->
+ </section>
+ <section role="h1" id="WCF-HowtouseQpidbinding">
+ <title>
+ How to use Qpid binding
+ </title>
+
+ <para>
+ WCF services are implemented using:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>A service contract with one or more operation contracts.
+ </para>
+ </listitem>
+ <listitem>
+ <para>A service implementation for those contracts.
+ </para>
+ </listitem>
+ <listitem>
+ <para>A configuration file to provide that implementation with an
+ endpoint and a binding for that specific contract.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following configuration file can be used to configure a Hello
+ Service:
+ </para>
+ <programlisting>
+&lt;configuration&gt;
+ &lt;system.serviceModel&gt;
+ &lt;services&gt;
+ &lt;!-- the service class --&gt;
+ &lt;service name="org.apache.qpid.wcf.demo.HelloService"&gt;
+ &lt;host&gt;
+ &lt;baseAddresses&gt;
+ &lt;!-- Use SOAP over AMQP --&gt;
+ &lt;add baseAddress="soap.amqp:///" /&gt;
+ &lt;/baseAddresses&gt;
+ &lt;/host&gt;
+
+ &lt;endpoint
+ address="Hello"
+ &lt;!-- We use a Qpid Binding, see below def --&gt;
+ binding="customBinding"
+ bindingConfiguration="QpidBinding"
+ &lt;!-- The service contract --&gt;
+ contract="org.apache.qpid.wcf.demo.IHelloContract"/&gt;
+ &lt;/service&gt;
+ &lt;/services&gt;
+
+ &lt;bindings&gt;
+ &lt;customBinding&gt;
+ &lt;!-- cf def of the qpid binding --&gt;
+ &lt;binding name="QpidBinding"&gt;
+ &lt;textMessageEncoding /&gt;
+ &lt;!-- specify the host and port number of the broker --&gt;
+ &lt;QpidTransport
+ host="192.168.1.14"
+ port="5673" /&gt;
+ &lt;/binding&gt;
+ &lt;/customBinding&gt;
+ &lt;/bindings&gt;
+
+ &lt;extensions&gt;
+ &lt;bindingElementExtensions&gt;
+ &lt;!-- use Qpid binding element: org.apache.qpid.wcf.model.QpidTransportElement --&gt;
+ &lt;add
+ name="QpidTransport"
+ type="org.apache.qpid.wcf.model.QpidTransportElement, qpidWCFModel"/&gt;
+ &lt;/bindingElementExtensions&gt;
+ &lt;/extensions&gt;
+
+ &lt;/system.serviceModel&gt;
+&lt;/configuration&gt;
+ </programlisting>
+ <para>
+ Endpoints and bindings can also be set within the service code:
+ </para>
+ <programlisting>
+/* set HostName, portNumber and MyService accordingly */
+Binding binding = new QpidBinding("HostName", portNumber);
+ServiceHost service = new ServiceHost(typeof(MyService), new Uri("soap.amqp:///"));
+service.AddServiceEndpoint(typeof(IBooking), binding, "MyService");
+service.Open();
+....
+ </programlisting>
+ <!--h1-->
+ </section>
+</chapter>
diff --git a/doc/book/src/schemas.xml b/doc/book/src/schemas.xml
index 116dc53598..197a6b98c7 100644
--- a/doc/book/src/schemas.xml
+++ b/doc/book/src/schemas.xml
@@ -1,5 +1,6 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
+ <uri resource="AMQP Ruby Messaging Client.xml" typeId="DocBook"/>
<uri resource="AMQP Compatibility.xml" typeId="DocBook"/>
<uri resource="Qpid Troubleshooting Guide.xml" typeId="DocBook"/>
<uri resource="Book_Info.xml" typeId="DocBook"/>