Session Title

Download Report

Transcript Session Title

Messaging Fundamentals

Ted Neward http://www.tedneward.com

Objectives

    Understand the basics of messaging-based communication – what messaging is – how messaging works Recognize when to use it – what messaging offers – what complications messaging presents Learn some of the patterns around messaging – message-exchange patterns – architectural communication approaches See some concrete messaging plumbing

The Goal

  Applications need to talk to one another – no violations of the "Once and Only Once" rule – processing sometimes needs centralization for correctness – processing sometimes needs distribution for scale – either way, machines need to talk to machines The traditional answer has been RPC – "make it look like a function call" – define an interface (for compilation type-safe requirements) – write server-side implementation – tools generate the plumbing necessary between the two

RPC Programming Model

public long add(long l1,long l2); long I = add(5,10); add method stub compiler Request message Method: add Params: 5(long),10(long) Return: 15(long) Response message } public long add(long l1, long l2) { return l1+l2; add method skeleton

The Problem

 RPC can't solve all communication issues – What if the network connectivity is flaky or periodically out?

traveling salesmen, dial-up connections, wireless …

– What if we get huge burst loads?

"the Slashdot effect"

– What if we need to scale out?

"today Duluth; tomorrow, the world!"

– What if we need to offer priority to certain clients?

"It's the VP on port 34865, and he's in a hurry…"

– What if we need transactional semantics when communicating with multiple recipients?

"When it absolutely, positively has to be there"

– What if we evolve?

"We didn't know we needed it when we wrote the spec!"

The Issues

  RPC enables easy communication, at a cost: – request/response communication • for every request, we expect a responseblock caller thread until response is received – servers and servants must be available and well known • RPC proxies typically "pin" against a given server

servant object must be up & running to answer

if server or servant dies, RPC proxies will fail – proxies and stubs are compile-time constants • strong binding/typing makes programming easierbut makes evolution/change harder RPC exposes

behavior

A Solution: Messaging

  Strip the veneer off RPC – RPC == request message + response message – break the messages apart, treat them independently – allows for different message exchange patterns • request-responsefire-and-forgetsolicit-notifyrequest-async response Messaging exposes – instead of creating contracts based on interfaces (RPC) …

data

– create contracts based on message types (Messaging) – Note: seductively similar to RPC

"On a NewCustomer message, create a new customer…"

– strive for context-complete communications

What is messaging?

 Anatomy of a MOM system – Message = headers (routing info) + payload • Delivery can be asynchronousFormat is unspecified (loosely bound) – Destination = named message repository • Decouples message producer/consumerAllows for easier redirection/change of call flow – Runtime = variety of delivery semantics • Reliable, transacted, prioritized, deadline-based,

publish-and-subscribe etc

Provides one or more

channels to deliver messages

Messaging System Examples

    File transfer – Messages: files – Destination: filesystem subdirectory – Runtime: operating system Shared database – Messages: data tuples – Destination: database tables – Runtime: database JMS/MSMQ – Messages: byte, text, object, stream, map – Destination: queues (point-to-point), topics (publish subscribe) – Runtime: MOM support SOAP – Messages: SOAP XML format – Destination: (depends on transport) – Runtime: Axis, WebLogic, etc

Why use messaging?

 Benefits of a MOM system – Use messaging for flexibility – Use messaging to smooth out burst loads – Use messaging for system integration

Why use messaging?

 Use messaging for flexibility – Application now has many more data flow options

Fire-and-forget, multicast, disconnected, load-balancing, flow control, priority routing, etc

– Permits more granular processing logic •

through a series of processing steps when the sequence of steps is not known at design-time and may vary for each message"

Routing Slip systems" [EAI] "routes a message consecutively Content-Based Router [EAI] "handles a situation where the implementation of a single logical function (e.g., inventory check) is spread across multiple physical

– Permits easier maintenance and evolution • change message format without recompiling

uninterested clients

"flow" data from one side to another without modifying

intermediate peers

– Avoid concurrency deadlocks (due to blocking on RPC response)

Why use messaging?

 Use messaging to smooth out burst loads – queues can fill up with messages waiting to be processed – processors/consumers pull messages as fast as possible – if processor nodes can't keep up...

add more processorswait for the burst load to disperse over time

Why use messaging?

 Use messaging for system integration – messaging doesn't require agreement on type system • message

is the type

no agreement on "object semantics" necessary – messaging doesn't require strongly-bound APIs – messaging can bridge several systems (Java, .NET, etc) • XML is absolutely perfect for thisother data representations (CSV, NDR, plain text)

work too

– messaging's flexibility permits easier integration •

Message Translators of message

Message Routers workflow [EAI] permit transmutation [EAI] enable processing

Why use messaging?

  Complications of a message-based system – communication is with queues, not objects

bidirectional communication requires at least two queues: one for the request message, one for the response

– no sense of conversational state • sequence—messages may arrive out of ordersynchronous communication requires addt’l work – no sense of "object identity" • messages come to queues, not objectsdisruption of the usual "client-server" approachmore like "producer-consumer" or "peer-to-peer" For request/response communication, stick with RPC!

Simple Messaging

Sometimes you've just gotta get back to basics

Simple Messaging

    Messaging systems have long been a part of enterprise systems – batch file processing (file == message) – email (email message == message) – database (database tuple(s) == message) Plus a few new ones have cropped up in recent years – instant messengers (instant message == message) – HTTP request (request body == message) When combined with XML (or SOAP) as data payload...

Make use of these!

– in essence, project the RESTful model on the other parts of the systems in your enterprise

REST

 Representational State Transfer (REST) – doctoral thesis of Roy Fielding (Apache chair, 2000) – "Using elements of the client/server, pipe-and-filter, and distributed objects paradigms, this [ 'representational state transfer' ] style optimises the network transfer of representations of a resource. A Web-based application can be viewed as a dynamic graph of state representations (pages) and the potential transitions (links) between states. The result is an architecture that separates server implementation from the client's perception of resources, scales well with large numbers of clients, enables transfer of data in streams of unlimited size and type, supports intermediaries (proxies and gateways) as data transformation and caching components, and concentrates application state within the user agent components.

"

REST

 In other words… – REST takes the position that the Web as it currently exists is all we really need—why reinvent the wheel?

URIs provide unique monikers on the network HTTP provides commands and request/responseHTML/XML provides content format – a RESTful model seeks to establish "resources" and use the basic CRUD methods provided by HTTP (GET, POST, PUT, DELETE) • find an Employee:

GET /employeeDatabase?name='fred'

– returned content body will be employee data • creating a new Employee:

PUT /employeeDatabase

– content body is the employee data • modify an existing Employee:

POST /employeeDatabase?name='fred'

REST

 "Resource Modeling" – goal of RESTful system is to model the data elements • addressable resources (via URIs)uniform interfaces that apply to all resourcesmanipulation of resources through

representations

stateless self-descriptive messages'representations'—multiple content types

accepted or sent

– in essence, we're organizing a distributed application into URI addressable resources that provide the full capabilities of that application solely through HTTP – this is a complete flip from traditional O-O • objects encapsulate data behind processorsREST hides processing behind data

elements/structures

REST

 There's something to be said for this model – consider the World Wide Web: • well-established, well-documented, "debugged"no new infrastructure to establishpayload-agnosticwell-defined solutions (HTTPS, proxies, gateways)obviously extensible (WebDAV, explosive growth)platform-neutral and technology-agnostic – it's hard to argue with success!

REST

 Advantages – REST provides "anarchic scalability" • assumes there is no one central entity of controlarchitectural elements must continue operating

when subjected to unexpected load ("the Slashdot effect")

– REST allows for independent deployment • hardware/software can be introduced over time

w/o breaking clients (the power of the URI and DNS)

not all participants need change/evolve

simultaneously

– REST returns us to simplicity

it's all URLs, HTTP, and HTML/XML; nothing else

REST

 Disadvantages – REST depends a great deal on underlying technology • HTTP uses simple name/value pairs for headersthis leaves out complex headers (a la WS-Sec) – REST requires a loosely-bound API • “interface genericity”no metadata constructs to key from – REST requires more work on your part

EMail Access

    Simple Mail Transfer Protocol (SMTP) – Internet standard for the better part of a decade Post Office Protocol (v3) (POP3) – Internet standard for storing and allowing user email download – widely supported, particularly for web-based email systems (Hotmail, Yahoo! mail, etc) Internet Mail Access Protocol (v4) (IMAP4) – Internet standard for storing and accessing email – more sophisticated than POP3, less widely supported All are straight text-based protocols

EMail Access

 JavaMail – "provides a set of abstract classes defining objects that comprise a mail system." – targets three kinds of developers:

"client, server, or middleware developers interested in building mail and messaging applications…" "application developers who need to 'mail-enable' their applciations" "service providers who need to implement specific access and transfer protocols" (using JavaMail to contact pagers, for example)

– Java enterprise developers are a little bit of all three!

EMail Access

  System.Web.Mail

– specifically geared towards sending SMTP mail – Assembly: System.Web.dll

– MailMessage: encapsulates the message itself • Most properties self-descriptive (To, From, etc)Attachments property allows for mail file

attachments (MailAttachment objects)

custom headers added via Headers property – SmtpServer: static class encapsulating access to SMTP server • Send sends message to SMTP serverNote: no SMTP authorization capability; be careful

when setting this up to avoid creating an open relay server(!)

No POP3/IMAP support in .NET 1.1

EMail Access

 Example: Sending mail

MailMessage msg = new MailMessage(); msg.To = "[email protected]"; msg.From = "[email protected]"; msg.Subject = "Order-4512345112"; msg.Body = " ... "; msg.Headers["X-OrderPriority"] = "Normal"; // could use normal email Priority header, if desired msg.Attachments.Add( new MailAttachment(@"C:\docs\foo.pdf", MailEncoding.Base64)); msg.Attachments.Add( new MailAttachment(@"C:\temp\input4512345112", MailEncoding.Base64)); SmtpMail.SmtpServer = "localhost"; SmtpMail.Send(msg);

Other Access

  File Transfer Protocol (FTP) – simple file transfer from one machine to another – well-known/understood security implications

authentication ports & firewall accessibility

– Java: Apache Commons Net – .NET: Support coming in Whidbey FCL Straight sockets: TCP, UDP – Java: java.net.* – .NET: System.Net.Sockets

Java Messaging System (JMS)

Messaging-Oriented Middleware, Java style

JMS: Java Messaging Service

  Specification for messaging in Java – currently at 1.1

– package javax.jms.* Captures essence of messaging – Synchronous or asynchronous operation – Loosely- or strongly-coupled operation – Point-to-point and publish-and-subscribe – Guaranteed or fast delivery – Transacted send/receive – Prioritized delivery – Deadline-based delivery – Delivery filtering

Modes of operation

  JMS defines two modes: – point-to-point: consumer "takes" message – publish-subscribe: consumer "copies" message APIs are syntactically and semantically similar – both sets inherit from common base classes

JMS Queues

 Point-to-point:

sender Message Message Message Queue receiver receiver sender receiver

JMS Topics

 Publish-subscribe:

publisher publisher Message Message Message Topic durable subscriber (attached) transient subscriber (detached) transient subscriber (attached) durable subscriber (detached) Delivered at re-attachment

Programming Model

  Mostly identical for both P2P and PubSub: – Factories obtained from JNDI for bootstrapping – Connections: physical connection to JMS provider – Sessions: thread-scoped context for sending/receiving msgs – Destinations: obtained from JNDI representing the endpoints – (Examples are all P2P; see docs for PubSub equivalents) Factories and Destinations called

Administered Objects

– intended to be set up by sys admin, not programmers – some JMS providers offer programmatic API

Programming Model

ConnectionFactory creates Connection creates Session creates creates Administered Objects found via JNDI but created and configured via a provider-specific technique MessageProducer produce based on Destination based on MessageConsumer Message sync consume (polling) async consume (callback) async consume (callback) MessageListener

Programming Model

 Creating the Connection: – look up ConnectionFactory, create Connection – call start condition!

only after all setup is complete: race – one Connection instance per JVM is usually enough

String qfname = "jms/MyQueueConnectionFactory"; // Names chosen by system administrator // when setting up the JMS provider Context ctx = new InitialContext(); QueueConnectionFactory qfac = (QueueConnectionFactory)ctx.lookup(qfname); QueueConnection qcon = qfac.createQueueConnection(); // later, after everything else is set up qcon.start(); // we start receiving messages now

Programming Model

 Establishing the thread-scoped Session: – created from Connection – only safe for this thread—synchronize accordingly!

– should messages be run under transactional (JTA) semantics?

– do you want to acknowledge message receipt manually?

QueueConnection qcon = ...; // from previous QueueSession qsession = qcon.createQueueSession(false, // transacted?

Session.AUTO_ACKNOWLEDGE); // acknowledgement mode

