From dbf8ae9298863c331570a28129343161c85d738d Mon Sep 17 00:00:00 2001 From: Jonathan Robie Date: Wed, 12 May 2010 19:56:06 +0000 Subject: Added WCF section by applying Cliff Jansen's patch (see https://issues.apache.org/jira/browse/QPID-2595). Fixed maps tables by using Variant.h types for integer types in C++. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@943660 13f79535-47bb-0310-9956-ffa450edef68 --- doc/book/src/Programming-In-Apache-Qpid.xml | 485 +++++++++++++++++++++++++++- 1 file changed, 469 insertions(+), 16 deletions(-) (limited to 'doc/book/src/Programming-In-Apache-Qpid.xml') diff --git a/doc/book/src/Programming-In-Apache-Qpid.xml b/doc/book/src/Programming-In-Apache-Qpid.xml index 5fd47e68b4..93d9c4db54 100644 --- a/doc/book/src/Programming-In-Apache-Qpid.xml +++ b/doc/book/src/Programming-In-Apache-Qpid.xml @@ -1133,6 +1133,9 @@ options := map
Logging + To simplify debugging, Qpid provides a logging facility + that prints out messaging events. +
Logging in C++ The Qpidd broker and C++ clients can both use environment @@ -1473,8 +1476,8 @@ sender.send(message) boolboolboolean - intlonglong - longlonglong + intint64long + longint64long floatdoubledouble unicodestringjava.lang.String uuidqpid::types::Uuidjava.util.UUID @@ -1565,14 +1568,12 @@ sender.send(message, true); boolboolboolean - unsigned charunicodechar - unsigned short intint | longshort - unsigned intint | longint - unsigned longint | longlong - charunicodechar - shortint | longshort - intint | longint - longint | longlong + uint16int | longshort + uint32int | longint + uint64int | longlong + int16int | longshort + int32int | longint + int64int | longlong floatfloatfloat doublefloatdouble stringunicodejava.lang.String @@ -1685,20 +1686,22 @@ sender.send(Message("Hello world!")); Python: --> - +
+
Transactions @@ -2696,10 +2699,9 @@ producer.send(m); booleanboolbool - charunicodeThe Python string will contain one Unicode characterint - shortint | longshort - intint | longint - longint | longlong + shortint | longint16 + intint | longint32 + longint | longint64 floatfloatfloat doublefloatdouble java.lang.Stringunicodestd::string @@ -2814,6 +2816,457 @@ variable := ( | )]]>
+ + + Using the Qpid WCF client +
+ XML and Binary Bindings + + The Qpid WCF client provides two bindings, each with support for + Windows .NET transactions. + + The AmqpBinding is suitable for communication between two WCF + applications. By default it uses the WCF binary .NET XML encoder + (BinaryMessageEncodingBindingElement) for efficient message + transmission, but it can also use the text and Message Transmission + Optimization Mechanism (MTOM) encoders. Here is a traditional service + model sample program using the AmqpBinding. It assumes that the queue + "hello_service_node" has been created and configured on the AMQP + broker. + + + Traditional service model "Hello world!" example + channelFactory = + new ChannelFactory(amqpBinding, clientEndpoint); + IHelloService clientProxy = channelFactory.CreateChannel(); + + clientProxy.SayHello("Greetings from WCF client"); + + // wait for service to process the greeting + while (HelloService.GreetingCount == 0) + { + Thread.Sleep(100); + } + channelFactory.Close(); + serviceHost.Close(); + } + catch (Exception e) + { + Console.WriteLine("Exception: {0}", e); + } + } + } +} + ]]> + + + The second binding, AmqpBinaryBinding, is suitable for WCF + applications that need to inter-operate with non-WCF clients or that + wish to have direct access to the raw wire representation of the + message body. It relies on a custom encoder to read and write raw + (binary) content which operates similarly to the ByteStream encoder + (introduced in .NET 4.0). The encoder presents an abstract XML + infoset view of the raw message content on input. On output, the + encoder does the reverse and peels away the XML infoset layer exposing + the raw content to the wire representation of the message body. The + application must do the inverse of what the encoder does to allow the + XML infoset wrapper to cancel properly. This is demonstrated in the + following sample code (using the channel programming model) which + directly manipulates or provides callbacks to the WCF message readers + and writers when the content is consumed. In contrast to the + AmqpBinding sample where the simple greeting is encapsulated in a + compressed SOAP envelope, the wire representation of the message + contains the raw content and is identical and fully interoperable with + the Qpid C++ "Hello world!" example. + + + Binary "Hello world!" example using the channel model + 0) + { + broker = args[0]; + } + + if (args.Length > 1) + { + port = int.Parse(args[1]); + } + + if (args.Length > 2) + { + target = args[2]; + } + + if (args.Length > 3) + { + source = args[3]; + } + + AmqpBinaryBinding binding = new AmqpBinaryBinding(); + binding.BrokerHost = broker; + binding.BrokerPort = port; + + IChannelFactory receiverFactory = binding.BuildChannelFactory(); + receiverFactory.Open(); + IInputChannel receiver = receiverFactory.CreateChannel(new EndpointAddress("amqp:" + source)); + receiver.Open(); + + IChannelFactory senderFactory = binding.BuildChannelFactory(); + senderFactory.Open(); + IOutputChannel sender = senderFactory.CreateChannel(new EndpointAddress("amqp:" + target)); + sender.Open(); + + sender.Send(Message.CreateMessage(MessageVersion.None, "", new HelloWorldBinaryBodyWriter())); + + Message message = receiver.Receive(); + XmlDictionaryReader reader = message.GetReaderAtBodyContents(); + while (!reader.HasValue) + { + reader.Read(); + } + + byte[] binaryContent = reader.ReadContentAsBase64(); + string text = Encoding.UTF8.GetString(binaryContent); + + Console.WriteLine(text); + + senderFactory.Close(); + receiverFactory.Close(); + } + } + + public class HelloWorldBinaryBodyWriter : BodyWriter + { + public HelloWorldBinaryBodyWriter() : base (true) {} + + protected override void OnWriteBodyContents(XmlDictionaryWriter writer) + { + byte[] binaryContent = Encoding.UTF8.GetBytes("Hello world!"); + + // wrap the content: + writer.WriteStartElement("Binary"); + writer.WriteBase64(binaryContent, 0, binaryContent.Length); + } + } +} +]]> + + + Bindings define ChannelFactories and ChannelListeners associated with + an AMQP Broker. WCF will frequently automatically create and manage + the life cycle of a these and the resulting IChannel objects used in + message transfer. The binding parameters that can be set are: + + + WCF Binding Parameters + + + + + + + Parameter + Default + Description + + + + + + BrokerHost + + + localhost + + + The broker's server name. Currently the WCF channel + only supports connections with a single broker. + Failover to multiple brokers will be provided in the + future. + + + + + + BrokerPort + + + 5672 + + + The port the broker is listening on. + + + + + + PrefetchLimit + + + 0 + + + The number of messages to prefetch from the amqp + broker before the application actually consumes them. + Increasing this number can dramatically increase the + read performance in some circumstances. + + + + + + Shared + + + false + + + Indicates if separate channels to the same broker can + share an underlying AMQP tcp connection (provided they + also share the same authentication credentials). + + + + + + TransferMode + + + buffered + + + Indicates whether the channel's encoder uses the WCF + BufferManager cache to temporarily store message + content during the encoding/decoding phase. For small + to medium sized SOAP based messages, buffered is + usually the preferred choice. For binary messages, + streamed TransferMode is the more efficient mode. + + + + +
+
+ +
+ Endpoints + + In Qpid 0.6 the WCF Endpoints map to simple AMQP 0-10 + exchanges (IOutputChannel) or AMQP 0-10 queues (IInputChannel). + The format for an IOutputChannel is + + + + and for an IInputChannel is + + + + The routing key is in fact a default value associated with + the particular channel. Outgoing messages can always have their + routing key uniquely set. + + If the respective queue or exchange doesn't exist, an exception + is thrown when opening the channel. Queues and exchanges can be + created and configured using qpid-config. + +
+ +
+ Message Headers + + AMQP specific message headers can be set on or retrieved + from the ServiceModel.Channels.Message using the AmqpProperties + type. + + For example, on output: + + + + On input the headers can be accessed from the Message or extracted + from the operation context + + + +
+ +
+ Security + + To engage TLS/SSL: + + + + Currently the WCF client only provides SASL PLAIN (i.e. username and + password) authentication. To provide a username and password, you can + set the DefaultAmqpCredential value in the binding. This value can be + overridden or set for a binding's channel factories and listeners, + either by setting the ClientCredentials as a binding parameter, or by + using an AmqpCredential as a binding parameter. The search order for + credentials is the AmqpCredential binding parameter, followed by the + ClientCredentials (unless IgnoreEndpointClientCredentials has been + set), and finally defaulting to the DefaultAmqpCredential of the + binding itself. Here is a sample using ClientCredentials: + + (bindingParameters); +]]> + +
+ +
+ Transactions + + The WCF channel provides a transaction resource manager + module and a recovery module that together provide distributed + transaction support with one-phase optimization. Some + configuration is required on Windows machines to enable + transaction support (see your installation notes or top level + ReadMe.txt file for instructions). Once properly configured, + the Qpid WCF channel acts as any other System.Transactions aware + resource, capable of participating in explicit or implicit + transactions. + + Server code: + + + + Because this operation involves two transaction resources, the + database and the AMQP message broker, this operates as a full two + phase commit transaction managed by the Distributed Transaction + Coordinator service. If the transaction proceeds without error, + both ExactlyOnceReceived is incremented in the database and the AMQP + message is consumed from the broker. Otherwise, ExactlyOnceReceived is + unchanged and AMQP message is returned to its queue on the broker. + + For the client code a few changes are made to the non-transacted + example. For "exactly once" semantics, we set the AMQP "Durable" + message property and enclose the transacted activities in a + TransactionScope: + + channelFactory = + new ChannelFactory(amqpBinding, clientEndpoint); + IHelloService clientProxy = channelFactory.CreateChannel(); + + using (TransactionScope ts = new TransactionScope()) + { + AmqpProperties amqpProperties = new AmqpProperties(); + clientProxy.SayHello("Greetings from WCF client"); + // increment ExactlyOnceSent counter on DB + + ts.Complete(); + } +]]> + +
+
+