misc updates for quick start application

This commit is contained in:
markpollack
2008-08-14 07:09:03 +00:00
parent 6e5a741be5
commit 45eb16c6b2
18 changed files with 155 additions and 98 deletions

View File

@@ -4,7 +4,7 @@
<!-- MVC objects -->
<object id="StockController" type="Spring.NmsQuickStart.Client.UI.StockController, Spring.NmsQuickStart.Client">
<property name="StockServiceGateway" ref="StockServiceGateway"/>
<property name="StockService" ref="StockServiceGateway"/>
</object>
<object name="StockAppHandler" type="Spring.NmsQuickStart.Client.Handlers.StockAppHandler, Spring.NmsQuickStart.Client">

View File

@@ -24,23 +24,13 @@
<property name="MessageConverter" ref="XmlMessageConverter"/>
</object>
<!-- Consume messages on queue APP.STOCK.JOE -->
<object id="MessagingContainer" type="Spring.Messaging.Nms.Listener.SimpleMessageListenerContainer, Spring.Messaging.Nms">
<property name="ConnectionFactory" ref="ConnectionFactory"/>
<property name="DestinationName" value="APP.STOCK.JOE"/>
<property name="ConcurrentConsumers" value="1"/>
<property name="MessageListener" ref="MessageListenerAdapter"/>
</object>
<!-- Consume messages on topic APP.STOCK.MARKETDATA -->
<object id="MessagingContainerMarketData" type="Spring.Messaging.Nms.Listener.SimpleMessageListenerContainer, Spring.Messaging.Nms">
<property name="ConnectionFactory" ref="ConnectionFactory"/>
<property name="PubSubDomain" value="true"/>
<property name="DestinationName" value="APP.STOCK.MARKETDATA"/>
<property name="ConcurrentConsumers" value="1"/>
<property name="MessageListener" ref="MessageListenerAdapter"/>
</object>
<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>
<!-- Plain object message handler -->
<object id="MessageListenerAdapter" type="Spring.Messaging.Nms.Listener.Adapter.MessageListenerAdapter, Spring.Messaging.Nms">
<property name="HandlerObject" ref="StockAppHandler"/>
@@ -60,20 +50,5 @@
<property name="DefaultAssemblyName" value="Spring.NmsQuickStart.Common"/>
</object>
<!--
<object name="MultiMessageConverter" type="Spring.NmsQuickStart.Common.Converters.MultiMessageConverter, Spring.NmsQuickStart.Common">
<property name="NamedMessageConverters">
<list>
<ref object="TradeRequestConverter"/>
<ref object="TradeConverter"/>
</list>
</property>
</object>
<object name="TradeRequestConverter" type="Spring.NmsQuickStart.Common.Converters.TradeRequestConverter, Spring.NmsQuickStart.Common"/>
<object name="TradeConverter" type="Spring.NmsQuickStart.Common.Converters.TradeConverter, Spring.NmsQuickStart.Common"/>
-->
</objects>

View File

@@ -1,6 +1,7 @@
using System;
using Apache.NMS;
using Spring.Messaging.Nms.Core;
using Spring.NmsQuickStart.Common.Data;
@@ -8,7 +9,7 @@ using Spring.Objects.Factory;
namespace Spring.NmsQuickStart.Client.Gateways
{
public class NmsStockServiceGateway : NmsGatewaySupport, IStockService, IInitializingObject
public class NmsStockServiceGateway : NmsGatewaySupport, IStockService
{
private IDestination defaultReplyToQueue;
@@ -19,25 +20,12 @@ namespace Spring.NmsQuickStart.Client.Gateways
public void Send(TradeRequest tradeRequest)
{
NmsTemplate.ConvertAndSend(tradeRequest, new ReplyToPostProcessor(defaultReplyToQueue));
}
public class ReplyToPostProcessor : IMessagePostProcessor
{
private IDestination replyToDestination;
public ReplyToPostProcessor(IDestination replyToDestination)
{
this.replyToDestination = replyToDestination;
}
public IMessage PostProcessMessage(IMessage message)
{
message.NMSReplyTo = replyToDestination;
return message;
}
}
NmsTemplate.ConvertAndSendWithDelegate(tradeRequest, delegate(IMessage message)
{
message.NMSReplyTo = defaultReplyToQueue;
message.NMSCorrelationID = new Guid().ToString();
return message;
});
}
}
}

