From stonehenge-commits-return-33-apmail-incubator-stonehenge-commits-archive=incubator.apache.org@incubator.apache.org Fri Dec 19 18:00:31 2008 Return-Path: Delivered-To: apmail-incubator-stonehenge-commits-archive@locus.apache.org Received: (qmail 17159 invoked from network); 19 Dec 2008 18:00:31 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 19 Dec 2008 18:00:31 -0000 Received: (qmail 13902 invoked by uid 500); 19 Dec 2008 18:00:43 -0000 Delivered-To: apmail-incubator-stonehenge-commits-archive@incubator.apache.org Received: (qmail 13890 invoked by uid 500); 19 Dec 2008 18:00:43 -0000 Mailing-List: contact stonehenge-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stonehenge-dev@incubator.apache.org Delivered-To: mailing list stonehenge-commits@incubator.apache.org Delivered-To: moderator for stonehenge-commits@incubator.apache.org Received: (qmail 96280 invoked by uid 99); 19 Dec 2008 17:44:18 -0000 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests=WHOIS_NETSOLPR X-Spam-Check-By: apache.org Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r728078 [3/9] - in /incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution: ./ BasicClient/ BasicClient/Properties/ BusinessServiceConfigurationSettings/ BusinessServiceConfigurationSettings/Properties/ Busine... Date: Fri, 19 Dec 2008 17:43:32 -0000 To: stonehenge-commits@incubator.apache.org From: drewbai@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20081219174335.C722923889D4@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeService.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeService.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeService.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeService.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,850 @@ +// .Net StockTrader Sample WCF Application for Benchmarking, Performance Analysis and Design Considerations for Service-Oriented Applications + +//====================================================================================================== +// The implementation class for the BSL, defining all the business logic. +//====================================================================================================== + +//====================================================================================================== +// Code originally contributed by Microsoft Corporation. +// This contribution to the Stonehenge project is limited strictly +// to the source code that is submitted in this submission. +// Any technology, including underlying platform technology, +// that is referenced or required by the submitted source code +// is not a part of the contribution. +// For example and not by way of limitation, +// any systems/Windows libraries (WPF, WCF, ASP.NET etc.) +// required to run the submitted source code is not a part of the contribution +//====================================================================================================== + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Transactions; +using System.Reflection; +using System.Configuration; +using System.Security.Policy; +using Trade.IDAL; +using Trade.DALFactory; +using Trade.BusinessServiceConfigurationSettings; +using Trade.BusinessServiceDataContract; +using Trade.BusinessServiceContract; +using Trade.Utility; +using Trade.OrderProcessorAsyncClient; +using Trade.OrderProcessorContract; + + +namespace Trade.BusinessServiceImplementation +{ + /// + /// Tradeservice.cs. This is the base service implementation class--the Business Service Layer or BSL. + /// It holds the actual implementation of the business logic for the various + /// business service methods or operations, save for the order submit and processing operations for buys and sells + /// (these are contained in the separate project/namespace SharedOrderProcessClass). Both the + /// ASMX and WCF Service facades flow through this class by exposing a service interface to this logic. + /// This class makes calls to the separate, logical data access layer (DAL). It activates the database + /// layer via a factory model, loading a specific DAL on demand, vs direcly referencing + /// it in the VS project. This helps to further 'decouple' the BSL from the underlying database it operates against. + /// + public class TradeService : ITradeServices + { + private IOrder dalOrder; + private ICustomer dalCustomer; + private IMarketSummary dalMarketSummary; + + //The following are the core functional service method implementations that + //provide for the business functions/back-end processing of the application. + //Each has a counterpart service to the Trade 6.1 WebSphere benchmark application. + //These methods are exposed as industry-standard Web Services via both + //ASMX and Windows Communication Foundation (.NET 3.5) facades. + + //As such, the J2EE/WebSphere front end can easily be used with the + //.NET backend (and vice-versa); simply by configuring the WCF service endpoints. + //The more interesting business logic functions are buy, sell and register new + //accounts, since these actually have some business logic required, and transactions + //involved. + + //Another important point is the use of a (quite simple, actually) DAL technique that enables + //the BSL to be more effectively isolated from the DAL. Read the technical documentation for more + //information. The key here is that our DAL overcomes some previous limitations (for example, see PetShop + //3.0 or 4.0) for enterprise applications that had multiple DAL method calls within a single business logic + //operation yet did not need to or want to invoke a distributed transaction against SQL Server since all operations + //would be against a single database resource. Our new DAL accomplishes this without having + //to pass transaction objects or connections between layers. At the same time, it enables the + //SQL Server 2005 DAL to fully utilize System.Transaction 'lightweight' transaction feature without + //extra code. Newer releases of the Oracle Data Provider for .NET (ODP.NET) also support this feature when using + //Oracle database with the Trade.DAL.Oracle Data Access Layer. + + + public void emptyMethodAction() + { + return; + } + + public void isOnline() + { + return; + } + + /// + /// Logs user in/authenticates against StockTrader database. + /// + /// User id to authenticate. + /// Password for authentication + public AccountDataModel login(string userid, string password) + { + Console.WriteLine("Entering Login"); + //Create instance of a DAL, which could be designed for any type of DB backend. + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + + //As feature of the StockTrader DAL, you will see dal.Open, dal.BeginTransaction, dal.CommitTransaction, + //dal.AbortTransaction and dal.Close methods being invoked in the BSL. The pattern within this BSL is: + //a) Create an instance of the DAL; + //b) Open the DAL; + //c) Start a transaction only if necessary (more than one update/insert/delete involved); + //d) You get to pick ADO.NET transaction or System.Transactions or ServicedComponent, it will work with + // all of the above; StockTrader lets you choose ADO.NET txs or System.Transactions via config. + //e) Close the DAL. This releases the DAL's internal connection back to the connection pool. + + //The implementation "hides" the type of database being used from the BSL, so this BSL will work + //with any type of database you create a DAL for, with no changes in the BSL whatsoever. + + //System.Transactions and SQL Server 2005 and Oracle databases work together + //with a new feature called "lightweight transactions"; which means you do not *need* to have the + //same performance penalty you got with Serviced Components for always invoking the tx as a full + //two-phase operation with DTC logging unless necessary. For now, only SQL Server 2005 and Oracle databases support this feature which + //will automatically keep a transaction as a local database transaction and auto-promote to a distributed tx if needed. + //If operating against a single connection to SQL 2005 or Oracle, will not promote to a DTC-coordinated tx; and hence be much faster. + //On other databases, System.Transactions (and Serviced Components) *always* invoke the DTC, even when + //on a single connection to a single database. So our StockTrader DAL is designed to: + + // 1. Hide DB implementation from BSL so we maintain clean separation of BSL from DAL. + // 2. Let you freely call into the DAL from BSL methods as many times as you want *without* + // creating new separate DB connections; which would invoke the DTC even on SQL Server 2005. + // 3. As a by-product, it also helps you use ADO.NET transactions without worrying about + // passing DB connections/transaction objects between tiers; maintaining cleaner separation + // of BSL from DAL. If using ADO.NET txs; you can accomplish DB-implementation isolation also with + // the Provider Factories introduced with ADO.NET 2.0/.NET 2.0: see for details: + + // http://msdn2.microsoft.com/en-us/library/ms379620(VS.80).aspx + + + + //Note Open() is not really necessary, since the DAL will open a new connection automatically + //if it's internal connection is not already open. It's also free to open up more connections, if desired. + //We use Open() to stick with a consistent pattern in this application, since the Close() method IS + //important. Look for this pattern in all BSL methods below; with a transaction scope defined + //only for operations that actually require a transaction per line (c) above. + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING); + try + { + Console.WriteLine("Leaving Login"); + return dalCustomer.login(userid, password); + } + catch + { + throw; + } + finally + { + //Always close the DAL, this releases its primary DB connection. + dalCustomer.Close(); + } + } + + /// + /// Logs a user out--updates logout count. + /// + /// User id to logout. + public void logout(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + dalCustomer.logOutUser(userID); + return; + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets account data for a user. Transforms data from DataContract to model UI class for HTML display. + /// + /// User id to retrieve data for. + public AccountDataModel getAccountData(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getCustomerByUserID(userID); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets account profile data for a user. Transforms data from DataContract to model UI class for HTML display. + /// + /// User id to retrieve data for. + public AccountProfileDataModel getAccountProfileData(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getAccountProfileData(userID); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets recent orders for a user. Transforms data from DataContract to model UI class for HTML display. + /// + /// User id to retrieve data for. + public List getOrders(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getOrders(userID, false, Settings.MAX_QUERY_TOP_ORDERS,Settings.MAX_QUERY_ORDERS); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets specific top n orders for a user. Transforms data from DataContract to model UI class for HTML display. + /// + /// User id to retrieve data for. + public List getTopOrders(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getOrders(userID, true, Settings.MAX_QUERY_TOP_ORDERS,Settings.MAX_QUERY_ORDERS); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets any closed orders for a user--orders that have been processed. Also updates status to complete. + /// + /// User id to retrieve data for. + public List getClosedOrders(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getClosedOrders(userID); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + + } + + /// + /// Gets holding data for a user. Transforms data from DataContract to model UI class for HTML display. + /// + /// User id to retrieve data for. + public List getHoldings(string userID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getHoldings(userID); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets a holding for a user. Transforms data from DataContract to model UI class for HTML display. + /// + /// User id to retrieve data for. + /// Holding id to retrieve data for. + public HoldingDataModel getHolding(string userID, int holdingID) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.getHolding(userID, holdingID); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Registers/adds new user to database. + /// + /// User id for account creation/login purposes as specified by user. + /// Password as specified by user. + /// Name as specified by user. + /// Address as specified by user. + /// Email as specified by user. + /// Credit card number as specified by user. + /// Open balance as specified by user. + public AccountDataModel register(string userID, string password, string fullname, string address, string email, string creditcard, decimal openBalance) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + + //Switch is two let you configure which transaction model you want to benchmark/test. + switch (Settings.TRANSACTION_MODEL) + { + case (StockTraderUtility.TRANSACTION_MODEL_SYSTEMDOTTRANSACTION_TRANSACTION): + { + System.Transactions.TransactionOptions txOps = new TransactionOptions(); + txOps.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; + txOps.Timeout = TimeSpan.FromSeconds(15); + //Start our System.Transactions tx with the options set above. System.Transactions + //will handle rollbacks automatically if there is an exception; note the + //difference between the System.Transaction case and the ADO.NET transaction case; + //and where the dal.Open() happens (which opens a 'hidden' DB connection in DAL). + //System.Transactions will automatically enlist ANY connection + //opened within the tx scope in the transaction for you. Since it supports distributed + //tx's; it frees you quite a bit, with the caveat of the overhead of doing a distributed + //tx when you do not need one. Hence: lightweight System.Transactions with SQL Server 2005 and Oracle; + //and our DAL designed to take advantage of this important feature (auto-promote to DTC + //only if needed). ADO.NET txs always require an already-open connection before starting a tx. + using (TransactionScope tx = new TransactionScope(TransactionScopeOption.Required, txOps)) + { + //Now open the connection, after entering tx scope. + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + AccountDataModel newCustomer = addNewRegisteredUser(userID, password, fullname, address, email, creditcard, openBalance); + //Scope complete, commit work. + tx.Complete(); + return newCustomer; + } + catch + { + //no rollback needed, infrastructure will never commit without + //scope.Complete() and immediately issue rollback on and unhandled + //exception. + throw; + } + finally + { + dalCustomer.Close(); + } + } + } + + case (StockTraderUtility.TRANSACTION_MODEL_ADONET_TRANSACTION): + { + //ADO.NET TX case: First you need to open the connecton. + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + + //Now you start TX + dalCustomer.BeginADOTransaction(); + try + { + AccountDataModel newCustomer = addNewRegisteredUser(userID, password, fullname, address, email, creditcard, openBalance); + //done, commit. + dalCustomer.CommitADOTransaction(); + return newCustomer; + } + catch + { + //explicit rollback needed. + dalCustomer.RollBackTransaction(); + throw; + } + finally + { + //ALWAYS call dal.Close is using StockTrader DAL implementation; + //this is equivalent to calling Connection.Close() in the DAL -- + //but for a generic DB backend as far as the BSL is concerned. + dalCustomer.Close(); + } + } + } + throw new Exception(Settings.ENABLE_GLOBAL_SYSTEM_DOT_TRANSACTIONS_CONFIGSTRING + ": " + StockTraderUtility.EXCEPTION_MESSAGE_INVALID_TXMMODEL_CONFIG + " Repository ConfigKey table."); + } + + /// + /// Adds user account data to Account table and also profile data to AccountProfile table. + /// + /// + /// + /// + /// + /// + /// + /// + /// + private AccountDataModel addNewRegisteredUser(string userID, string password, string fullname, string address, string email, string creditcard, decimal openBalance) + { + AccountProfileDataModel customerprofile = new AccountProfileDataModel(userID, password, fullname, address, email, creditcard); + dalCustomer.insertAccountProfile(customerprofile); + + //Check our acid test conditions here for transactional testing; we want to test part way through + //the register operations from the BSL, to make sure database is never left in state with one + //insert above going through, and the one below not--the entire BSL operation needs to be + //treated as one logical unit of work. Also note the ordering of operations here: + //since trying to register a non-unique userid might be something that happens frequently in the real + //world, lets do the insert that would fail on this condition first (accountprofile); + //rather than wait and do it last. + if (customerprofile.userID.Equals(StockTraderUtility.ACID_TEST_USER)) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_ACID_REGISTRATION); + AccountDataModel customer = new AccountDataModel(0, userID, DateTime.Now, (decimal)openBalance, 0, (decimal)openBalance, DateTime.Now, 0); + dalCustomer.insertAccount(customer); + return customer; + } + + /// + /// Updates account profile data for a user. + /// + /// Profile data model class with updated info. + public AccountProfileDataModel updateAccountProfile(AccountProfileDataModel profileData) + { + dalCustomer = Trade.DALFactory.Customer.Create(Settings.DAL); + dalCustomer.Open(Settings.TRADEDB_SQL_CONN_STRING);; + try + { + return dalCustomer.update(profileData); + } + catch + { + throw; + } + finally + { + dalCustomer.Close(); + } + } + + /// + /// Gets the current market summary. This results in an expensive DB query in the DAL; hence look to cache data returned for 60 second or so. + /// + public MarketSummaryDataModelWS getMarketSummary() + { + dalMarketSummary = Trade.DALFactory.MarketSummary.Create(Settings.DAL); + dalMarketSummary.Open(Settings.TRADEDB_SQL_CONN_STRING); + try + { + return dalMarketSummary.getMarketSummaryData(); + } + catch + { + throw; + } + finally + { + dalMarketSummary.Close(); + } + } + + /// + /// Gets a single quote based on symbol. + /// + /// Symbol to get data for. + public QuoteDataModel getQuote(string symbol) + { + dalMarketSummary = Trade.DALFactory.MarketSummary.Create(Settings.DAL); + dalMarketSummary.Open(Settings.TRADEDB_SQL_CONN_STRING); + try + { + return dalMarketSummary.getQuote(symbol); + } + catch + { + throw; + } + finally + { + dalMarketSummary.Close(); + } + } + + /// + /// Performs a holding sell operation. + /// Note orderProcessing mode param is not used by StockTrader or IBM Trade 6.1; instead + /// both apps pick this up from the application configuration. + /// + /// User id to create/submit order for. + /// Holding id to sell off. + /// Not used, set to zero. + public OrderDataModel sell(string userID, int holdingID, int orderProcessingMode) + { + //In the case of running in 'Sync_InProcess' mode, then the PlaceOrder method + //will synchronously invoke the processOrder method as part of this service, and not make an + //additional remote service-to-sevice call via WCF. See ProcessOrder.cs. + //note, this method always sells entire holding, quantity is not passed in. This is default behavior of WebSphere Trade 6.1 + return placeOrder(StockTraderUtility.ORDER_TYPE_SELL, userID, holdingID, null, (double)0); + } + + + /// + /// Allows user to sell part of a holding vs. all. + /// This is added functionality that .NET StockTrader implements to allow selling of partial + /// holdings, vs. liquidating the entire holding at once, ala IBM Trade 6.1. This method is + /// exposed by StockTrader as a WCF/Web service; but does not exist in IBM Trade 6.1. + /// + /// User id to submit sell for. + /// Holding id to sell. + /// Number of shares to sell. + public OrderDataModel sellEnhanced(string userID, int holdingID, double quantity) + { + return placeOrder(StockTraderUtility.ORDER_TYPE_SELL_ENHANCED, userID, holdingID, null, quantity); + } + + /// + /// Performs a stock buy operation. + /// Note orderProcessing mode param is not used by StockTrader or IBM Trade 6.1; instead + /// both apps pick this up from the application configuration. + /// + /// User id to create/submit order for. + /// Stock symbol to buy. + /// Shares to buy. + ///Not used. + public OrderDataModel buy(string userID, string symbol, double quantity, int orderProcessingMode) + { + return placeOrder(StockTraderUtility.ORDER_TYPE_BUY, userID, 0, symbol, quantity); + } + + + /// + /// This is the business logic for placing orders, handling txs. + /// StockTrader allows the user to select whether to use the new .NET 2.0 System.Transactions + /// or use ADO.NET Provider-supplied transactions for order placement (buy, sell); and new user registrations. + /// The best choice for performance will vary based on the backend database being used with the + /// application. + /// + /// Buy or sell type. + /// User id to create/submit order for. + /// Holding id to sell. + /// Stock symbol to buy. + /// Shares to buy. + public OrderDataModel placeOrder(string orderType, string userID, int holdingID, string symbol, double quantity) + { + OrderDataModel order = null; + HoldingDataModel holding = new HoldingDataModel(); + dalOrder = Trade.DALFactory.Order.Create(Settings.DAL); + + switch (Settings.TRANSACTION_MODEL) + { + case (StockTraderUtility.TRANSACTION_MODEL_SYSTEMDOTTRANSACTION_TRANSACTION): + { + 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)) + { + dalOrder.Open(Settings.TRADEDB_SQL_CONN_STRING); + try + { + //Business Step 1: create the order header. + order = createOrder(orderType, userID, holdingID, symbol, quantity, ref holding); + + //Business Step 2: Determine which order processing mode to use, + //and either process order right away (sync) and in-process with + //calling ASP.NET Web app; or interface with the + //async WCF Order Processing Service (cooler) via a service-to-service call, + //distributed/remote. + if (Settings.orderMode != StockTraderUtility.ORDER_Sync) + { + //Fire up our async client; we follow the same model here as with the + //StockTrader Web App in that we do not talk 'directly' to the generated proxy + //for the service; rather we channel all calls through a single + //class that then talks to the service proxy. This will aid in more + //easily knowing where communication and proxy logic sits; and make changes to services + //you might want to interface with vs. littering proxy calls throughout the + //business tier itself. + TradeOrderServiceAsyncClient asyncclient = new TradeOrderServiceAsyncClient(Settings.orderMode); + asyncclient.processOrderASync(order); + } + else + { + processOrderSync(order, holding); + } + + //Commit! + tx.Complete(); + return order; + } + //If per chance you are doing step-through debugging through here and are getting a + // "TRANSACTION HAS ABORTED" exception and do not know why, + //it's quite likely you are hitting the 15-second timeout we set in + //ConfigurationSettings for the System.Transaction options so its just doing what we told it to. + //Simply adjust timeout higher, recompile if you need to. + catch + { + throw; + } + finally + { + dalOrder.Close(); + } + } + } + + //Repeat for ADO.NET transactions config option case. + case (StockTraderUtility.TRANSACTION_MODEL_ADONET_TRANSACTION): + { + dalOrder.Open(Settings.TRADEDB_SQL_CONN_STRING); + dalOrder.BeginADOTransaction(); + try + { + //Business Step 1: create the order header. + order = createOrder(orderType, userID, holdingID, symbol, quantity, ref holding); + + //Business Step 2: Determine which order processing mode to use, + //and either process order right away (sync); or interface with the + //async WCF Order Processing Service (cooler) via a service-to-service call. + if (Settings.orderMode != StockTraderUtility.ORDER_Sync) + { + //Fire up our async client; we follow the same model here as with the + //StockTrader Web App in that we do not talk 'directly' to the generated proxy + //for the service; rather we channel all calls through a single + //class that then talks to the service proxy. This will aid in more + //easily knowing where communication and proxy logic sits; and make changes to services + //you might want to interface with vs. littering proxy calls throughout the + //business tier itself. + TradeOrderServiceAsyncClient asyncclient = new TradeOrderServiceAsyncClient(Settings.orderMode); + asyncclient.processOrderASync(order); + dalOrder.CommitADOTransaction(); + } + else + { + processOrderSync(order, holding); + } + dalOrder.CommitADOTransaction(); + return order; + } + catch + { + dalOrder.RollBackTransaction(); + throw; + } + finally + { + dalOrder.Close(); + } + } + } + throw new Exception(Settings.ENABLE_GLOBAL_SYSTEM_DOT_TRANSACTIONS_CONFIGSTRING + ": " + StockTraderUtility.EXCEPTION_MESSAGE_INVALID_TXMMODEL_CONFIG + " Repository ConfigKey table."); + } + + + /// + /// Business logic to create the order header. + /// The order header is always created synchronously by Trade; its the actual + /// processing of the order that can be done asynchrounously via the WCF service. + /// If, however, this service cannot communicate with the async order processor, + /// the order header is rolled back out of the database since we are wrapped in a tx here + /// either ADO.NET tx or System.TransactionScope as noted above, based on user setting. + /// + private OrderDataModel createOrder(string orderType, string userID, int holdingID, string symbol, double quantity, ref HoldingDataModel holding) + { + OrderDataModel order; + switch (orderType) + { + case StockTraderUtility.ORDER_TYPE_SELL: + { + holding = dalOrder.getHolding(holdingID); + if (holding == null) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_INVALID_HOLDING_NOT_FOUND); + order = dalOrder.createOrder(userID, holding.quoteID, StockTraderUtility.ORDER_TYPE_SELL, holding.quantity, holdingID); + break; + } + //StockTrader, unlike WebSphere Trade 6.1, allows users to sell part + //of a holding, not required to dump all shares at once. This business logic + //on the processing side of the pipe is more tricky. Have to check for + //conditions like another order coming in and the shares do not exist anymore + //in the holding, etc. This is not done here--it is done in the ProcessOrder class. + //Here we are merely creatingt he order header as with all orders--note its just the *quantity* variable + //that varies with SELL_ENHANCED case vs. SELL. SELL always uses the total + //number of shares in the holding to sell ala IBM Trade 6.1; here we have obtained from the + //requesting service (for example, the StockTrader Web App), how many shares + //the user actually wants to sell. + case StockTraderUtility.ORDER_TYPE_SELL_ENHANCED: + { + holding = dalOrder.getHolding(holdingID); + if (holding == null) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_INVALID_HOLDING_NOT_FOUND); + //If user requests to sell more shares than in holding, we will just invoke the core + //sell operation which liquidates/sells the entire holding. Seems logical--they will + //get proper notification based on the client order alert in the Web app how many + //were actually sold. + if (quantity > holding.quantity) + { + goto case StockTraderUtility.ORDER_TYPE_SELL; + } + else + { + order = dalOrder.createOrder(userID, holding.quoteID, StockTraderUtility.ORDER_TYPE_SELL, quantity, holdingID); + break; + } + } + case StockTraderUtility.ORDER_TYPE_BUY: + { + //Buys are easier business case! Especially when on unlimited margin accounts :-). + order = dalOrder.createOrder(userID, symbol, StockTraderUtility.ORDER_TYPE_BUY, quantity, -1); + break; + } + default: + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_BADORDERTYPE); + } + return order; + } + + /// + /// Business logic to synchrounously process the order within BSL layer, used with OrderMode="Sync." + /// + /// Order information model class with header info. + /// Holding model class with holding to sell if applicable. + public void processOrderSync(OrderDataModel order, HoldingDataModel holding) + { + try + { + decimal total = 0; + int holdingid = -1; + QuoteDataModel quote = dalOrder.getQuoteForUpdate(order.symbol); + //Get the latest trading price--this is the money going into (or out of) the users account. + order.price = quote.price; + + //Calculate order total, and create/update the Holding. Whole holding + //sells delete the holding, partials sells update the holding with new amount + //(and potentially the order too), and buys create a new holding. + if (order.orderType == StockTraderUtility.ORDER_TYPE_BUY) + { + holdingid = dalOrder.createHolding(order); + total = Convert.ToDecimal(order.quantity) * order.price + order.orderFee; + } + else + if (order.orderType == StockTraderUtility.ORDER_TYPE_SELL) + { + holdingid = sellHolding(order, holding); + total = -1 * Convert.ToDecimal(order.quantity) * order.price + order.orderFee; + } + + //Debit/Credit User Account. Note, if we did not want to allow unlimited margin + //trading, we would change the ordering a bit and add the biz logic here to make + //sure the user has enough money to actually buy the shares they asked for! + + //Now Update Account Balance. + dalOrder.updateAccountBalance(order.accountID, total); + + //Update the stock trading volume and price in the quote table + dalOrder.updateStockPriceVolume(order.quantity, quote); + + //Now perform our ACID tx test, if requested based on order type and acid stock symbols + if (order.symbol.Equals(StockTraderUtility.ACID_TEST_BUY) && order.orderType == StockTraderUtility.ORDER_TYPE_BUY) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_ACID_BUY); + else + if (order.symbol.Equals(StockTraderUtility.ACID_TEST_SELL) && order.orderType == StockTraderUtility.ORDER_TYPE_SELL) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_ACID_SELL); + + //Finally, close the order + order.orderStatus = StockTraderUtility.ORDER_STATUS_CLOSED; + order.completionDate = DateTime.Now; + order.holdingID = holdingid; + dalOrder.closeOrder(order); + //Done! + + return; + } + catch + { + throw; + } + } + + /// + /// Sell the holding. + /// + /// + /// + /// + int sellHolding(OrderDataModel order, HoldingDataModel holding) + { + int holdingid = holding.holdingID; + //There are three distinct business cases here, each needs different treatment: + // a) Quantity requested is less than total shares in the holding -- update holding. + // b) Quantity requested is equal to total shares in the holding -- delete holding. + // c) Quantity requested is greater than total shares in the holding -- delete holding, update order table. + if (order.quantity < holding.quantity) + { + dalOrder.updateHolding(holdingid, order.quantity); + } + else + if (holding.quantity == order.quantity) + { + dalOrder.deleteHolding(holdingid); + } + else + //We now need to back-update the order record quantity to reflect + //fact not all shares originally requested were sold since the holding + //had less shares in it, perhaps due to other orders + //placed against that holding that completed before this one. So we will + //sell the remaining shares, but need to update the final order to reflect this. + if (order.quantity > holding.quantity) + { + dalOrder.deleteHolding(holdingid); + order.quantity = holding.quantity; + dalOrder.updateOrder(order); + } + return holdingid; + } + } +} \ No newline at end of file Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeServiceFacadeWcf.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeServiceFacadeWcf.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeServiceFacadeWcf.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/TradeServiceFacadeWcf.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,175 @@ +// .Net StockTrader Sample WCF Application for Benchmarking, Performance Analysis and Design Considerations for Service-Oriented Applications + +//====================================================================================================== +// TradeServiceFacadeWcf: The WCF/.NET 3.5 Web Service facade to TradeService.cs. +//====================================================================================================== + + +using System; +using System.Collections.Generic; +using System.Text; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Dispatcher; +using System.ServiceModel.Description; +using System.Configuration; +using System.Diagnostics; +using System.Xml; +//using ConfigService.ServiceConfigurationUtility; +using Trade.BusinessServiceConfigurationSettings; +using Trade.BusinessServiceDataContract; +using Trade.BusinessServiceContract; +using Trade.Utility; + +namespace Trade.BusinessServiceImplementation +{ + + /// + /// This is the service facade implementation for WCF-based Trade Business Services. It defines the business service layer operations + /// that are implemented in the TradeService.cs implementation class. + /// + [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)] + public class TradeServiceWcf : ITradeServices + { + static int loginCount; + + public void emptyMethodAction() + { + return; + } + + public AccountDataModel login(string userid, string password) + { + loginCount++; + if (Settings.DISPLAY_WEBSERVICE_LOGINS && (loginCount % Settings.LOGIN_ITERATIONSTO_DISPLAY == 0)) + StockTraderUtility.writeConsoleMessage("Login request # " + loginCount.ToString() + " received. Login is for user id: " + userid + "\n",EventLogEntryType.Information,false, Settings.EVENT_LOG); + TradeService service = new TradeService(); + return service.login(InputText(userid, StockTraderUtility.USERID_MAX_LENGTH), InputText(password, StockTraderUtility.PASSWORD_MAX_LENGTH)); + } + + public List getOrders(string userID) + { + TradeService service = new TradeService(); + return service.getOrders(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + } + + public AccountDataModel getAccountData(string userID) + { + TradeService service = new TradeService(); + return service.getAccountData(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + } + + public AccountProfileDataModel getAccountProfileData(string userID) + { + TradeService service = new TradeService(); + return service.getAccountProfileData(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + } + + public AccountProfileDataModel updateAccountProfile(AccountProfileDataModel profileData) + { + TradeService service = new TradeService(); + return service.updateAccountProfile(profileData); + } + + public void logout(string userID) + { + TradeService service = new TradeService(); + service.logout(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + return; + } + + //note orderProcessing mode param is not used by StockTrader or IBM Trade 6.1; instead + //both apps pick this up from the application configuration. + public OrderDataModel buy(string userID, string symbol, double quantity, int orderProcessingMode) + { + if (quantity <= 0) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_BAD_ORDER_PARMS); + TradeService service = new TradeService(); + return service.buy(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH), InputText(symbol, StockTraderUtility.QUOTESYMBOL_MAX_LENGTH), quantity, orderProcessingMode); + } + + //note orderProcessing mode param is not used by StockTrader or IBM Trade 6.1; instead + //both apps pick this up from the application configuration. + public OrderDataModel sell(string userID, int holdingID, int orderProcessingMode) + { + TradeService service = new TradeService(); + return service.sell(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH), holdingID, orderProcessingMode); + } + + public List getHoldings(string userID) + { + TradeService service = new TradeService(); + return service.getHoldings(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + } + + public AccountDataModel register(string userID, string password, string fullname, string address, string email, string creditcard, decimal openBalance) + { + TradeService service = new TradeService(); + return service.register(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH), InputText(password, StockTraderUtility.PASSWORD_MAX_LENGTH), InputText(fullname, StockTraderUtility.FULLNAME_MAX_LENGTH), InputText(address, StockTraderUtility.ADDRESS_MAX_LENGTH), InputText(email, StockTraderUtility.EMAIL_MAX_LENGTH), InputText(creditcard, StockTraderUtility.CREDITCARD_MAX_LENGTH), openBalance); + } + + public List getClosedOrders(string userID) + { + TradeService service = new TradeService(); + return service.getClosedOrders(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + } + + public MarketSummaryDataModelWS getMarketSummary() + { + TradeService service = new TradeService(); + return service.getMarketSummary(); + } + + public QuoteDataModel getQuote(string symbol) + { + string _symbol = InputText(symbol, StockTraderUtility.QUOTESYMBOL_MAX_LENGTH); + if (_symbol.Length == 0) + return null; + TradeService service = new TradeService(); + return service.getQuote(InputText(symbol, StockTraderUtility.QUOTESYMBOL_MAX_LENGTH)); + } + + public HoldingDataModel getHolding(string userID, int holdingID) + { + TradeService service = new TradeService(); + return service.getHolding(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH), holdingID); + } + + public List getTopOrders(string userID) + { + TradeService service = new TradeService(); + return service.getTopOrders(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH)); + } + + public OrderDataModel sellEnhanced(string userID, int holdingID, double quantity) + { + if (quantity <= 0) + throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_BAD_ORDER_PARMS); + TradeService service = new TradeService(); + return service.sellEnhanced(InputText(userID, StockTraderUtility.USERID_MAX_LENGTH), holdingID, quantity); + } + + //Used for online check in WCF proxy logic for clients to this service; employed in + //StockTrader load-balanced scenarios to ensure application-level failover of + //service-to-service remote calls to clusters running this service. + public void isOnline() + { + return; + } + + private string InputText(string inputString, int maxLength) + { + // check incoming parameters for null or blank string + if ((inputString != null) && (inputString != String.Empty)) + { + inputString = inputString.Trim(); + + //chop the string incase the client-side max length + //fields are bypassed to prevent buffer over-runs + if (inputString.Length > maxLength) + inputString = inputString.Substring(0, maxLength); + } + return inputString; + } + } +} \ No newline at end of file Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/stocktrader.snk URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/stocktrader.snk?rev=728078&view=auto ============================================================================== Binary file - no diff available. Propchange: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/BusinessServiceImplementation/stocktrader.snk ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,156 @@ +// .Net StockTrader Sample WCF Application for Benchmarking, Performance Analysis and Design Considerations for Service-Oriented Applications + +//====================================================================================================== +// This is the client for the OrderProcessorService. +//====================================================================================================== + +//====================================================================================================== +// Code originally contributed by Microsoft Corporation. +// This contribution to the Stonehenge project is limited strictly +// to the source code that is submitted in this submission. +// Any technology, including underlying platform technology, +// that is referenced or required by the submitted source code +// is not a part of the contribution. +// For example and not by way of limitation, +// any systems/Windows libraries (WPF, WCF, ASP.NET etc.) +// required to run the submitted source code is not a part of the contribution +//====================================================================================================== + +using System; +using System.Diagnostics; +using System.Data; +using System.Collections.Generic; +using System.Text; +using System.ServiceModel; +using System.Threading; +using System.ServiceModel.Channels; +using System.Runtime.Serialization; +using System.Globalization; +using System.Reflection; +using Trade.BusinessServiceDataContract; +using Trade.OrderProcessorContract; +using Trade.BusinessServiceConfigurationSettings; +using Trade.Client; +using Trade.Utility; + +namespace Trade.OrderProcessorAsyncClient +{ + + /// + /// This is the WCF client class for the remote Order Processor Services. This class implements channel initialization and + /// load balancing/failover logic across cached channel instances specific to the Configuration Management/Node services + /// implemented in StockTrader via the LoadBalancingClient.Client class, now re-used across all clients + /// implementing the configuration service. + /// + public class TradeOrderServiceAsyncClient : IOrderProcessor + { + public Client.Client opsclient; + private int _orderMode = -1; + private string _clientConfig; + + /// + /// This will initialize the correct client/endpoint based on the OrderMode setting the user has set + /// in the repository. + /// + /// The order mode, determines what type of binding/remote interface is used for communication. + public TradeOrderServiceAsyncClient(int orderMode) + { + _orderMode = orderMode; + switch (orderMode) + { + default: + { + throw new Exception("OrderMode not recognized"); + } + case StockTraderUtility.ORDER_ASync_Http: + { + _clientConfig = Settings.OPS_DOTNET_ENDPOINT_CONFIG_HTTP; + break; + } + + case StockTraderUtility.ORDER_ASync_WSHttp: + { + _clientConfig = Settings.OPS_DOTNET_ENDPOINT_CONFIG_WSHTTP; + break; + } + case StockTraderUtility.ORDER_ASync_WSHttp_WSO2: + { + _clientConfig = Settings.OPS_WSO2_ENDPOINT_CONFIG_WSHTTP; + break; + } + } + opsclient = new Client.Client(typeof(IOrderProcessor),_clientConfig); + } + + /// + /// This returns the base channel type, cast to the specific contract type. + /// + public IOrderProcessor Channel + { + get + { + return (IOrderProcessor)opsclient.Channel; + } + set + { + opsclient.Channel = (IChannel)value; + } + } + + /// + /// The online check method. + /// + public void isOnline() + { + try + { + this.Channel.isOnline(); + return; + } + catch + { + this.Channel = null; + throw; + } + } + + /// + /// Submits an order to a non-transacted queue. + /// + /// + public void SubmitOrder(OrderDataModel order) + { + try + { + this.Channel.SubmitOrder(order); + return; + } + catch + { + this.Channel = null; + throw; + } + } + + /// + /// This method sends an order off to the order processor service, in an async fashion depending on OrderMode setting. + /// + /// Order to submit. + public void processOrderASync(Trade.BusinessServiceDataContract.OrderDataModel order) + { + try + { + SubmitOrder(order); + } + catch (Exception e) + { + string innerException = null; + if (e.InnerException != null) + innerException = e.InnerException.ToString(); + StockTraderUtility.writeErrorConsoleMessage(e.ToString() + "\nInner Exception: " + innerException,EventLogEntryType.Error,true,Settings.EVENT_LOG); + this.Channel = null; + throw; + } + } + } +} \ No newline at end of file Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.csproj URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.csproj?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.csproj (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/OrderProcessorAsyncClient.csproj Fri Dec 19 09:43:28 2008 @@ -0,0 +1,105 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {623BC346-84FA-4B9E-B043-811DB7FBEC2A} + Library + Properties + Trade.OrderProcessorAsyncClient + Trade.OrderProcessorAsyncClient + true + stocktrader.snk + + + + + 2.0 + + + + + + + + + v3.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\release\ + TRACE + prompt + 4 + + + + False + ..\..\SharedLibraries\BasicClient.dll + + + + 3.5 + + + + False + ..\..\..\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\System.Runtime.Serialization.dll + + + False + ..\..\..\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\System.ServiceModel.dll + + + + False + ..\..\SharedLibraries\Trade.BusinessServiceConfigurationSettings.dll + + + False + ..\..\SharedLibraries\Trade.BusinessServiceContract.dll + + + False + ..\..\SharedLibraries\Trade.BusinessServiceDataContract.dll + + + False + ..\..\..\SharedLibraries\OrderProcessorService\Trade.OrderProcessorContract.dll + + + False + ..\..\..\SharedLibraries\BusinessService\Trade.Utility.dll + + + + + + + + + + + + + copy "$(TargetPath)" ..\..\..\..\SharedLibraries +copy "$(TargetDir)$(TargetName).pdb" ..\..\..\..\SharedLibraries + + \ No newline at end of file Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/Properties/AssemblyInfo.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/Properties/AssemblyInfo.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/Properties/AssemblyInfo.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/Properties/AssemblyInfo.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Trade.OrderProcessorAsyncClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct(".NET StockTrader")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("cd074ac1-9e3d-4fb1-ae01-377a7e59f234")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("2.0.2.0")] +[assembly: AssemblyFileVersion("2.0.2.0")] Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/stocktrader.snk URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/stocktrader.snk?rev=728078&view=auto ============================================================================== Binary file - no diff available. Propchange: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorASyncClient/stocktrader.snk ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/OrderProcessorServiceConfigurationSettings.csproj URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/OrderProcessorServiceConfigurationSettings.csproj?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/OrderProcessorServiceConfigurationSettings.csproj (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/OrderProcessorServiceConfigurationSettings.csproj Fri Dec 19 09:43:28 2008 @@ -0,0 +1,83 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B28867CC-DD77-4F17-BA01-92625C235F6C} + Library + Properties + Trade.OrderProcessorServiceConfigurationSettings + Trade.OrderProcessorServiceConfigurationSettings + true + stocktrader.snk + + + + + 2.0 + + + + + + + + + v3.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\release\ + TRACE + prompt + 4 + + + + + + 3.5 + + + + + False + ..\..\..\..\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\System.ServiceModel.dll + + + + False + ..\..\SharedLibraries\Trade.Utility.dll + + + + + + + + + + + + + copy "$(TargetPath)" ..\..\..\..\SharedLibraries +copy "$(TargetDir)$(TargetName).pdb" ..\..\..\..\SharedLibraries + + \ No newline at end of file Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Properties/AssemblyInfo.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Properties/AssemblyInfo.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Properties/AssemblyInfo.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Properties/AssemblyInfo.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Trade.OrderProcessorServiceConfigurationSettings")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct(".NET StockTrader")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a601f9cf-771c-4865-a0c4-42f9e5abe84c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("2.0.2.0")] +[assembly: AssemblyFileVersion("2.0.2.0")] Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Settings.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Settings.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Settings.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/Settings.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,122 @@ +// .Net StockTrader Sample WCF Application for Benchmarking, Performance Analysis and Design Considerations for Service-Oriented Applications + +//====================================================================================================== +// The Settings class for the Order Processor Service. Please note well that we only override the +// inherited settings (with the new keyword) becuase of the special case StockTrader allows for running +// OPS in-process with the Business Service layer, vs. remote. You will NOT need to do this for your +// services--your Settings class will be much simpler, simply using the *inherited* global settings, and only +// specifying app-specific settings here. +//====================================================================================================== +//====================================================================================================== +// Code originally contributed by Microsoft Corporation. +// This contribution to the Stonehenge project is limited strictly +// to the source code that is submitted in this submission. +// Any technology, including underlying platform technology, +// that is referenced or required by the submitted source code +// is not a part of the contribution. +// For example and not by way of limitation, +// any systems/Windows libraries (WPF, WCF, ASP.NET etc.) +// required to run the submitted source code is not a part of the contribution +//====================================================================================================== + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Web; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.Data; +//using System.Collections; +using System.Diagnostics; +using System.Messaging; +using System.Text; +using System.Reflection; + +using Trade.Utility; + + +namespace Trade.OrderProcessorServiceConfigurationSettings +{ + /// + /// Any app or service implementing the Configuration Service needs a custom Settings class that will contain it's + /// app-specific config settings. These are loaded from the SQL repository on startup with current values as set for service. + /// Your custom settings class should inherit from the ConfigurationSettingsBase class, which contains common + /// settings used by all services implementing the config service, in addition to the app-specific settings defined here. + /// + public class Settings + { + + + + public static string EVENT_LOG = "Order Processor Event Log"; + + public static string ORDER_PROCESSING_MODE; + public static string DBServer; + public static string Database; + public static string UserID; + public static string Password; + public static int MinDBConnections; + public static int MaxDBConnections; + public static string TRADEDB_SQL_CONN_STRING; + public static string DAL; + public static string ENABLE_GLOBAL_SYSTEM_DOT_TRANSACTIONS_CONFIGSTRING; + public static int SYSTEMDOTTRANSACTION_TIMEOUT; + public static string ORDER_PROCESSING_BEHAVIOR; + public static int DISPLAYNUMBERORDERITERATIONS; + + public Settings() + { + + Settings.ORDER_PROCESSING_MODE = ConfigurationManager.AppSettings.Get("ORDER_PROCESSING_MODE"); + Settings.DBServer = ConfigurationManager.AppSettings.Get("DBServer"); + Settings.Database = ConfigurationManager.AppSettings.Get("Database"); + Settings.UserID = ConfigurationManager.AppSettings.Get("UserID"); + Settings.Password = ConfigurationManager.AppSettings.Get("Password"); + Settings.MinDBConnections = Convert.ToInt32(ConfigurationManager.AppSettings.Get("MinDBConnections")); + Settings.MaxDBConnections = Convert.ToInt32(ConfigurationManager.AppSettings.Get("MaxDBConnections")); + Settings.DAL = ConfigurationManager.AppSettings.Get("DAL"); + Settings.ENABLE_GLOBAL_SYSTEM_DOT_TRANSACTIONS_CONFIGSTRING = ConfigurationManager.AppSettings.Get("ENABLE_GLOBAL_SYSTEM_DOT_TRANSACTIONS_CONFIGSTRING"); + Settings.SYSTEMDOTTRANSACTION_TIMEOUT = Convert.ToInt32(ConfigurationManager.AppSettings.Get("SYSTEMDOTTRANSACTION_TIMEOUT")); + Settings.ORDER_PROCESSING_BEHAVIOR = ConfigurationManager.AppSettings.Get("ORDER_PROCESSING_BEHAVIOR"); + Settings.DISPLAYNUMBERORDERITERATIONS = Convert.ToInt32(ConfigurationManager.AppSettings.Get("DISPLAYNUMBERORDERITERATIONS")); + buildConnString(); + } + + /// + /// This method builds a connection string based on DAL setting and settings for the database name, location, uid and password. + /// Called on host initialization and also when the DAL or DB connection parameters are changed via ConfigWeb. + /// + private void buildConnString() + { + switch (Settings.DAL) + { + case Trade.Utility.StockTraderUtility.DAL_SQLSERVER: + { + Settings.TRADEDB_SQL_CONN_STRING = "server=" + Settings.DBServer + ";database=" + Settings.Database + ";user id=" + Settings.UserID + ";password=" + Settings.Password + ";min pool size=" + Settings.MinDBConnections + ";max pool size=" + Settings.MaxDBConnections; + break; + } + + case Trade.Utility.StockTraderUtility.DAL_ORACLE: + { + Settings.TRADEDB_SQL_CONN_STRING = "Data Source=" + Settings.Database + ";user id=" + Settings.UserID + ";password=" + Settings.Password + ";min pool size=" + Settings.MinDBConnections + ";max pool size=" + Settings.MaxDBConnections + ";enlist=dynamic;"; + break; + } + + case Trade.Utility.StockTraderUtility.DAL_DB2: + { + Settings.TRADEDB_SQL_CONN_STRING = "Network Transport Library=TCPIP;Network Address=" + Settings.DBServer + ";Initial Catalog=" + Settings.Database + ";Package Collection=" + Settings.Database + ";Default Schema=Schema;User ID=" + Settings.UserID + ";Password=" + Settings.Password + ";network port=50000;Units of Work=RUW; Connection Pooling=True;defer prepare=false;CCSID=37;PC Code Page=1252"; + break; + } + } + } + + //You can of course also add any constants or statics in this class as well, not initialized from + //repository but just initialized here in code. + + /// + /// Local Settings Not From Config Database Repository. Note that any of these could optionally be moved into the + /// config repository instead of being initialized in code. + /// + /// + } +} \ No newline at end of file Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/stocktrader.snk URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/stocktrader.snk?rev=728078&view=auto ============================================================================== Binary file - no diff available. Propchange: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/OrderProcessorServiceConfigurationSettings/stocktrader.snk ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/ServiceConfigurationSettings/Properties/AssemblyInfo.cs URL: http://svn.apache.org/viewvc/incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/ServiceConfigurationSettings/Properties/AssemblyInfo.cs?rev=728078&view=auto ============================================================================== --- incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/ServiceConfigurationSettings/Properties/AssemblyInfo.cs (added) +++ incubator/stonehenge/contrib/stocktrader/dotnet/StockTrader/StockTraderWebAppSolution/ServiceConfigurationSettings/Properties/AssemblyInfo.cs Fri Dec 19 09:43:28 2008 @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Trade.StockTraderWebApplicationSettings")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct(".NET StockTrader")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d0c96e47-39d3-4231-af05-4cd2ce21b106")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2.0.2.0")] +[assembly: AssemblyFileVersion("2.0.2.0")]