
org.apache.geronimo.samples.daytrader.TradeAction Maven / Gradle / Ivy
The newest version!
/**
* 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.
*/
package org.apache.geronimo.samples.daytrader;
import java.math.BigDecimal;
import java.util.Collection;
import javax.naming.InitialContext;
import org.apache.geronimo.samples.daytrader.direct.TradeDirect;
import org.apache.geronimo.samples.daytrader.ejb3.TradeSLSBRemote;
import org.apache.geronimo.samples.daytrader.ejb3.DirectSLSBRemote;
import org.apache.geronimo.samples.daytrader.util.FinancialUtils;
import org.apache.geronimo.samples.daytrader.util.Log;
/**
* The TradeAction class provides the generic client side access to each of the
* Trade brokerage user operations. These include login, logout, buy, sell,
* getQuote, etc. The TradeAction class does not handle user interface
* processing and should be used by a class that is UI specific. For example,
* {trade_client.TradeServletAction}manages a web interface to Trade,
* making calls to TradeAction methods to actually performance each operation.
*/
public class TradeAction implements TradeServices {
// This lock is used to serialize market summary operations.
private static final Integer marketSummaryLock = new Integer(0);
private static long nextMarketSummary = System.currentTimeMillis();
private static MarketSummaryDataBean cachedMSDB = MarketSummaryDataBean.getRandomInstance();
// make this static so the trade impl can be cached
// - ejb3 mode is the only thing that really uses this
// - can go back and update other modes to take advantage (ie. TradeDirect)
private static TradeServices trade = null;
public TradeAction() {
if (Log.doTrace())
Log.trace("TradeAction:TradeAction()");
createTrade();
}
public TradeAction(TradeServices trade) {
if (Log.doActionTrace())
Log.trace("TradeAction:TradeAction(trade)");
this.trade = trade;
}
private void createTrade() {
if (TradeConfig.runTimeMode == TradeConfig.EJB3) {
try {
if (!(trade instanceof TradeSLSBRemote)) {
TradeSLSBRemote tradeSLSB = null;
InitialContext context = new InitialContext();
try {
tradeSLSB = (TradeSLSBRemote) context.lookup("java:comp/env/ejb/TradeSLSBBean");
} catch (Exception ex) {
Log.error("TradeAction:createTrade - Lookup of TradeSLSBRemote failed!!!");
tradeSLSB = (TradeSLSBRemote) context.lookup("TradeSLSBBean");
}
trade = tradeSLSB;
}
}
catch (Exception e) {
Log.error("TradeAction:TradeAction() Creation of Trade EJB 3 failed\n" + e);
e.printStackTrace();
}
} else if (TradeConfig.runTimeMode == TradeConfig.SESSION3) {
try {
if (!(trade instanceof DirectSLSBRemote)) {
DirectSLSBRemote directSLSB = null;
InitialContext context = new InitialContext();
try {
directSLSB = (DirectSLSBRemote) context.lookup("java:comp/env/ejb/DirectSLSBBean");
} catch (Exception ex) {
Log.error("TradeAction:createTrade - Lookup of DirectSLSBRemote failed!!!");
directSLSB = (DirectSLSBRemote) context.lookup("DirectSLSBBean");
}
trade = directSLSB;
}
}
catch (Exception e) {
Log.error("TradeAction:TradeAction() Creation of Trade SESSION3 failed\n" + e);
e.printStackTrace();
}
}else if (TradeConfig.runTimeMode == TradeConfig.DIRECT) {
try {
trade = new TradeDirect();
}
catch (Exception e) {
Log.error("TradeAction:TradeAction() Creation of Trade Direct failed\n" + e);
}
}
}
/**
* Market Summary is inherently a heavy database operation. For servers that have a caching
* story this is a great place to cache data that is good for a period of time. In order to
* provide a flexible framework for this we allow the market summary operation to be
* invoked on every transaction, time delayed or never. This is configurable in the
* configuration panel.
*
* @return An instance of the market summary
*/
public MarketSummaryDataBean getMarketSummary() throws Exception {
if (Log.doActionTrace()) {
Log.trace("TradeAction:getMarketSummary()");
}
if (TradeConfig.getMarketSummaryInterval() == 0) return getMarketSummaryInternal();
if (TradeConfig.getMarketSummaryInterval() < 0) return cachedMSDB;
/**
* This is a little funky. If its time to fetch a new Market summary then we'll synchronize
* access to make sure only one requester does it. Others will merely return the old copy until
* the new MarketSummary has been executed.
*/
long currentTime = System.currentTimeMillis();
if (currentTime > nextMarketSummary) {
long oldNextMarketSummary = nextMarketSummary;
boolean fetch = false;
synchronized (marketSummaryLock) {
/**
* Is it still ahead or did we miss lose the race? If we lost then let's get out
* of here as the work has already been done.
*/
if (oldNextMarketSummary == nextMarketSummary) {
fetch = true;
nextMarketSummary += TradeConfig.getMarketSummaryInterval()*1000;
/**
* If the server has been idle for a while then its possible that nextMarketSummary
* could be way off. Rather than try and play catch up we'll simply get in sync with the
* current time + the interval.
*/
if (nextMarketSummary < currentTime) {
nextMarketSummary = currentTime + TradeConfig.getMarketSummaryInterval()*1000;
}
}
}
/**
* If we're the lucky one then let's update the MarketSummary
*/
if (fetch) {
cachedMSDB = getMarketSummaryInternal();
}
}
return cachedMSDB;
}
/**
* Compute and return a snapshot of the current market conditions This
* includes the TSIA - an index of the price of the top 100 Trade stock
* quotes The openTSIA ( the index at the open) The volume of shares traded,
* Top Stocks gain and loss
*
* @return A snapshot of the current market summary
*/
public MarketSummaryDataBean getMarketSummaryInternal() throws Exception {
if (Log.doActionTrace()) {
Log.trace("TradeAction:getMarketSummaryInternal()");
}
MarketSummaryDataBean marketSummaryData = null;
marketSummaryData = trade.getMarketSummary();
return marketSummaryData;
}
/**
* Purchase a stock and create a new holding for the given user. Given a
* stock symbol and quantity to purchase, retrieve the current quote price,
* debit the user's account balance, and add holdings to user's portfolio.
*
* @param userID the customer requesting the stock purchase
* @param symbol the symbol of the stock being purchased
* @param quantity the quantity of shares to purchase
* @return OrderDataBean providing the status of the newly created buy order
*/
public OrderDataBean buy(String userID, String symbol, double quantity, int orderProcessingMode) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:buy", userID, symbol, new Double(quantity), new Integer(orderProcessingMode));
OrderDataBean orderData;
orderData = trade.buy(userID, symbol, quantity, orderProcessingMode);
//after the purchase or sell of a stock, update the stocks volume and
// price
updateQuotePriceVolume(symbol, TradeConfig.getRandomPriceChangeFactor(), quantity);
return orderData;
}
/**
* Sell(SOAP 2.2 Wrapper converting int to Integer) a stock holding and
* removed the holding for the given user. Given a Holding, retrieve current
* quote, credit user's account, and reduce holdings in user's portfolio.
*
* @param userID the customer requesting the sell
* @param holdingID the users holding to be sold
* @return OrderDataBean providing the status of the newly created sell
* order
*/
public OrderDataBean sell(String userID, int holdingID, int orderProcessingMode) throws Exception {
return sell(userID, new Integer(holdingID), orderProcessingMode);
}
/**
* Sell a stock holding and removed the holding for the given user. Given a
* Holding, retrieve current quote, credit user's account, and reduce
* holdings in user's portfolio.
*
* @param userID the customer requesting the sell
* @param holdingID the users holding to be sold
* @return OrderDataBean providing the status of the newly created sell
* order
*/
public OrderDataBean sell(String userID, Integer holdingID, int orderProcessingMode) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:sell", userID, holdingID, new Integer(orderProcessingMode));
OrderDataBean orderData;
orderData = trade.sell(userID, holdingID, orderProcessingMode);
if (!(orderData.getOrderStatus().equalsIgnoreCase("cancelled")))
//after the purchase or sell of a stock, update the stocks volume
// and price
updateQuotePriceVolume(orderData.getSymbol(), TradeConfig.getRandomPriceChangeFactor(), orderData.getQuantity());
return orderData;
}
/**
* Queue the Order identified by orderID to be processed
*
* Orders are submitted through JMS to a Trading Broker and completed
* asynchronously. This method queues the order for processing
*
* The boolean twoPhase specifies to the server implementation whether or
* not the method is to participate in a global transaction
*
* @param orderID the Order being queued for processing
*/
public void queueOrder(Integer orderID, boolean twoPhase) {
throw new UnsupportedOperationException("TradeAction: queueOrder method not supported");
}
/**
* Complete the Order identefied by orderID Orders are submitted through JMS
* to a Trading agent and completed asynchronously. This method completes
* the order For a buy, the stock is purchased creating a holding and the
* users account is debited For a sell, the stock holding is removed and the
* users account is credited with the proceeds
*
* The boolean twoPhase specifies to the server implementation whether or
* not the method is to participate in a global transaction
*
* @param orderID the Order to complete
* @return OrderDataBean providing the status of the completed order
*/
public OrderDataBean completeOrder(Integer orderID, boolean twoPhase) {
throw new UnsupportedOperationException("TradeAction: completeOrder method not supported");
}
/**
* Cancel the Order identified by orderID
*
* Orders are submitted through JMS to a Trading Broker and completed
* asynchronously. This method queues the order for processing
*
* The boolean twoPhase specifies to the server implementation whether or
* not the method is to participate in a global transaction
*
* @param orderID the Order being queued for processing
*/
public void cancelOrder(Integer orderID, boolean twoPhase) {
throw new UnsupportedOperationException("TradeAction: cancelOrder method not supported");
}
public void orderCompleted(String userID, Integer orderID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:orderCompleted", userID, orderID);
if (Log.doTrace())
Log.trace("OrderCompleted", userID, orderID);
}
/**
* Get the collection of all orders for a given account
*
* @param userID the customer account to retrieve orders for
* @return Collection OrderDataBeans providing detailed order information
*/
public Collection getOrders(String userID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getOrders", userID);
Collection orderDataBeans;
orderDataBeans = trade.getOrders(userID);
return orderDataBeans;
}
/**
* Get the collection of completed orders for a given account that need to
* be alerted to the user
*
* @param userID the customer account to retrieve orders for
* @return Collection OrderDataBeans providing detailed order information
*/
public Collection getClosedOrders(String userID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getClosedOrders", userID);
Collection orderDataBeans;
orderDataBeans = trade.getClosedOrders(userID);
return orderDataBeans;
}
/**
* Given a market symbol, price, and details, create and return a new
* {@link QuoteDataBean}
*
* @param symbol the symbol of the stock
* @param price the current stock price
* @return a new QuoteDataBean or null if Quote could not be created
*/
public QuoteDataBean createQuote(String symbol, String companyName, BigDecimal price) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:createQuote", symbol, companyName, price);
QuoteDataBean quoteData;
quoteData = trade.createQuote(symbol, companyName, price);
return quoteData;
}
/**
* Return a collection of {@link QuoteDataBean}describing all current
* quotes
*
* @return the collection of QuoteDataBean
*/
public Collection getAllQuotes() throws Exception {
if (Log.doActionTrace()) {
Log.trace("TradeAction:getAllQuotes");
}
Collection quotes;
quotes = trade.getAllQuotes();
return quotes;
}
/**
* Return a {@link QuoteDataBean}describing a current quote for the given
* stock symbol
*
* @param symbol the stock symbol to retrieve the current Quote
* @return the QuoteDataBean
*/
public QuoteDataBean getQuote(String symbol) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getQuote", symbol);
if ((symbol == null) || (symbol.length() == 0) || (symbol.length() > 10)) {
if (Log.doActionTrace()) {
Log.trace("TradeAction:getQuote --- primitive workload");
}
return new QuoteDataBean("Invalid symbol", "", 0.0, FinancialUtils.ZERO, FinancialUtils.ZERO, FinancialUtils.ZERO, FinancialUtils.ZERO, 0.0);
}
QuoteDataBean quoteData;
quoteData = trade.getQuote(symbol);
return quoteData;
}
/**
* Update the stock quote price for the specified stock symbol
*
* @param symbol for stock quote to update
* @return the QuoteDataBean describing the stock
*/
/* avoid data collision with synch */
public QuoteDataBean updateQuotePriceVolume(String symbol, BigDecimal changeFactor, double sharesTraded) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:updateQuotePriceVolume", symbol, changeFactor, new Double(sharesTraded));
QuoteDataBean quoteData = null;
try {
quoteData = trade.updateQuotePriceVolume(symbol, changeFactor, sharesTraded);
}
catch (Exception e) {
Log.error("TradeAction:updateQuotePrice -- ", e);
}
return quoteData;
}
/**
* Return the portfolio of stock holdings for the specified customer as a
* collection of HoldingDataBeans
*
* @param userID the customer requesting the portfolio
* @return Collection of the users portfolio of stock holdings
*/
public Collection getHoldings(String userID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getHoldings", userID);
Collection holdingDataBeans;
holdingDataBeans = trade.getHoldings(userID);
return holdingDataBeans;
}
/**
* Return a specific user stock holding identifed by the holdingID
*
* @param holdingID the holdingID to return
* @return a HoldingDataBean describing the holding
*/
public HoldingDataBean getHolding(Integer holdingID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getHolding", holdingID);
HoldingDataBean holdingData;
holdingData = trade.getHolding(holdingID);
return holdingData;
}
/**
* Return an AccountDataBean object for userID describing the account
*
* @param userID the account userID to lookup
* @return User account data in AccountDataBean
*/
public AccountDataBean getAccountData(String userID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getAccountData", userID);
AccountDataBean accountData;
accountData = trade.getAccountData(userID);
return accountData;
}
/**
* Return an AccountProfileDataBean for userID providing the users profile
*
* @param userID the account userID to lookup
*/
public AccountProfileDataBean getAccountProfileData(String userID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:getAccountProfileData", userID);
AccountProfileDataBean accountProfileData;
accountProfileData = trade.getAccountProfileData(userID);
return accountProfileData;
}
/**
* Update userID's account profile information using the provided
* AccountProfileDataBean object
*
* @param accountProfileData account profile data in AccountProfileDataBean
*/
public AccountProfileDataBean updateAccountProfile(AccountProfileDataBean accountProfileData) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:updateAccountProfile", accountProfileData);
accountProfileData = trade.updateAccountProfile(accountProfileData);
return accountProfileData;
}
/**
* Attempt to authenticate and login a user with the given password
*
* @param userID the customer to login
* @param password the password entered by the customer for authentication
* @return User account data in AccountDataBean
*/
public AccountDataBean login(String userID, String password) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:login", userID, password);
AccountDataBean accountData;
accountData = trade.login(userID, password);
return accountData;
}
/**
* Logout the given user
*
* @param userID the customer to logout
*/
public void logout(String userID) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:logout", userID);
trade.logout(userID);
}
/**
* Register a new Trade customer. Create a new user profile, user registry
* entry, account with initial balance, and empty portfolio.
*
* @param userID the new customer to register
* @param password the customers password
* @param fullname the customers fullname
* @param address the customers street address
* @param email the customers email address
* @param creditCard the customers creditcard number
* @param openBalance the amount to charge to the customers credit to open the
* account and set the initial balance
* @return the userID if successful, null otherwise
*/
public AccountDataBean register(String userID, String password, String fullname, String address, String email, String creditCard, BigDecimal openBalance) throws Exception {
if (Log.doActionTrace())
Log.trace("TradeAction:register", userID, password, fullname, address, email, creditCard, openBalance);
AccountDataBean accountData;
accountData = trade.register(userID, password, fullname, address, email, creditCard, openBalance);
return accountData;
}
public AccountDataBean register(String userID, String password, String fullname, String address, String email, String creditCard, String openBalanceString) throws Exception {
BigDecimal openBalance = new BigDecimal(openBalanceString);
return register(userID, password, fullname, address, email, creditCard, openBalance);
}
/**
* Reset the TradeData by - removing all newly registered users by scenario
* servlet (i.e. users with userID's beginning with "ru:") * - removing all
* buy/sell order pairs - setting logoutCount = loginCount
*
* return statistics for this benchmark run
*/
public RunStatsDataBean resetTrade(boolean deleteAll) throws Exception {
RunStatsDataBean runStatsData;
runStatsData = trade.resetTrade(deleteAll);
return runStatsData;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy