/**
* Licensed to4the 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.aries.samples.ariestrader.web;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.aries.samples.ariestrader.api.TradeServices;
import org.apache.aries.samples.ariestrader.api.persistence.*;
import org.apache.aries.samples.ariestrader.util.*;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;
import java.math.BigDecimal;
/**
* TradeServletAction provides servlet specific client side access to each of
* the Trade brokerage user operations. These include login, logout, buy, sell,
* getQuote, etc. TradeServletAction manages a web interface to Trade handling
* HttpRequests/HttpResponse objects and forwarding results to the appropriate
* JSP page for the web interface. TradeServletAction invokes
* {@link TradeServices} methods to actually perform each
* trading operation.
*
*/
public class TradeServletAction {
private TradeServices tradeServices = null;
public TradeServletAction(TradeServices tradeServices) {
this.tradeServices = tradeServices;
}
/**
* Display User Profile information such as address, email, etc. for the
* given Trader Dispatch to the Trade Account JSP for display
*
* @param userID
* The User to display profile info
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @param results
* A short description of the results/success of this web request
* provided on the web page
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doAccount(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String results)
throws javax.servlet.ServletException, java.io.IOException {
try {
AccountDataBean accountData = tradeServices.getAccountData(userID);
AccountProfileDataBean accountProfileData = tradeServices
.getAccountProfileData(userID);
ArrayList orderDataBeans = (TradeConfig.getLongRun() ? new ArrayList() : (ArrayList) tradeServices.getOrders(userID));
req.setAttribute("accountData", accountData);
req.setAttribute("accountProfileData", accountProfileData);
req.setAttribute("orderDataBeans", orderDataBeans);
req.setAttribute("results", results);
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.ACCOUNT_PAGE));
} catch (java.lang.IllegalArgumentException e) { // this is a user
// error so I will
// forward them to another page rather than throw a 500
req.setAttribute("results", results
+ "could not find account for userID = " + userID);
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.HOME_PAGE));
// log the exception with an error level of 3 which means, handled
// exception but would invalidate a automation run
Log.error("TradeServletAction.doAccount(...)",
"illegal argument, information should be in exception string",
e);
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.doAccount(...)"
+ " exception user =" + userID, e);
}
}
/**
* Update User Profile information such as address, email, etc. for the
* given Trader Dispatch to the Trade Account JSP for display If any in put
* is incorrect revert back to the account page w/ an appropriate message
*
* @param userID
* The User to upddate profile info
* @param password
* The new User password
* @param cpassword
* Confirm password
* @param fullname
* The new User fullname info
* @param address
* The new User address info
* @param cc
* The new User credit card info
* @param email
* The new User email info
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doAccountUpdate(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String password,
String cpassword, String fullName, String address,
String creditcard, String email)
throws javax.servlet.ServletException, java.io.IOException {
String results = "";
// First verify input data
boolean doUpdate = true;
if (password.equals(cpassword) == false) {
results = "Update profile error: passwords do not match";
doUpdate = false;
} else if (password.length() <= 0 || fullName.length() <= 0
|| address.length() <= 0 || creditcard.length() <= 0
|| email.length() <= 0) {
results = "Update profile error: please fill in all profile information fields";
doUpdate = false;
}
try {
if (doUpdate) {
tradeServices.updateAccountProfile(userID, password, fullName, address, email, creditcard);
results = "Account profile update successful";
}
} catch (java.lang.IllegalArgumentException e) {
// this is a user error so I will forward them to another page rather than throw a 500
req.setAttribute("results",
results + "invalid argument, check userID is correct, and the database is populated" + userID);
Log.error(e,
"TradeServletAction.doAccount(...)",
"illegal argument, information should be in exception string",
"treating this as a user error and forwarding on to a new page");
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.doAccountUpdate(...)" + " exception user =" + userID, e);
}
doAccount(ctx, req, resp, userID, results);
}
/**
* Buy a new holding of shares for the given trader Dispatch to the Trade
* Portfolio JSP for display
*
* @param userID
* The User buying shares
* @param symbol
* The stock to purchase
* @param amount
* The quantity of shares to purchase
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doBuy(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String symbol,
String quantity) throws ServletException, IOException {
String results = "";
try {
OrderDataBean orderData = tradeServices.buy(userID, symbol, new Double(
quantity).doubleValue(), TradeConfig.orderProcessingMode);
req.setAttribute("orderData", orderData);
req.setAttribute("results", results);
} catch (java.lang.IllegalArgumentException e) { // this is a user
// error so I will
// forward them to another page rather than throw a 500
req.setAttribute("results", results + "illegal argument:");
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.HOME_PAGE));
// log the exception with an error level of 3 which means, handled
// exception but would invalidate a automation run
Log.error(e, "TradeServletAction.doBuy(...)",
"illegal argument. userID = " + userID, "symbol = "
+ symbol);
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.buy(...)"
+ " exception buying stock " + symbol + " for user "
+ userID, e);
}
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.ORDER_PAGE));
}
/**
* Create the Trade Home page with personalized information such as the
* traders account balance Dispatch to the Trade Home JSP for display
*
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @param results
* A short description of the results/success of this web request
* provided on the web page
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doHome(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String results)
throws javax.servlet.ServletException, java.io.IOException {
try {
AccountDataBean accountData = tradeServices.getAccountData(userID);
Collection holdingDataBeans = tradeServices.getHoldings(userID);
// Edge Caching:
// Getting the MarketSummary has been moved to the JSP
// MarketSummary.jsp. This makes the MarketSummary a
// standalone "fragment", and thus is a candidate for
// Edge caching.
// marketSummaryData = tradeServices.getMarketSummary();
req.setAttribute("accountData", accountData);
req.setAttribute("holdingDataBeans", holdingDataBeans);
// See Edge Caching above req.setAttribute("marketSummaryData", marketSummaryData);
req.setAttribute("results", results);
} catch (java.lang.IllegalArgumentException e) {
// this is a user error so I will forward them to another page rather than throw a 500
req.setAttribute("results", results + "check userID = " + userID + " and that the database is populated");
requestDispatch(ctx, req, resp, userID, TradeConfig.getPage(TradeConfig.HOME_PAGE));
// log the exception with an error level of 3 which means, handled exception but would invalidate a automation run
Log.error("TradeServletAction.doHome(...)"
+ "illegal argument, information should be in exception string"
+ "treating this as a user error and forwarding on to a new page",
e);
} catch (Exception e) {
throw new ServletException("TradeServletAction.doHome(...)" + " exception user =" + userID, e);
}
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.HOME_PAGE));
}
/**
* Login a Trade User. Dispatch to the Trade Home JSP for display
*
* @param userID
* The User to login
* @param passwd
* The password supplied by the trader used to authenticate
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @param results
* A short description of the results/success of this web request
* provided on the web page
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doLogin(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String passwd)
throws javax.servlet.ServletException, java.io.IOException {
String results = "";
try {
// Got a valid userID and passwd, attempt login
AccountDataBean accountData = tradeServices.login(userID, passwd);
if (accountData != null) {
HttpSession session = req.getSession(true);
session.setAttribute("uidBean", userID);
session.setAttribute("sessionCreationDate",
new java.util.Date());
results = "Ready to Trade";
doHome(ctx, req, resp, userID, results);
return;
} else {
req.setAttribute("results", results
+ "\nCould not find account for + " + userID);
// log the exception with an error level of 3 which means,
// handled exception but would invalidate a automation run
Log.log(
"TradeServletAction.doLogin(...)",
"Error finding account for user " + userID + "",
"user entered a bad username or the database is not populated");
}
} catch (java.lang.IllegalArgumentException e) { // this is a user
// error so I will
// forward them to another page rather than throw a 500
req.setAttribute("results", results + "illegal argument:"
+ e.getMessage());
// log the exception with an error level of 3 which means, handled
// exception but would invalidate a automation run
Log
.error(
e,
"TradeServletAction.doLogin(...)",
"illegal argument, information should be in exception string",
"treating this as a user error and forwarding on to a new page");
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.doLogin(...)"
+ "Exception logging in user " + userID + "with password"
+ passwd, e);
}
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.WELCOME_PAGE));
}
/**
* Logout a Trade User Dispatch to the Trade Welcome JSP for display
*
* @param userID
* The User to logout
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @param results
* A short description of the results/success of this web request
* provided on the web page
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doLogout(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID) throws ServletException,
IOException {
String results = "";
try {
tradeServices.logout(userID);
} catch (java.lang.IllegalArgumentException e) { // this is a user
// error so I will
// forward them to another page, at the end of the page.
req.setAttribute("results", results + "illegal argument:"
+ e.getMessage());
// log the exception with an error level of 3 which means, handled
// exception but would invalidate a automation run
Log
.error(
e,
"TradeServletAction.doLogout(...)",
"illegal argument, information should be in exception string",
"treating this as a user error and forwarding on to a new page");
} catch (Exception e) {
// log the exception and forward to a error page
Log.error(e, "TradeServletAction.doLogout(...):",
"Error logging out" + userID, "fowarding to an error page");
// set the status_code to 500
throw new ServletException("TradeServletAction.doLogout(...)"
+ "exception logging out user " + userID, e);
}
HttpSession session = req.getSession();
if (session != null) {
session.invalidate();
}
Object o = req.getAttribute("TSS-RecreateSessionInLogout");
if (o != null && ((Boolean) o).equals(Boolean.TRUE)) {
// Recreate Session object before writing output to the response
// Once the response headers are written back to the client the
// opportunity
// to create a new session in this request may be lost
// This is to handle only the TradeScenarioServlet case
session = req.getSession(true);
}
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.WELCOME_PAGE));
}
/**
* Retrieve the current portfolio of stock holdings for the given trader
* Dispatch to the Trade Portfolio JSP for display
*
* @param userID
* The User requesting to view their portfolio
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @param results
* A short description of the results/success of this web request
* provided on the web page
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doPortfolio(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String results)
throws ServletException, IOException {
try {
// Get the holdings for this user
Collection quoteDataBeans = new ArrayList();
Collection holdingDataBeans = tradeServices.getHoldings(userID);
// Walk through the collection of user
// holdings and creating a list of quotes
if (holdingDataBeans.size() > 0) {
Iterator it = holdingDataBeans.iterator();
while (it.hasNext()) {
HoldingDataBean holdingData = (HoldingDataBean) it.next();
QuoteDataBean quoteData = tradeServices.getQuote(holdingData
.getQuoteID());
quoteDataBeans.add(quoteData);
}
} else {
results = results + ". Your portfolio is empty.";
}
req.setAttribute("results", results);
req.setAttribute("holdingDataBeans", holdingDataBeans);
req.setAttribute("quoteDataBeans", quoteDataBeans);
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.PORTFOLIO_PAGE));
} catch (java.lang.IllegalArgumentException e) { // this is a user
// error so I will
// forward them to another page rather than throw a 500
req.setAttribute("results", results + "illegal argument:"
+ e.getMessage());
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.PORTFOLIO_PAGE));
// log the exception with an error level of 3 which means, handled
// exception but would invalidate a automation run
Log.error(
e,
"TradeServletAction.doPortfolio(...)",
"illegal argument, information should be in exception string",
"user error");
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.doPortfolio(...)"
+ " exception user =" + userID, e);
}
}
/**
* Retrieve the current Quote for the given stock symbol Dispatch to the
* Trade Quote JSP for display
*
* @param userID
* The stock symbol used to get the current quote
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doQuotes(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String symbols)
throws ServletException, IOException {
String results = "";
// Edge Caching:
// Getting Quotes has been moved to the JSP
// Quote.jsp. This makes each Quote a
// standalone "fragment", and thus is a candidate for
// Edge caching.
//
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.QUOTE_PAGE));
}
/**
* Register a new trader given the provided user Profile information such as
* address, email, etc. Dispatch to the Trade Home JSP for display
*
* @param userID
* The User to create
* @param passwd
* The User password
* @param fullname
* The new User fullname info
* @param ccn
* The new User credit card info
* @param money
* The new User opening account balance
* @param address
* The new User address info
* @param email
* The new User email info
* @return The userID of the new trader
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doRegister(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String passwd,
String cpasswd, String fullname, String ccn,
String openBalanceString, String email, String address)
throws ServletException, IOException {
String results = "";
try {
// Validate user passwords match and are atleast 1 char in length
if ((passwd.equals(cpasswd)) && (passwd.length() >= 1)) {
AccountDataBean accountData = tradeServices.register(userID, passwd,
fullname, address, email, ccn, new BigDecimal(
openBalanceString));
if (accountData == null) {
results = "Registration operation failed;";
System.out.println(results);
req.setAttribute("results", results);
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.REGISTER_PAGE));
} else {
doLogin(ctx, req, resp, userID, passwd);
results = "Registration operation succeeded; Account "
+ accountData.getAccountID() + " has been created.";
req.setAttribute("results", results);
}
} else {
// Password validation failed
results = "Registration operation failed, your passwords did not match";
System.out.println(results);
req.setAttribute("results", results);
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.REGISTER_PAGE));
}
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.doRegister(...)"
+ " exception user =" + userID, e);
}
}
/**
* Sell a current holding of stock shares for the given trader. Dispatch to
* the Trade Portfolio JSP for display
*
* @param userID
* The User buying shares
* @param symbol
* The stock to sell
* @param indx
* The unique index identifying the users holding to sell
* @param ctx
* the servlet context
* @param req
* the HttpRequest object
* @param resp
* the HttpResponse object
* @exception javax.servlet.ServletException
* If a servlet specific exception is encountered
* @exception javax.io.IOException
* If an exception occurs while writing results back to the
* user
*
*/
void doSell(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, Integer holdingID)
throws ServletException, IOException {
String results = "";
try {
OrderDataBean orderData = tradeServices.sell(userID, holdingID,
TradeConfig.orderProcessingMode);
req.setAttribute("orderData", orderData);
req.setAttribute("results", results);
} catch (java.lang.IllegalArgumentException e) { // this is a user
// error so I will
// just log the exception and then later on I will redisplay the
// portfolio page
// because this is just a user exception
Log.error(e,
"TradeServletAction.doSell(...)",
"illegal argument, information should be in exception string",
"user error");
} catch (Exception e) {
// log the exception with error page
throw new ServletException("TradeServletAction.doSell(...)"
+ " exception selling holding " + holdingID + " for user ="
+ userID, e);
}
requestDispatch(ctx, req, resp, userID, TradeConfig
.getPage(TradeConfig.ORDER_PAGE));
}
void doWelcome(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String status) throws ServletException,
IOException {
req.setAttribute("results", status);
requestDispatch(ctx, req, resp, null, TradeConfig
.getPage(TradeConfig.WELCOME_PAGE));
}
private void requestDispatch(ServletContext ctx, HttpServletRequest req,
HttpServletResponse resp, String userID, String page)
throws ServletException, IOException {
ctx.getRequestDispatcher(page).include(req, resp);
}
}