View File

@@ -32,6 +32,8 @@ namespace Spring.NmsQuickStart.Common.Data {
private string orderTypeField;
private string confirmationNumberField;
private bool errorField;
private string errorMessageField;
@@ -76,6 +78,16 @@ namespace Spring.NmsQuickStart.Common.Data {
}
}
/// <remarks/>
public string ConfirmationNumber {
get {
return this.confirmationNumberField;
}
set {
this.confirmationNumberField = value;
}
}
/// <remarks/>
public bool Error {
get {

View File

@@ -7,6 +7,7 @@
<xs:element name="Quantity" type="xs:long"/>
<xs:element name="Price" type="xs:decimal"/>
<xs:element name="OrderType" type="xs:string"/>
<xs:element name="ConfirmationNumber" type="xs:string"/>
<xs:element name="Error" type="xs:boolean"/>
<xs:element name="ErrorMessage" type="xs:string"/>
</xs:sequence>

View File

@@ -18,7 +18,8 @@
<context>
<resource uri="~/Config/Messaging.xml"/>
<resource uri="~/Config/Services.xml"/>
<resource uri="~/Config/Handlers.xml"/>
<resource uri="~/Config/ServiceStubs.xml"/>
</context>
<parsers>

View File

@@ -2,7 +2,10 @@
<objects xmlns="http://www.springframework.net">
<object name="StockAppHandler" type="Spring.NmsQuickStart.Server.Handlers.StockAppHandler, Spring.NmsQuickStart.Server">
<constructor-arg ref="CreditCheckService"/>
<constructor-arg ref="ExecutionVenueService"/>
<constructor-arg ref="TradingService"/>
</object>
</objects>

View File

@@ -6,8 +6,6 @@
<constructor-arg index="0" value="tcp://localhost:61616"/>
</object>
<object name="NmsTemplate" type="Spring.Messaging.Nms.Core.NmsTemplate, Spring.Messaging.Nms">
<property name="ConnectionFactory" ref="ConnectionFactory"/>
<property name="PubSubDomain" value="true"/>
@@ -16,28 +14,15 @@
</object>
<object name="MarketDataGateway" type="Spring.NmsQuickStart.Server.Gateways.MarketDataGateway, Spring.NmsQuickStart.Server">
<object name="MarketDataGateway" type="Spring.NmsQuickStart.Server.Gateways.MarketDataServiceGateway, Spring.NmsQuickStart.Server">
<property name="NmsTemplate" ref="NmsTemplate"/>
</object>
<!-- Consume messages on queue APP.STOCK.REQUEST -->
<!--
<nms:listener-container connection-factory="ConnectionFactory" concurrency="10">
<nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.REQUEST" />
</nms:listener-container>
-->
<object id="MessageListenerContainer" type="Spring.Messaging.Nms.Listener.SimpleMessageListenerContainer, Spring.Messaging.Nms">
<property name="ConnectionFactory" ref="ConnectionFactory"/>
<property name="DestinationName" value="APP.STOCK.REQUEST"/>
<property name="ConcurrentConsumers" value="1"/>
<property name="MessageListener" ref="MessageListenerAdapter"/>
<property name="ExceptionListener" ref="LoggingExceptionListener"/>
</object>
<object name="LoggingExceptionListener" type="Spring.NmsQuickStart.Server.Handlers.LoggingExceptionListener, Spring.NmsQuickStart.Server"/>
<!-- Plain object message handler -->
<object id="MessageListenerAdapter" type="Spring.Messaging.Nms.Listener.Adapter.MessageListenerAdapter, Spring.Messaging.Nms">
<property name="HandlerObject" ref="StockAppHandler"/>
@@ -57,19 +42,4 @@
<property name="DefaultAssemblyName" value="Spring.NmsQuickStart.Common"/>
</object>
<!--
<object name="MultiMessageConverter" type="Spring.NmsQuickStart.Common.Converters.MultiMessageConverter, Spring.NmsQuickStart.Common">
<property name="NamedMessageConverters">
<list>
<ref object="TradeRequestConverter"/>
<ref object="TradeConverter"/>
</list>
</property>
</object>
<object name="TradeRequestConverter" type="Spring.NmsQuickStart.Common.Converters.TradeRequestConverter, Spring.NmsQuickStart.Common"/>
<object name="TradeConverter" type="Spring.NmsQuickStart.Common.Converters.TradeConverter, Spring.NmsQuickStart.Common"/>
-->
</objects>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<object name="CreditCheckService" type="Spring.NmsQuickStart.Server.Services.Stubs.CreditCheckServiceStub, Spring.NmsQuickStart.Server"/>
<object name="ExecutionVenueService" type="Spring.NmsQuickStart.Server.Services.Stubs.ExecutionVenueServiceStub, Spring.NmsQuickStart.Server"/>
<object name="TradingService" type="Spring.NmsQuickStart.Server.Services.Stubs.TradingServiceStub, Spring.NmsQuickStart.Server"/>
</objects>

View File

@@ -11,7 +11,7 @@ namespace Spring.NmsQuickStart.Server.Gateways
private static readonly ILog log = LogManager.GetLogger(typeof (MarketDataServiceGateway));
private readonly Random random;
private int sleepTimeInSeconds = 2;
private TimeSpan sleepTimeInSeconds = new TimeSpan(0,0,0,10,0);
public MarketDataServiceGateway()
@@ -19,7 +19,7 @@ namespace Spring.NmsQuickStart.Server.Gateways
random = new Random();
}
public int SleepTimeInSeconds
public TimeSpan SleepTimeInSeconds
{
set { sleepTimeInSeconds = value; }
}
@@ -32,15 +32,15 @@ namespace Spring.NmsQuickStart.Server.Gateways
log.Info("Sending market data.");
NmsTemplate.ConvertAndSend(data);
log.Info("Sleeping " + sleepTimeInSeconds + " seconds before sending more market data.");
Thread.Sleep(sleepTimeInSeconds*1000);
Thread.Sleep(sleepTimeInSeconds);
}
}
private IDictionary GenerateFakeMarketData()
{
IDictionary md = new Hashtable();
md.Add("TICKER", "CSCO");
md.Add("PRICE", "22" + string.Format("{0:#.###}", Math.Abs(Gaussian())));
md.Add("TICKER", "CSCO");
md.Add("PRICE", string.Format("{0:##.##}", 22+Math.Abs(Gaussian())));
return md;
}

