finish nms quickstart docs
add minimal wcf quickstart docs
This commit is contained in:
@@ -9,19 +9,22 @@
|
||||
messaging to implement a system for purchasing a stock. To purchase a
|
||||
stock, a client application will send a stock request message containing
|
||||
the information about the stock, i.e. ticker symbol, quantity, etc. The
|
||||
client request message will be recieved by the server where it will
|
||||
perform business processing on the requst, for example to determine if the
|
||||
user has sufficient credit to purchase the stock or if the user is even
|
||||
allowed to make the purchase due to existing account restrictions. Usually
|
||||
the server application will persist state about the request and forward it
|
||||
on to an execute venue where the actual execution of the stock request is
|
||||
peformed. In addition, market data for the stock will be sent from the
|
||||
server process to the client. The high level messaging flow is shown
|
||||
below.</para>
|
||||
client request message will be received by the server where it will
|
||||
perform business processing on the request, for example to determine if
|
||||
the user has sufficient credit to purchase the stock or if the user is
|
||||
even allowed to make the purchase due to existing account restrictions.
|
||||
These are typically external processes as well. Usually the server
|
||||
application will persist state about the request and forward it on to an
|
||||
execute venue where the actual execution of the stock request is
|
||||
performed. In addition, market data for the stock will be sent from the
|
||||
server process to the client. The high level exchange of information is
|
||||
shown below.</para>
|
||||
|
||||
<para></para>
|
||||
|
||||
<para></para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/nms-quickstart.jpg" scale="75" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -42,9 +45,14 @@
|
||||
one based on messaging or another middleware technology. The messaging
|
||||
flow showing the queues and topics used is shown below.</para>
|
||||
|
||||
<para> </para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/nms-quickstart-msg-destinations.jpg"
|
||||
role="" scale="75" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para></para>
|
||||
<para>Queues are shown in red and topics in green.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -52,7 +60,7 @@
|
||||
|
||||
<para>Gateways represent the service operation to send a message. The
|
||||
client will send a stock request to the server based on the contract
|
||||
defined by the <classname>IStockService</classname> interface . </para>
|
||||
defined by the <classname>IStockService</classname> interface .</para>
|
||||
|
||||
<programlisting> public interface IStockService
|
||||
{
|
||||
@@ -61,7 +69,7 @@
|
||||
|
||||
<para>The server will send market data to the clients based on the
|
||||
contract defined by the <classname>IMarketDataService</classname>
|
||||
interface. </para>
|
||||
interface.</para>
|
||||
|
||||
<programlisting> public interface IMarketDataService
|
||||
{
|
||||
@@ -78,7 +86,7 @@
|
||||
created. Implementations that use messaging to communicate will be based
|
||||
on the Spring's <classname>NmsGateway</classname> class and will be
|
||||
discussed later. stub or mock implementations can be used for testing
|
||||
purposes. </para>
|
||||
purposes.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -113,7 +121,7 @@
|
||||
</programlisting>
|
||||
|
||||
<para>Running xsd.exe on this schema will result in a class that contains
|
||||
properties for each of the element names. A parital code listing of the
|
||||
properties for each of the element names. A partial code listing of the
|
||||
TradeRequest class is shown below</para>
|
||||
|
||||
<programlisting>// This code was generated by a tool.
|
||||
@@ -148,7 +156,7 @@
|
||||
|
||||
<para>When sending a response back to the client the type
|
||||
<classname>TradeResponse</classname> will be used. The schema for the
|
||||
<classname>TradeResponse</classname> is shown below </para>
|
||||
<classname>TradeResponse</classname> is shown below</para>
|
||||
|
||||
<programlisting><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://www.springframework.net/nms/common/2008-08-05">
|
||||
@@ -202,10 +210,10 @@
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Mesage Handlers</title>
|
||||
<title>Message Handlers</title>
|
||||
|
||||
<para>When the <classname>TradeRequest</classname> message is received by
|
||||
the server, it wll be handled by the class
|
||||
the server, it will be handled by the class
|
||||
<classname>Spring.NmsQuickStart.Server.Handlers.StockAppHandler
|
||||
</classname>shown below</para>
|
||||
|
||||
@@ -236,6 +244,186 @@
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>The stub implementations of the services, located in the namespace
|
||||
<literal>Spring.NmsQuickStart.Server.Services.Stubs</literal>, will result
|
||||
in always sending back a error-free trade response message. A realistic
|
||||
implementation would likely have the execution venue and trading service
|
||||
be remote services and the trading service could be implemented as a local
|
||||
transactional service layer that uses spring's declarative transaction
|
||||
management features.</para>
|
||||
|
||||
<para>The client will receive a TradeResponse message as well as a
|
||||
Hashtable of data representing the market data. The message handle for the
|
||||
client is the class Spring.NmsQuickStart.Client.Handlers.StockAppHandler
|
||||
and is shown below.</para>
|
||||
|
||||
<programlisting> public class StockAppHandler
|
||||
{
|
||||
|
||||
// definition of stockController omitted for brevity.
|
||||
|
||||
public void Handle(Hashtable data)
|
||||
{
|
||||
// forward to controller to update view
|
||||
stockController.UpdateMarketData(data);
|
||||
}
|
||||
|
||||
public void Handle(TradeResponse tradeResponse)
|
||||
{
|
||||
// forward to controller to update view
|
||||
stockController.UpdateTrade(tradeResponse);
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>What is important to note about these handlers is that they contain
|
||||
no messaging API artifacts. As such you can write unit and integration
|
||||
tests against these classes independent of the middleware. The missing
|
||||
link between the messaging world and the objects processed by the message
|
||||
handlers are message converters. Spring's messaging helper classes, i.e.
|
||||
SimpleMessageListenerContainer and NmsTemplate use message converters to
|
||||
pass data to the handlers and to send data via messaging for gateway
|
||||
implementations</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Message Converters</title>
|
||||
|
||||
<para>The implementation of IMessageConverter used is
|
||||
<classname>Spring.NmsQuickStart.Common.Converters.XmlMessageConverter</classname>.
|
||||
This converter adds the ability to marshal and unmarshal objects to and
|
||||
from XML strings. It also uses Spring's
|
||||
<classname>SimpleMessageConverter</classname> to convert Hashtables,
|
||||
strings, and byte arrays. In order to pass information about the
|
||||
serialized type, type information is put in the message properties. The
|
||||
type information can be either the class name or an integer value
|
||||
identifying the type. In systems where the client and server are deployed
|
||||
together and are tightly coupled, sharing the class name is a convenient
|
||||
shortcut. The alternative is to register a type for a given integer value.
|
||||
The XML configuration used to configure these objects is shown
|
||||
below</para>
|
||||
|
||||
<programlisting> <object name="XmlMessageConverter" type="Spring.NmsQuickStart.Common.Converters.XmlMessageConverter, Spring.NmsQuickStart.Common">
|
||||
<property name="TypeMapper" ref="TypeMapper"/>
|
||||
</object>
|
||||
|
||||
<object name="TypeMapper" type="Spring.NmsQuickStart.Common.Converters.TypeMapper, Spring.NmsQuickStart.Common">
|
||||
<!-- use simple configuation style -->
|
||||
<property name="DefaultNamespace" value="Spring.NmsQuickStart.Common.Data"/>
|
||||
<property name="DefaultAssemblyName" value="Spring.NmsQuickStart.Common"/>
|
||||
</object></programlisting>
|
||||
|
||||
<para>This configuration is common between the server and the
|
||||
client.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Messaging Infrastructure</title>
|
||||
|
||||
<para>The implementations of the gateway interfaces inherit from Spring's
|
||||
helper class <classname>NmsGatewaySupport</classname> in order to get easy
|
||||
access to a NmsTemplate for sending. The implementation of the
|
||||
IStockService interface is shown below</para>
|
||||
|
||||
<programlisting> public class NmsStockServiceGateway : NmsGatewaySupport, IStockService
|
||||
{
|
||||
private IDestination defaultReplyToQueue;
|
||||
|
||||
public IDestination DefaultReplyToQueue
|
||||
{
|
||||
set { defaultReplyToQueue = value; }
|
||||
}
|
||||
|
||||
public void Send(TradeRequest tradeRequest)
|
||||
{ // post process message
|
||||
NmsTemplate.ConvertAndSendWithDelegate(tradeRequest, delegate(IMessage message)
|
||||
{
|
||||
message.NMSReplyTo = defaultReplyToQueue;
|
||||
message.NMSCorrelationID = new Guid().ToString();
|
||||
return message;
|
||||
});
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>The use of an anonymous delegate allows makes it very easy to apply
|
||||
any post processing logic to the converted message. </para>
|
||||
|
||||
<para>The object definition for the
|
||||
<classname>NmsStockServiceGateway</classname> is shown below along with
|
||||
its dependent object definitions of NmsTemplate and the
|
||||
ConnectionFactory.</para>
|
||||
|
||||
<para><programlisting> <object name="StockServiceGateway" type="Spring.NmsQuickStart.Client.Gateways.NmsStockServiceGateway, Spring.NmsQuickStart.Client">
|
||||
<property name="NmsTemplate" ref="<emphasis role="bold">NmsTemplate</emphasis>"/>
|
||||
<property name="DefaultReplyToQueue">
|
||||
<object type="Apache.NMS.ActiveMQ.Commands.ActiveMQQueue, Apache.NMS.ActiveMQ">
|
||||
<constructor-arg value="APP.STOCK.JOE"/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object name="<emphasis role="bold">NmsTemplate</emphasis>" type="Spring.Messaging.Nms.Core.NmsTemplate, Spring.Messaging.Nms">
|
||||
<property name="ConnectionFactory" ref="<emphasis role="bold">ConnectionFactory</emphasis>"/>
|
||||
<property name="DefaultDestinationName" value="APP.STOCK.REQUEST"/>
|
||||
<property name="MessageConverter" ref="XmlMessageConverter"/>
|
||||
</object>
|
||||
|
||||
<object id="<emphasis role="bold">ConnectionFactory</emphasis>" type="Apache.NMS.ActiveMQ.ConnectionFactory, Apache.NMS.ActiveMQ">
|
||||
<constructor-arg index="0" value="tcp://localhost:61616"/>
|
||||
</object></programlisting>In this example the 'raw'
|
||||
<classname>Apache.NMS.ActiveMQ.ConnectionFactory </classname>connection
|
||||
factory was used. It would be more efficient resource wise to use Spring's
|
||||
<classname>CachingConnectionFactory</classname> wrapper class so that
|
||||
connections will not be open and closed for each message send as well as
|
||||
allowing for the caching of other intermediate NMS API objects such as
|
||||
sessions and message producers.</para>
|
||||
|
||||
<para>A similar configuration is used on the server to configure the class
|
||||
<classname>Spring.NmsQuickStart.Server.Gateways.MarketDataServiceGateway
|
||||
</classname>that implements the <classname>IMarketDataService</classname>
|
||||
interface. </para>
|
||||
|
||||
<para>Since the client is also a consumer of messages, on the topic
|
||||
APP.STOCK.MARKETDATA and the queue APP.STOCK.JOE (for Trader Joe!), two
|
||||
message listener containers are defined as shown below. </para>
|
||||
|
||||
<programlisting> <nms:listener-container connection-factory="ConnectionFactory">
|
||||
<nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.JOE" />
|
||||
<nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.MARKETDATA" pubsub-domain="true"/>
|
||||
</nms:listener-container></programlisting>
|
||||
|
||||
<para>Refer to the <link linkend="messaging">messages reference
|
||||
docs</link> for all the available attributes to configure the container
|
||||
and also the section on <link
|
||||
linkend="xsd-config-body-schemas-nms">registering the NMS schema</link>
|
||||
with Spring..</para>
|
||||
|
||||
<para>On the server we define a message listener container for the queue
|
||||
APP.STOCK.REQUEST but set the concurrency property to 10 so that 10
|
||||
threads will be consuming messages from the queue.</para>
|
||||
|
||||
<programlisting> <nms:listener-container connection-factory="ConnectionFactory" concurrency="<emphasis
|
||||
role="bold">10</emphasis>">
|
||||
<nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.REQUEST" />
|
||||
</nms:listener-container></programlisting>
|
||||
</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
|
||||
hardcoded 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