// // 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 Service Configuration V2.0 for Design Considerations for Service-Oriented Applications based on Windows Communication Foundation. Created with Microsoft .NET Framework 3.5 and Microsoft Visual Studio. Copyright 2008, Microsoft Corporation. //====================================================================================================== // 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.ServiceModel; using System.ServiceModel.Channels; using System.Runtime.Serialization; using System.Collections.Generic; using System.Threading; using System.Configuration; using Trade.BusinessServiceContract; using Trade.BusinessServiceDataContract; using Trade.StockTraderWebApplicationSettings; using Trade.Client; using Trade.Utility; using Trade.ConfigClient; using Trade.ConfigServiceContract; using Trade.ConfigServiceDataContract; namespace Trade.BusinessServiceClient { /// /// This is the WCF client class for the remote Business Services, connecting to any Web Service platform /// via WCF (.NET, J2EE etc.) that implements ITradeServices. 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. /// [System.Runtime.Serialization.KnownType(typeof(AccountDataModel))] public class BusinessServiceClient : ITradeServices { public Client.Client bslclient; public BusinessServiceClient() { //Clears the cache of the client so that changes in the database configuration can //be recognized without restarts Initialize(); //Using the database configuration system - this BusinessServiceClient is created based on the CLIENTTOBS //Configuration Settings specified in the database i.e. the row containing DOTNET_CLIENT var configClient = new ConfigServiceClient(); var clientRequest = new ClientConfigRequest(); clientRequest.ClientName = Settings.CLIENT_LABEL; var clientConfig = configClient.GetClientConfig(clientRequest); //In case the client cannot be properly configured from the database, look up the default ACCESSMODE from the //App.config file if (clientConfig == null) { throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_BAD_CONFIG); } //If configuration information was properly received from the database then choose the appropriate business //service based on the info in the CLIENTTOBS table i.e. the row with DOTNET_CLIENT try { if (ConfigurationManager.AppSettings.Get(clientConfig.BSName) == null) throw new Exception(string.Format("The WCF endpoint for {0} was not defined in the configuration", clientConfig.BSName)); bslclient = new Client.Client(ConfigurationManager.AppSettings.Get(clientConfig.BSName), clientConfig.BS, Settings.BSL_USERID, Settings.BSL_PASSWORD, true); } catch { throw new Exception(string.Format(StockTraderUtility.EXCEPTION_MESSAGE_BAD_CONFIG, clientRequest.ClientName)); } } public ITradeServices Channel { get { return bslclient.Channel; } set { bslclient.Channel = value; } } public void emptyMethodAction() { try { this.Channel.emptyMethodAction(); } catch { this.Channel = null; throw; } } /// /// Logs user in/authenticates against StockTrader database. /// /// User id to authenticate. /// Password for authentication public AccountDataModel login(string userID, string password) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.login(userID, password); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getOrders(userID); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getAccountData(userID); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getAccountProfileData(userID); } catch { this.Channel = null; throw; } } /// /// Updates account profile data for a user. /// /// Profile data model class with updated info. public AccountProfileDataModel updateAccountProfile(AccountProfileDataModel profileData) { try { return this.Channel.updateAccountProfile(profileData); } catch { this.Channel = null; throw; } } /// /// Logs a user out--updates logout count. /// /// User id to logout. public void logout(string userID) { try { if (userID == null) userID = GetDefaultUserId(); this.Channel.logout(userID); } catch { this.Channel = null; throw; } return; } /// /// Performs a stock buy operation. /// /// User id to create/submit order for. /// Stock symbol to buy. /// Shares to buy public OrderDataModel buy(string userID, string symbol, double quantity, int orderProcessingMode) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.buy(userID, symbol, quantity, orderProcessingMode); } catch { this.Channel = null; throw; } } /// /// Performs a holding sell operation. /// /// User id to create/submit order for. /// Holding id to sell off. /// Shares to sell. public OrderDataModel sell(string userID, int holdingID, int orderProcessingMode) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.sell(userID, holdingID, orderProcessingMode); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getHoldings(userID); } catch { this.Channel = null; throw; } } /// /// 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) { try { return this.Channel.register(userID, password, fullname, address, email, creditcard, openBalance); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getClosedOrders(userID); } catch { this.Channel = null; throw; } } /// /// 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() { try { return this.Channel.getMarketSummary(); } catch { this.Channel = null; throw; } } /// /// Gets a single quote based on symbol. /// /// Symbol to get data for. public QuoteDataModel getQuote(string symbol) { try { return this.Channel.getQuote(symbol); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getHolding(userID, holdingID); } catch { this.Channel = null; throw; } } /// /// 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) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.getTopOrders(userID); } catch { this.Channel = null; throw; } } /// /// Allows user to sell part of a holding vs. all. Not implemented by Trade 6.1 on WebSphere. /// /// User id to submit sell for. /// Holding id to sell. /// Number of shares to sell. public OrderDataModel sellEnhanced(string userID, int holdingID, double quantity) { try { if (userID == null) userID = GetDefaultUserId(); return this.Channel.sellEnhanced(userID, holdingID, quantity); } catch { this.Channel = null; throw; } } /// /// Simple online check method. /// public void isOnline() { try { this.Channel.isOnline(); return; } catch { this.Channel = null; throw; } } /// /// A Static method that clears the cache of the Client Service /// public static void Initialize() { Client.Client.ClearCache(); } /// /// TODO: Hack for metro /// /// private string GetDefaultUserId() { return Settings.BSL_USERID; } } }