diff options
| author | Jonathan Robie <jonathan@apache.org> | 2010-01-23 16:39:14 +0000 |
|---|---|---|
| committer | Jonathan Robie <jonathan@apache.org> | 2010-01-23 16:39:14 +0000 |
| commit | 83b3d97aabaf5d6f1ba672080c936de2743186ed (patch) | |
| tree | 86f702297d8b751c02e951c41cf2349cab5d9a2f /doc | |
| parent | 772484f911db95bbc0c1ac599ed72b2ee143bec0 (diff) | |
| download | qpid-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.xml | 87 | ||||
| -rw-r--r-- | doc/book/src/AMQP C++ Messaging Client.xml | 40 | ||||
| -rw-r--r-- | doc/book/src/AMQP Python Messaging Client.xml | 41 | ||||
| -rw-r--r-- | doc/book/src/AMQP Ruby Messaging Client.xml | 19 | ||||
| -rw-r--r-- | doc/book/src/Book.xml | 4 | ||||
| -rw-r--r-- | doc/book/src/Excel AddIn.xml | 148 | ||||
| -rw-r--r-- | doc/book/src/NET User Guide.xml | 1362 | ||||
| -rw-r--r-- | doc/book/src/PythonBrokerTest.xml | 77 | ||||
| -rw-r--r-- | doc/book/src/WCF.xml | 116 | ||||
| -rw-r--r-- | doc/book/src/schemas.xml | 1 |
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><project-root>\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> +<add key="ProcessorAssembly" +value="<path>\qpid\dotnet\client-010\addins\ExcelAddInMessageProcessor\bin\Debug\ExcelAddInMessageProcessor.dll"/> + </programlisting> + <programlisting> + <add key="ProcessorClass" + value="ExcelAddInMessageProcessor.Processor"/> + </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> +<home> + |-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 + <home>/qpid/lib + The examples can be run by executing the provided exe files: + </para> + + + <programlisting> +$ cd <home>/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 > 0 ? args[0] : "localhost"; + int port = args.Length > 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 + <home>/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 <home>/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 <home>/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 < 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 + <home>/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 <home>/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 <home>/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 < 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 + <home>/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 <home>/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 <home>/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 < 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 + <home>/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 <home>/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 <home>/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> +<configuration> + <system.serviceModel> + <services> + <!-- the service class --> + <service name="org.apache.qpid.wcf.demo.HelloService"> + <host> + <baseAddresses> + <!-- Use SOAP over AMQP --> + <add baseAddress="soap.amqp:///" /> + </baseAddresses> + </host> + + <endpoint + address="Hello" + <!-- We use a Qpid Binding, see below def --> + binding="customBinding" + bindingConfiguration="QpidBinding" + <!-- The service contract --> + contract="org.apache.qpid.wcf.demo.IHelloContract"/> + </service> + </services> + + <bindings> + <customBinding> + <!-- cf def of the qpid binding --> + <binding name="QpidBinding"> + <textMessageEncoding /> + <!-- specify the host and port number of the broker --> + <QpidTransport + host="192.168.1.14" + port="5673" /> + </binding> + </customBinding> + </bindings> + + <extensions> + <bindingElementExtensions> + <!-- use Qpid binding element: org.apache.qpid.wcf.model.QpidTransportElement --> + <add + name="QpidTransport" + type="org.apache.qpid.wcf.model.QpidTransportElement, qpidWCFModel"/> + </bindingElementExtensions> + </extensions> + + </system.serviceModel> +</configuration> + </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"/> |