View File

@@ -1,9 +1,9 @@
using System.Collections;
using Common.Logging;
using Spring.NmsQuickStart.Common.Data;
using Spring.NmsQuickStart.Server.Services;
using Spring.Util;
namespace Spring.NmsQuickStart.Server.Handlers
{
@@ -14,22 +14,30 @@ namespace Spring.NmsQuickStart.Server.Handlers
private ICreditCheckService creditCheckService;
private ITradingService tradingService;
public StockAppHandler(IExecutionVenueService executionVenueService, ICreditCheckService creditCheckService, ITradingService tradingService)
{
this.executionVenueService = executionVenueService;
this.creditCheckService = creditCheckService;
this.tradingService = tradingService;
}
public TradeResponse Handle(TradeRequest tradeRequest)
{
TradeResponse tradeResponse;
IList errors = new ArrayList();
ArrayList errors = new ArrayList();
if (creditCheckService.CanExecute(tradeRequest, errors))
{
tradeResponse = executionVenueService.ExecuteTradeRequest(tradeRequest);
tradingService.ProcessTrade(tradeRequest, tradeResponse);
}
else
{
tradeResponse = new TradeResponse();
tradeResponse.Error = true;
tradeResponse.ErrorMessage = errors[0].ToString();
tradeResponse.ErrorMessage = StringUtils.ArrayToCommaDelimitedString(errors.ToArray());
}
tradingService.ProcessTrade(tradeRequest, tradeResponse);
return tradeResponse;
}
}

