//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// .Net StockTrader Sample WCF Application for Benchmarking, Performance Analysis and Design Considerations for Service-Oriented Applications
//======================================================================================================
// The Order Processor Service implementation class/business logic.
//======================================================================================================
using System;
using System.Configuration;
using System.Diagnostics;
using System.Messaging;
using System.Transactions;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
//using ConfigService.ServiceConfigurationBase;
//using ConfigService.ServiceConfigurationUtility;
//using ConfigService.ServiceConfigurationHelper;
using Trade.BusinessServiceDataContract;
using Trade.OrderProcessorContract;
using Trade.OrderProcessorServiceConfigurationSettings;
using Trade.Utility;
//using Trade.OrderProcessorAsyncClient;
namespace Trade.OrderProcessorImplementation
{
///
/// Service class which implements the Order Processor service contract.
/// ReleaseServiceInstanceOnTransactionComplete is marked as false to support transacted batches from the
/// transacted (persisted) durable MSMQ message queue. This is required!
///
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
public class OrderProcessor : IOrderProcessor
{
public OrderProcessor()
{
}
///
/// Interesting in that this service contract is a one-way contract. However, it
// turns out this online check works fine in that we are loosely couple when working with MSMQ
// and still tightly coupled on one-way TCP or HTTP bindings. The behavior is such
// that this method will fail from calling client only on TCP/HTTP one-way (Async)
// bindings, which happens regardless on any method call; but will not fail on MSMQ bindings
// if the messaging service is running. If MSMQ messaging service is not running at the endpoint,
// we will have endpoint not found detection as desired.
///
public void isOnline()
{
return;
}
///
/// SubmitOrder service operation is a service operation that processes order messages from the client
/// coming in via TCP, HTTP, or a non-transacted (volatile) MSMQ WCF binding from either the BSL or another remote instance
/// of the Order Processor Service running in 'Forward' mode.
/// This method *always* uses a System.Transaction tx to ensure database integrity.
/// However, since it is receiving from a non-persisted format, the order could possibly be lost
/// even as database integrity is maintained on the processing of the order itself.
/// This is because if a received order is not processed successfully to the database, the message
/// will not be automatically preserved by the source it is being received from since that source
/// is not a durable (persisted) source.
///
/// Order to submit.
public void SubmitOrder(OrderDataModel order)
{
System.Transactions.TransactionOptions txOps = new TransactionOptions();
txOps.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
txOps.Timeout = TimeSpan.FromSeconds(Settings.SYSTEMDOTTRANSACTION_TIMEOUT);
//Start our System.Transactions tx with the options set above.
using (TransactionScope tx = new TransactionScope(TransactionScopeOption.Required, txOps))
{
try
{
processOrder(order);
//Complete transaction scope!
tx.Complete();
}
catch
{
throw;
}
}
return;
}
///
/// Processes the order and creates holding, or sells stock.
///
/// Order to process.
private void processOrder(OrderDataModel queuedOrder)
{
//You could extend this application by transforming the order message
//as it comes in to another format, if required. In this case,
//no transformation actually takes place since the types are the same.
//You can imagine different systems bridged might have different schema,
//however, and transformations could be rather easily accomplished here.
if (queuedOrder.orderID % Settings.DISPLAYNUMBERORDERITERATIONS == 0)
{
string message = string.Format("Processing Order {0}, symbol {1}, type {2}.", queuedOrder.orderID.ToString(), queuedOrder.symbol, queuedOrder.orderType);
StockTraderUtility.Logger.WriteDebugMessage(message + "\n");
}
ProcessOrder orderService = new ProcessOrder();
orderService.ProcessAndCompleteOrder(queuedOrder);
return;
}
}
}