Programming Model

 Look up the Destination – again, go back to JNDI – name of the Destination selected by administrator – typically prefixed by "jms/" (not required)

Context ctx = // from before String qname = "jms/MyQueue"; // Name chosen by system administrator when installing // JMS software and configuring initial deployment Queue queue = (Queue)ctx.lookup(qname);

Programming Model

 Senders: Create a Producer – scoped and tied to the Session (and Queue) that created it – use this Producer object to do the actual message send

QueueSession qsession = // from before Queue queue = // from before QueueSender qsender = qsession.createSender(queue);

Programming Model

 Messages – 3 parts: headers, properties, payload

headers are for JMS usage properties are for app usage payload is the actual data Header Properties Body Routing and delivery info used by system Application-level properties Payload - the request, Response or event

Programming Model

0 – 4 (normal), 5 – 9 (expedited).

Unique id Format of “ID:xxx”. Specified by and limited to one provider.

Programming Model

 Senders: Create a Message – use the Session to create one of five kinds of messages: – ByteMessage: payload viewed as a byte array – TextMessage: payload viewed as a String – ObjectMessage: payload viewed as a Serializable object – StreamMessage: payload viewed as a DataOutputStream – MapMessage: payload viewed as a java.util.Map

Programming Model

 Senders: Create a Message

ByteMessage bm = qsession.createByteMessage(); byte[] data = ...; bm.writeBytes(data); TextMessage tm = qsession.createTextMessage(); tm.setText("hello"); ObjectMessage om = qsession.createObjectMessage(); MyObject obj = new MyObject("foo", 7, 2.5); om.setObject(obj); StreamMessage sm = qsession.createStreamMessage(); sm.writeString("foo"); sm.writeInt(7); sm.writeDouble(2.5); MapMessage mm = qsession.createMapMessage(); mm.setInt("num1", 7); mm.setString("name", "foo"); mm.setDouble("num2", 2.5);

Programming Model

 Senders: Send the Message – use the Producer object to send the message – delivery mode:

PERSISTENT: msg remains in queue NON-PERSISTENT: msg clears if nobody receives it

– priority: 0 (MIN) – 9 (MAX) value – time to live: when will msg automatically clear

Message msg = // from before QueueSender qsender = // from before qsender.send(msg); int priority = 0; long timetolive=0; qsender.send(msg, DeliveryMode.PERSISTENT, priority, timetolive); int priority = 9; long timetolive=10*1000; qsender.send(msg, DeliveryMode.NON-PERSISTENT, priority, timetolive);

Programming Model

 Receivers: Create a Consumer – use the Session object to create the Consumer – scoped to the Session and the Destination

