add missing quickstart file
This commit is contained in:
241
doc/reference/src/msmq-quickstart.xml
Normal file
241
doc/reference/src/msmq-quickstart.xml
Normal file
@@ -0,0 +1,241 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter id="msmq-quickstart">
|
||||
<title>MSMQ QuickStart</title>
|
||||
|
||||
<section>
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>The MSMQ quick start application demonstrates how to use
|
||||
asynchronous messaging to implement a system for purchasing a stock. Is
|
||||
follows the same basic approach as in the <link
|
||||
linkend="nms-quickstart">NMS QuickStart </link>but is adapted as need for
|
||||
use with MSMQ. Please read the introduction in that chapter to get an
|
||||
overview of the system. </para>
|
||||
|
||||
<para>When there is direct overlap in functionality between the MSMQ and
|
||||
NMS quickstart a reference to the appropriate section in the NMS
|
||||
QuickStart documentation is given.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Message Destinations</title>
|
||||
|
||||
<para>To communicate between th client and server a pair of queues will be
|
||||
used. Messages sent from the client to the server will use the
|
||||
transactional queue named
|
||||
<classname>.\Private$\request.txqueue</classname>. Messages sent from the
|
||||
server to the client will use the transactional queue
|
||||
<classname>.\Private$\response.joe.txqueue</classname>. The queue for
|
||||
messages that cannot be processed, so called 'poison messages' will be
|
||||
sent to the queue <classname>.\Private$\dead.queue</classname>. You can
|
||||
create these queues using the computer management administration console.
|
||||
Private queues are used to simplify the application setup
|
||||
requirements.</para>
|
||||
|
||||
<para>Since MSMQ does not natively support the publish-subscribe messaging
|
||||
style as in other messaging systems, Apache MQ, IBM Websphere MQ, TIBCO
|
||||
EMS, the market data information is sent on the same queue as the
|
||||
responses from the server to the client for trade requests.. </para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Gateways</title>
|
||||
|
||||
<para>The gateway interfaces are the same as those described in the NMS
|
||||
QuickStart <link linkend="nms-gateways">here</link>.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Message Data</title>
|
||||
|
||||
<para>TradeRequest and TradeResponse messages are defined using XML Schema
|
||||
and classes are generated from that schema. This is the same approach as
|
||||
described in more details in the NMS QuickStart <link
|
||||
linkend="nms-messagedata">here</link>.</para>
|
||||
|
||||
<para>An important difference in the types of message data formats
|
||||
supported 'out-of-the-box' with Apache, IBM, TIBCO as compared to
|
||||
Microsoft MSMQ is the latter support sending a hashtable data structure.
|
||||
As a result, the hashtable that was used to send market data information
|
||||
from the server to the client was changed to be of type System.String in
|
||||
the MSMQ example.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Message Handlers</title>
|
||||
|
||||
<para>The message handlers are the same as used in the NMS QuickStart
|
||||
<link linkend="nms-handlers">here</link>, aside from the change of the
|
||||
hashtable data structure to a string. This is an important benefit of
|
||||
enforcing a separation between the messaging specific classes and the
|
||||
business processing layer.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>MessageConverters</title>
|
||||
|
||||
<para>The message converter used is
|
||||
Spring.Messaging.Support.Converters.XmlMessageConverter. It is configured
|
||||
by specifying the data types that will be send and received. Here is a
|
||||
configuration example for types generated from the XML Schema and a plain
|
||||
string.</para>
|
||||
|
||||
<programlisting> <object id="xmlMessageConverter" type="Spring.Messaging.Support.Converters.XmlMessageConverter, Spring.Messaging">
|
||||
<property name="TargetTypes">
|
||||
<list>
|
||||
<value>Spring.MsmqQuickStart.Common.Data.TradeRequest, Spring.MsmqQuickStart.Common</value>
|
||||
<value>Spring.MsmqQuickStart.Common.Data.TradeResponse, Spring.MsmqQuickStart.Common</value>
|
||||
<value>System.String, mscorlib</value>
|
||||
</list>
|
||||
</property>
|
||||
</object></programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Messaging Infrastructure</title>
|
||||
|
||||
<para>The implementations of the gateway interfaces inherit from Spring's
|
||||
helper class <classname>MessageQueueGatewaySupport</classname> in order to
|
||||
get easy access to a <classname>MessageQueueTemplate</classname> for
|
||||
sending. The implementation of the <classname>IStockService</classname>
|
||||
interface is shown below</para>
|
||||
|
||||
<programlisting> public class MsmqStockServiceGateway : MessageQueueGatewaySupport, IStockService
|
||||
{
|
||||
private Random random = new Random();
|
||||
|
||||
private string defaultResponseQueueObjectName;
|
||||
|
||||
public string DefaultResponseQueueObjectName
|
||||
{
|
||||
set { defaultResponseQueueObjectName = value; }
|
||||
}
|
||||
|
||||
public void Send(TradeRequest tradeRequest)
|
||||
{
|
||||
MessageQueueTemplate.ConvertAndSend(tradeRequest, delegate(Message message)
|
||||
{
|
||||
message.ResponseQueue = GetResponseQueue();
|
||||
message.AppSpecific = random.Next();
|
||||
return message;
|
||||
});
|
||||
}
|
||||
|
||||
private MessageQueue GetResponseQueue()
|
||||
{
|
||||
return MessageQueueFactory.CreateMessageQueue(defaultResponseQueueObjectName);
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>The <classname>Send</classname> method is using
|
||||
MessageQueueTemplate's <literal>ConvertAndSend(object obj,
|
||||
MessagePostProcessorDelegate messagePostProcessorDelegate)</literal>
|
||||
method. The anonymous delegate allows you to modify the message
|
||||
properties, such as ResponseQueue and AppSpecific after the message has
|
||||
been converted from an object but before it has been sent. The use of an
|
||||
anonymous delegate allows makes it very easy to apply any post processing
|
||||
logic to the converted message.</para>
|
||||
|
||||
<para>The configuration for <classname>MsmqStockServiceGateway</classname>
|
||||
and all its dependencies is shown below, highlighting important dependency
|
||||
links.</para>
|
||||
|
||||
<programlisting> <object name="stockServiceGateway" type="Spring.MsmqQuickStart.Client.Gateways.MsmqStockServiceGateway, Spring.MsmqQuickStart.Client">
|
||||
<property name="MessageQueueTemplate" ref="<emphasis role="bold">messageQueueTemplate</emphasis>"/>
|
||||
<property name="DefaultResponseQueueObjectName" value="responseTxQueue"/>
|
||||
</object>
|
||||
|
||||
<object id="<emphasis role="bold">messageQueueTemplate</emphasis>" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="requestTxQueue"/>
|
||||
<property name="MessageConverterObjectName" value="<emphasis
|
||||
role="bold">xmlMessageConverter</emphasis>"/>
|
||||
</object>
|
||||
|
||||
<object id="<emphasis role="bold">xmlMessageConverter</emphasis>" type="Spring.Messaging.Support.Converters.XmlMessageConverter, Spring.Messaging">
|
||||
<property name="TargetTypes">
|
||||
<list>
|
||||
<value>Spring.MsmqQuickStart.Common.Data.TradeRequest, Spring.MsmqQuickStart.Common</value>
|
||||
<value>Spring.MsmqQuickStart.Common.Data.TradeResponse, Spring.MsmqQuickStart.Common</value>
|
||||
<value>System.String, mscorlib</value>
|
||||
</list>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id="requestTxQueue" type="Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging">
|
||||
<property name="Path" value=".\Private$\request.txqueue"/>
|
||||
<property name="MessageReadPropertyFilterSetAll" value="true"/>
|
||||
</object>
|
||||
|
||||
<object id="responseTxQueue" type="Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging">
|
||||
<property name="Path" value=".\Private$\response.joe.txqueue"/>
|
||||
<property name="MessageReadPropertyFilterSetAll" value="true"/>
|
||||
</object></programlisting>
|
||||
|
||||
<para>Since the client also needs to listen to incoming messages on the
|
||||
responseTxQueue, a
|
||||
<classname>TransactionalMessageListenerContainer</classname> is
|
||||
configured. The configuration for the message listener container and all
|
||||
its dependencies is shown below, highlighting important dependency
|
||||
links.</para>
|
||||
|
||||
<programlisting> <!-- MSMQ Transaction Manager -->
|
||||
<object id="messageQueueTransactionManager" type="Spring.Messaging.Core.MessageQueueTransactionManager, Spring.Messaging"/>
|
||||
|
||||
<!-- Message Listener Container that uses MSMQ transactional for receives -->
|
||||
<object id="transactionalMessageListenerContainer" type="Spring.Messaging.Listener.TransactionalMessageListenerContainer, Spring.Messaging">
|
||||
<property name="MessageQueueObjectName" value="responseTxQueue"/>
|
||||
<property name="PlatformTransactionManager" ref="messageQueueTransactionManager"/>
|
||||
<property name="MessageListener" ref="<emphasis role="bold">messageListenerAdapter</emphasis>"/>
|
||||
<property name="MessageTransactionExceptionHandler" ref="<emphasis
|
||||
role="bold">sendToQueueExceptionHandler</emphasis>"/>
|
||||
|
||||
</object>
|
||||
|
||||
<!-- Delegate to plain .NET object for message handling -->
|
||||
<object id="<emphasis role="bold">messageListenerAdapter</emphasis>" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging">
|
||||
<property name="HandlerObject" ref="stockAppHandler"/>
|
||||
<property name="DefaultHandlerMethod" value="Handle"/>
|
||||
<property name="MessageConverterObjectName" value="xmlMessageConverter"/>
|
||||
</object>
|
||||
|
||||
<object id="<emphasis role="bold">sendToQueueExceptionHandler</emphasis>" type="Spring.Messaging.Listener.SendToQueueExceptionHandler, Spring.Messaging">
|
||||
<property name="MessageQueueObjectName" value="<emphasis role="bold">deadTxQueue</emphasis>"/>
|
||||
</object>
|
||||
|
||||
<object id="<emphasis role="bold">deadTxQueue</emphasis>" type="Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging">
|
||||
<property name="Path" value=".\Private$\dead.queue"/>
|
||||
<property name="MessageReadPropertyFilterSetAll" value="true"/>
|
||||
</object></programlisting>
|
||||
|
||||
<para>A similar configuration is used on the server to configure the class
|
||||
<classname>Spring.MsmqQuickStart.Server.Gateways.MarketDataServiceGateway
|
||||
</classname>that implements the <classname>IMarketDataService</classname>
|
||||
interface and a
|
||||
<classname>TransactionalMessageListenerContainer</classname> to process
|
||||
messages on the requestTxQueue. You can increase the number of processing
|
||||
thread in the <classname>TransactionalMessageListenerContainer</classname>
|
||||
by setting the property <classname>MaxConcurrentListeners</classname>, the
|
||||
default value is 1.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Running the application</title>
|
||||
|
||||
<para>To run both the client and server make sure that you select
|
||||
'Multiple Startup Projects' within VS.NET. The GUI has a button to make a
|
||||
hard coded trade request and show confirmation in a text box. A text area
|
||||
is used to display the market data. There is a 'Get Portfolio' button that
|
||||
is not implemented at the moment. A picture of the GUI after it has been
|
||||
running for a while and trade has been sent and responded to is shown
|
||||
below.</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/nms-quickstart-gui.png" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para></para>
|
||||
</section>
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user