View File

@@ -18,7 +18,7 @@ namespace Spring.NmsQuickStart.Server
ContextRegistry.GetContext().GetObject("MarketDataGateway") as MarketDataServiceGateway;
ThreadStart job = new ThreadStart(marketDataService.SendMarketData);
Thread thread = new Thread(job);
//thread.Start();
thread.Start();
Console.Out.WriteLine("--- Press <return> to quit ---");
Console.ReadLine();
}

View File

@@ -0,0 +1,16 @@
using System.Collections;
using Spring.NmsQuickStart.Common.Data;
using Spring.NmsQuickStart.Server.Services;
namespace Spring.NmsQuickStart.Server.Services.Stubs
{
public class CreditCheckServiceStub : ICreditCheckService
{
public bool CanExecute(TradeRequest tradeRequest, IList errors)
{
return true;
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using Spring.NmsQuickStart.Common.Data;
using Spring.NmsQuickStart.Server.Services;
namespace Spring.NmsQuickStart.Server.Services.Stubs
{
public class ExecutionVenueServiceStub : IExecutionVenueService
{
public TradeResponse ExecuteTradeRequest(TradeRequest request)
{
TradeResponse response = new TradeResponse();
response.OrderType = request.OrderType;
response.Price = CalculatePrice(request.Ticker, request.Quantity, request.OrderType, request.Price, request.UserName);
response.Quantity = request.Quantity;
response.Ticker = request.Ticker;
response.ConfirmationNumber = new Guid().ToString();
return response;
}
private decimal CalculatePrice(string ticker, long quantity, string ordertype, decimal limitPrice, string userName)
{
// provide as sophisticed an impl as testing requires...for now all the same price.
if (ordertype.CompareTo("LIMIT") == 0)
{
return limitPrice;
}
else
{
return 27.6m;
}
}
}
}

View File

@@ -0,0 +1,15 @@
using Spring.NmsQuickStart.Common.Data;
using Spring.NmsQuickStart.Server.Services;
namespace Spring.NmsQuickStart.Server.Services.Stubs
{
public class TradingServiceStub : ITradingService
{
public void ProcessTrade(TradeRequest request, TradeResponse response)
{
//do nothing implementation, typical implementations would persist state to the database.
}
}
}

View File

@@ -54,6 +54,9 @@
<Compile Include="Services\ICreditCheckService.cs" />
<Compile Include="Services\IExecutionVenueService.cs" />
<Compile Include="Services\ITradingService.cs" />
<Compile Include="Services\Stubs\CreditCheckServiceStub.cs" />
<Compile Include="Services\Stubs\ExecutionVenueServiceStub.cs" />
<Compile Include="Services\Stubs\TradingServiceStub.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
@@ -81,10 +84,13 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Config\ServiceStubs.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Config\Messaging.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Config\Services.xml">
<Content Include="Config\Handlers.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

View File

@@ -88,6 +88,8 @@ namespace Spring.Messaging.Nms.Config
private readonly string MAX_RECOVERY_TIME_ATTRIBUTE = "max-recovery-time";
private readonly string CONNECTION_FACTORY_ATTRIBUTE = "connection-factory";
private readonly string PUBSUB_DOMAIN_ATTRIBUTE = "pubsub-domain";
#endregion
@@ -190,6 +192,10 @@ namespace Spring.Messaging.Nms.Config
parserContext.ReaderContext.GenerateObjectName(containerDefBuilder.RawObjectDefinition);
}
string pubsubDomain = listenerElement.GetAttribute(PUBSUB_DOMAIN_ATTRIBUTE);
containerDefBuilder.AddPropertyValue("PubSubDomain", pubsubDomain);
parserContext.Registry.RegisterObjectDefinition(containerObjectName, containerDefBuilder.ObjectDefinition);
}

View File

@@ -196,6 +196,16 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pubsub-domain" type="xsd:boolean" use="optional" default="false">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
Set to true for the publish-subscribe domain (Topics) or false (the default) for the
point-to-point domain (Queues).
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>