QueueSession qsession = // from before Queue queue = // from before QueueReceiver qreceiver = qsession.createReceiver(queue);

Programming Model

 Receivers: Receive Messages (Synchronously) – poll for messages by blocking in receive on Consumer – returns generic Message object; downcast as necessary

while (true) { Message m = qreceiver.receive(); if (m instanceof ByteMessage) { byte data []; int len = ((ByteMessage)m).readBytes(data); } else if (m instanceof TextMessage) { StringBuffer sb = ((TextMessage)m).getText(); } else if (m instanceof ObjectMessage) { MyObject obj = new MyObject(); obj = ((ObjectMessage)m).getObject(); String s = obj.getFoo(); int i = obj.getNum(); } }

Programming Model

 Receivers: Receive Messages (Asynchronously) – register a MessageListener with the Consumer – NOTE: onMessage calls will be on separate threads

qreceiver.setMessageListener(new MessageListener() { public void onMessage(Message m) { try { if (m instanceof StreamMessage) { StringBuffer s = m.readString(); int n = m.readInt(); double d = m.readDouble(); } else if (m instanceof MapMessage) { // . . . and so on } } catch (Throwable t) { // Divert message to Dead Letter queue?

} } });

Programming Model

 Receivers: Selectively receive messages – use selector to filter messages before consuming – properties used to set predicate criteria – uses subset of SQL-92 syntax (predicate clauses) – full set of relational and boolean operators available

JMS Spec, section 3.8

// Sender code TextMessage tm = qsession.createTextMessage(); tm.setText("hello"); tm.setStringProperty("name", "fred"); qsender.send(tm); // Receiver code QueueReceiver qr = qsession.createReceiver(q, "name='fred'"); TextMessage tm = (TextMessage)qr.receive(); StringBuffer data = tm.getText(); // tm.getStringProperty("name").equals("fred"), guaranteed!

Programming Model

 Request/Response messaging – use Requester to simplify send/block-for-response pattern – creates TemporaryQueue (or Topic), sets JMSReplyTo – receiver extracts JMSReplyTo, posts response there

// Rosencrantz.class: QueueRequester qreq = new QueueRequester(qsession, queue); TextMessage tmin = qsess.createTextMessage(); tmin.setText("Hello"); TextMessage tmout = qreq.request(tmin); // blocks // Guildenstern.class: Message msg = ...; Destination reply = msg.getJMSReplyTo() TextMessage tmout = qsess.createTextMessage(); tmout.setText("Hi yourself"); QueueSender qs = qsess.createSender((Queue)reply); qs.send(tmout);

Transactional Programming Model

 Group messages into atomic units – delivery guaranteed under ACID conditions – transacted session (specified at creation) scopes messages – can integrate with JTA (distributed transactions) – no transactional call flow (from sender to receiver) – on commit, all messages delivered, consumed messages ack'd – on abort, all messages discarded

QueueSession qsession = qcon.createQueueSession(tx, ackmode); TextMessage tm = qsession.createTextMessage(); tm.setText("hello"); qsender.send(tm); tm = qsession.createTextMessage(); tm.setText("world"); qsender.send(tm); // Calling qsession.commit() here would send both messages // Calling qsession.abort() here would discard both messages

Microsoft Message Queue (MSMQ)

Messaging-Oriented Middleware, .NET/COM style

MSMQ: Microsoft Message Queueing

  Specification for messaging on Microsoft operating systems – currently at 3.0 (XP, Win2003 Server, client on CE)

2.0 installs on Win2k, 1.0 on NT4, Windows 9x

Captures essence of messaging – Synchronous or asynchronous operation – Loosely- or strongly-coupled operation – Transacted send/receive – Prioritized delivery – Deadline-based delivery – Delivery filtering

System.Messaging

 .NET bindings for MSMQ – wrappers (more or less) for MSMQ 2.0 COM API – managed API obviates (most) need for COMInterop access – System.Messaging

namespace – System.Messaging.dll

assembly – requires full trust to execute; no partially-trusted caller support

Programming Model

 Fairly straightforward: – Create MessageQueue around queue to use – Set properties/filters on MessageQueue – For sending, create Message, populate, Send() – For receiving, establish Formatter, retrieve Message, unpack

Programming Model

 Creating the MessageQueue object: – Queue must already exist on machine; object is just wrapper around native queue – name is case-insensitive (more on this later)

using System.Messaging; string queueName = @".\private$\myqueue"; if (MessageQueue.Exists(queueName)) { // MessageQueue is IDisposable--either use "using" or // make sure to call Close() upon completion // using (MessageQueue myQ = new MessageQueue(queueName)) { // . . .

} }

Programming Model

 Creating the Message: – instantiate new Message – populate Body property with message payload – set Label: application-defined string to identify message – set Extension: app-defined information (byte[])

using (MessageQueue myQ = new MessageQueue(queueName)) { Message msg = new Message("Hello, MSMQ!"); // or use Body property to populate payload } msg.Label = "Greetings";

Programming Model

 Sending the Message: – call MessageQueue.Send() passing Message – overload allows passing "label" to describe the Message

{ completely app-defined, no meaning to MSMQ often used to define behavior on recipient end Message msg = new Message("Hello, MSMQ!"); } myQ.Send(msg); myQ.Send(msg, "greetingmsg");

Programming Model

 Retrieving the Message: – establish the Formatter on the MessageQueue instance – call either Receive(), Peek() or GetAllMessages() – examine the Body property

using (MessageQueue myQ = new MessageQueue(queueName)) { myQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); } Message msg = myQ.Peek(); // retrieves the message without removing it Message msg2 = myQ.Receive(); // removes the message from the queue Console.WriteLine((string)(msg.Body));

Programming Model

 Filtered retrieval: – MessageReadPropertyFilter defines properties of message that will be retrieved – does NOT do any filtering based on the property value of the

using (MessageQueue myQ = new MessageQueue(queueName)) { myQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); myQ.MessageReadPropertyFilter.Label = true; myQ.MessageReadPropertyFilter.Extension = true; // Now those properties will be retrieved as well } Message m = myQ.Receive(); Console.WriteLine(m.Priority); // always 0

Programming Model

 Request/Response messaging: – Message.ResponseQueue indicates response queue – "client" sets this before Send() – "server" responds to this upon Receive() or Peek() – completely application-defined (default is null )

using (MessageQueue responseQueue = new MessageQueue(...), senderQueue = new MessageQueue(...)) { responseQueue.Formatter = ...; // as before Message msg = new Message("Hello, there!"); msg.ResponseQueue = responseQueue; senderQueue.Send(msg); } Message responseMsg = responseQueue.Receive(); Console.WriteLine(responseMsg.Body);

Queues

  Application queues – queues established by admins or programmers – 4 roles: destination, administration, response, report System queues – queues established by MSMQ itself – dead-letter, journal, connector

Application Queues

    Destination queues – stores messages for application use – public or private • public: registered in directory servicesprivate: minimal directory overhead; no lookup Administration queues – used to store system-generated ack messages Response queues – stores application responses to request messages Report queues – public queues storing "report" messages (route tracing)

System Queues

   Journal queues – stores copies of messages sent to/through/from this machine – allows for better quality-of-service guarantees for messages – read-only (can't be directly sent to); much like database logs Dead-letter queues – final resting place of undeliverable messages – one each for transactional and non-transactional Q’s – read-only (can only be read and deleted, not sent to) Connector queues – used for store-and-forward messaging in route

Queues

 Creating the Queue administratively: – ComputerManagement snap-in – Message Queuing, under Services and Applications – right-click folder to create New queue

Queues

 Creating the Queue programmatically: – MessageQueue.Create() to create a queue – MessageQueue.Delete() to remove a queue

using System.Messaging; string queueName = @".\private$\myqueue"; if (!MessageQueue.Exists(queueName)) { MessageQueue.Create(queueName); // or pass boolean true to create transactional queue } MessageQueue.Delete(queueName);

Queue names

 Queue Path ("friendly") name: – SERVER\queuename or .\PRIVATE$\queuename – case-insensitive

Queue names

 Format name: – public, private, direct, distribution list, multicast, machine – multi-format names are 1..* single-element names (send only) – PUBLIC= QueueGUID

public queues only

– PRIVATE= ComputerGUID\QueueNumber

private queues only

– DIRECT= address\QueueName • public or private queuesavoids directory service lookupsupports TCP, OS, HTTP, HTTPS, SPX – MACHINE= ComputerGUID ;JOURNAL • or DEADLETTER or DEADXACTused to access system queues (dead-letter,

journal, etc)

Queue access

  Queues can establish access rights – send, peek, or receive access rights Queues can establish share mode – can open queue in shared mode (default) or in "deny receive" – "deny-receive" grants exclusive access to first accessor

Programming Model

 Message payloads – messages can be any object, subject to Formatter restrictions – three Formatter types: ActiveX, Binary, Xml (default) • ActiveXMessageFormatter: works w/native MSMQBinaryMessageFormatter: uses .NET SerializationXmlMessageFormatter: uses .NET XmlSerializers – set Formatter property on Message instance to send – set Formatter property on MessageQueue instance to read

Programming Model

 Message payloads:

string queueName = @".\private$\myqueue"; using (MessageQueue newQueue = new MessageQueue(queueName)) { CustomObject o2 = new CustomObject(); o2._unexposed = "Do you see this?"; o2.Name = "Fred"; Message m2 = new Message(o2); m2.Formatter = new BinaryMessageFormatter(); newQueue.Send(m2); } newQueue.Formatter = new BinaryMessageFormatter(); recvMsg = newQueue.Receive(); CustomObject otherRecvObj = (CustomObject)recvMsg.Body; Assert.IsTrue(otherRecvObj.Name == "Fred"); Assert.IsTrue(otherRecvObj._unexposed != null); // Binary formatter should use Serialization

Programming Model

 Message priority – set Priority on Message instance

{

– set MessageReadPropertyFilter on MessageQueue

newQueue.MessageReadPropertyFilter.Priority = true; Message msg = new Message("Normal"); msg.Priority = MessagePriority.Normal; newQueue.Send(msg); Message msg2 = new Message("Highest"); msg2.Priority = MessagePriority.Highest; newQueue.Send(msg2); newQueue.Formatter = new XmlMessageFormatter(...); } Message recvMsg1 = newQueue.Receive(); Message recvMsg2 = newQueue.Receive();

Programming Model

 Asynchronous message retrieval – establish delegate callback

ReceiveCompleted or PeekCompleted

– call BeginReceive to set up receive thread and return – delegate called (from thread pool thread) on message arrival • delegate must call EndReceive to obtain Messagedelegate must call BeginReceive again – BeginPeek./EndPeek work the same way

Programming Model

 Asynchronous message retrieval:

public static void RecvCB(object src, ReceiveCompletedEventArgs a) { MessageQueue q = (MessageQueue)src; Message msg = q.EndReceive(a.AsyncResult); // Process msg } q.BeginReceive(); // set up async behavior again using (MessageQueue myQ = MessageQueue.Create(queueName)) { myQ.Formatter = ...; // as usual } myQ.ReceiveCompleted += new ReceiveCompletedEventHandler(RecvCB); myQ.BeginReceive();

Transactional Programming Model

 Group messages into atomic units – delivery guaranteed under ACID conditions – transacted object (MessageQueueTransaction) scopes msgs – on commit, all messages delivered

{

– on abort, all messages discarded

MessageQueueTransaction txn = new MessageQueueTransaction(); txn.Begin(); Message msg1 = new Message("First message"); Message msg2 = new Message("Second message"); mq.Send(msg1, txn); Assert.IsTrue(mq.GetAllMessages().Length == 0); mq.Send(msg2, txn); Assert.IsTrue(mq.GetAllMessages().Length == 0); txn.Commit(); // or txn.Abort() Assert.IsTrue(mq.GetAllMessages().Length == 2); }

Summary

 Messaging provides alternative communication – messaging is flexible – messaging is scalable – messaging can operate over many channels – messaging requires more work on the part of the programmer – many different messaging exchange patterns exist

Summary: Simple Messaging

  Sometimes "old" is better than "new" – well-known security implications – well-understood solutions to known problems (FTP) – well-established architecture already in place – interoperability already in place – better support for independent deployment Sometimes "simple" is better than "complex" – easier diagnostics – easier support – better anarchic scalability

Summary: JMS

 JMS provides convenient Java bindings for messaging – provides both P2P and PubSub semantics – can mimic RPC-style communication using Requestor – can provide more flexibility than vanilla RPC

Summary: MSMQ

  MSMQ provides messaging on Windows – provides both P2P and PubSub semantics – can mimic RPC-style communication using request/response – can provide more flexibility than vanilla RPC System.Messaging provides convenient .NET bindings

Resources

   Web – [EAI] http://www.enterpriseintegrationpatterns.com

– [HTTP] HTTP 1.1 Spec – [SOAP1.2] http://www.w3.org/TR/soap REST – Architectural Styles and the Design of Network-based Software Architectures , by Roy Thomas Fielding (2000, UCIrvine) – RESTWiki: http://internet.conveyor.org/RESTwiki/moin.cgi/ShortSumm aryOfRest Books – Enterprise Integration Patterns (Addison-Wesley)

?

Questions

Credentials

 Who is this guy?

– Independent consultant, architect, mentor – Founding Editor-in-Chief, TheServerSide.NET (www.theserverside.net) – Author • • • •

Server-Based Java Programming Effective Enterprise Java (Manning, 2000) (Addison-Wesley, 2004) C# in a Nutshell (OReilly, 2001) SSCLI Essentials (w/Stutz, Shilling; OReilly, 2003)

– Papers at www.neward.net/ted/Papers – Weblog at www.neward.net/ted/weblog