You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by dw...@apache.org on 2010/10/20 23:20:25 UTC
svn commit: r1025762 - in /openjpa/trunk/openjpa-integration/daytrader: ./
src/test/java/org/apache/openjpa/integration/daytrader/
Author: dwoods
Date: Wed Oct 20 21:20:23 2010
New Revision: 1025762
URL: http://svn.apache.org/viewvc?rev=1025762&view=rev
Log:
OPENJPA-1848 Update openjpa-integration-daytrader to perform user tasks
Added:
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeAction.java (with props)
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeScenario.java (with props)
Modified:
openjpa/trunk/openjpa-integration/daytrader/pom.xml
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/OrderDataBean.java
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TestDaytrader.java
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeBuildDB.java
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeConfig.java
openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeJPADirect.java
Modified: openjpa/trunk/openjpa-integration/daytrader/pom.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/pom.xml?rev=1025762&r1=1025761&r2=1025762&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/pom.xml (original)
+++ openjpa/trunk/openjpa-integration/daytrader/pom.xml Wed Oct 20 21:20:23 2010
@@ -47,7 +47,7 @@
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
- <artifactId>openjpa</artifactId>
+ <artifactId>openjpa-persistence-jdbc</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Maybe one day we can used published artifacts for this...
Modified: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/OrderDataBean.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/OrderDataBean.java?rev=1025762&r1=1025761&r2=1025762&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/OrderDataBean.java (original)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/OrderDataBean.java Wed Oct 20 21:20:23 2010
@@ -30,6 +30,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
@@ -106,10 +107,10 @@ public class OrderDataBean implements Se
private QuoteDataBean quote;
// Cause sell operation failed, see JIRA DAYTRADER-63 for details.
- //@OneToOne(fetch=FetchType.LAZY)
- //@JoinColumn(name = "HOLDING_HOLDINGID")
+ @OneToOne(fetch=FetchType.LAZY)
+ @JoinColumn(name = "HOLDING_HOLDINGID")
// Cause sell operation failed, see JIRA DAYTRADER-63 for details.
- @Transient
+ //@Transient
private HoldingDataBean holding;
// @Version
Modified: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TestDaytrader.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TestDaytrader.java?rev=1025762&r1=1025761&r2=1025762&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TestDaytrader.java (original)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TestDaytrader.java Wed Oct 20 21:20:23 2010
@@ -20,6 +20,8 @@ package org.apache.openjpa.integration.d
import java.math.BigDecimal;
import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.Query;
@@ -33,22 +35,25 @@ import javax.persistence.Query;
// import org.apache.geronimo.samples.daytrader.util.TradeConfig;
// import org.apache.geronimo.samples.daytrader.web.TradeBuildDB;
+import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
-import org.apache.openjpa.persistence.OpenJPAPersistence;
-import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase;
+//import org.apache.openjpa.persistence.test.SingleEMFTestCase;
/**
- * Uses Daytrader to stress test OpenJPA.
+ * Uses a modified version of Apache Geronimo Daytrader to stress test OpenJPA.
*
* @version $Rev$ $Date$
*/
-public class TestDaytrader extends SingleEMFTestCase {
-
+public class TestDaytrader extends AbstractPersistenceTestCase {
+ private static final int TEST_USERS = 50;
OpenJPAEntityManagerFactorySPI emf = null;
- //private TradeJPADirect trade = null;
+ Log log = null;
+ private TradeAction trade = null;
@Override
public void setUp() {
+ /*
super.setUp(DROP_TABLES, AccountDataBean.class,
AccountProfileDataBean.class, HoldingDataBean.class,
OrderDataBean.class, QuoteDataBean.class);
@@ -57,374 +62,51 @@ public class TestDaytrader extends Singl
"daytrader", "persistence.xml");
assertNotNull(emf);
}
- //trade = new TradeJPADirect((EntityManagerFactory)emf);
+ */
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("openjpa.DynamicEnhancementAgent", "false");
+ map.put("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true,"
+ + "SchemaAction='add,deleteTableContents')");
+ emf = createNamedEMF("daytrader", map);
+ assertNotNull(emf);
+ log = emf.getConfiguration().getLog("test");
+ TradeConfig.setRunTimeMode(TradeConfig.JPA);
+ TradeConfig.setLog(log);
+ trade = new TradeAction(emf.getConfiguration().getLog("test"), emf);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ trade = null;
+ log = null;
+ closeEMF(emf);
+ emf = null;
+ super.tearDown();
}
/**
* Scenario being tested:
+ * - Creates 1000 quotes
+ * - Creates 500 user accounts w/ 10 holdings each
+ * -
* @throws Exception
*
*/
- public void newtestTradeBuildDB() throws Exception {
- getLog().info("testTradeBuildDB() started");
- assertNotNull(emf);
- TradeBuildDB tradeDB = new TradeBuildDB(getLog(), emf);
- getLog().info("testTradeBuildDB() completed");
- }
-
- public void testTradeBuildDB() {
- getLog().info("testTradeBuildDB() started");
- getLog().info("testTradeBuildDB() createQuotes(" + TradeConfig.getMAX_QUOTES() + ")");
- createQuotes(TradeConfig.getMAX_QUOTES());
- getLog().info("testTradeBuildDB() createAccounts(" + TradeConfig.getMAX_USERS() + ")");
- createAccounts(TradeConfig.getMAX_USERS()); // with 10 holdings each
- getLog().info("testTradeBuildDB() completed");
- }
-
- // from TradeBuildDB.TradeBuildDB()
- private void createQuotes(int num) {
- int errorCount = 0;
- String symbol, companyName;
- TradeConfig.setMAX_QUOTES(num);
- for (int i = 0; i < num; i++) {
- symbol = "s:" + i;
- companyName = "S" + i + " Incorporated";
- try {
- QuoteDataBean quoteData = createQuote(symbol, companyName,
- new java.math.BigDecimal(TradeConfig.rndPrice()));
- } catch (Exception e) {
- if (errorCount++ >= 10) {
- getLog().error("createQuotes - aborting after 10 create quote errors", e);
- throw new RuntimeException(e);
- }
- }
- }
-
- }
-
- // from TradeJPADirect.createQuote()
- private QuoteDataBean createQuote(String symbol, String companyName, BigDecimal price) {
- EntityManager entityManager = emf.createEntityManager();
- QuoteDataBean quote = new QuoteDataBean(symbol, companyName, 0, price, price, price, price, 0);
- try {
- entityManager.getTransaction().begin();
- entityManager.persist(quote);
- entityManager.getTransaction().commit();
- }
- catch (Exception e) {
- getLog().error("createQuote - rollback - exception creating Quote", e);
- entityManager.getTransaction().rollback();
- throw new RuntimeException(e);
- } finally {
- entityManager.close();
- }
- if (getLog().isTraceEnabled())
- getLog().trace("createQuote-->" + quote);
- return quote;
- }
-
- // from TradeBuildDB.TradeBuildDB()
- private void createAccounts(int num) {
- TradeConfig.setMAX_USERS(num);
- for (int i = 0; i < num; i++) {
+ public void testTrade() throws Exception {
+ log.info("TestDaytrader.testTrade() started");
+ // setup quotes, accounts and holdings in DB
+ TradeBuildDB tradeDB = new TradeBuildDB(log, trade);
+ tradeDB.setup(TradeConfig.getMAX_QUOTES(), TradeConfig.getMAX_USERS());
+ // perform some operations per user
+ TradeScenario scenario = new TradeScenario(trade);
+ log.info("TestDaytrader.testTrade() calling TradeScenario.performUserTasks(" + TEST_USERS + ")");
+ for (int i = 0; i < TEST_USERS; i++) {
String userID = "uid:" + i;
- String fullname = TradeConfig.rndFullName();
- String email = TradeConfig.rndEmail(userID);
- String address = TradeConfig.rndAddress();
- String creditcard = TradeConfig.rndCreditCard();
- double initialBalance = (double) (TradeConfig.rndInt(100000)) + 200000;
- if (i == 0) {
- initialBalance = 1000000; // uid:0 starts with a cool million.
- }
-
- AccountDataBean accountData = register(userID, "xxx", fullname, address,
- email, creditcard, new BigDecimal(initialBalance));
-
- String results, symbol;
- if (accountData != null) {
- // 0-MAX_HOLDING (inclusive), avg holdings per user = (MAX-0)/2
- // int holdings = TradeConfig.rndInt(TradeConfig.getMAX_HOLDINGS() + 1);
- int holdings = TradeConfig.getMAX_HOLDINGS();
- double quantity = 0;
- OrderDataBean orderData;
- for (int j = 0; j < holdings; j++) {
- symbol = TradeConfig.rndSymbol();
- quantity = TradeConfig.rndQuantity();
- orderData = buy(userID, symbol, quantity, TradeConfig.orderProcessingMode);
- }
- if (getLog().isTraceEnabled())
- getLog().trace("createAccounts - created " + holdings + " for userID=" + userID);
- } else {
- throw new RuntimeException("createAccounts - userID=" + userID + " already registered.");
- }
- }
- }
-
- // from TradeJPADirect.register()
- private AccountDataBean register(String userID, String password, String fullname,
- String address, String email, String creditcard, BigDecimal openBalance) {
- AccountDataBean account = null;
- AccountProfileDataBean profile = null;
- EntityManager entityManager = emf.createEntityManager();
-
- // assume that profile with the desired userID doeesn't already exist
- profile = new AccountProfileDataBean(userID, password, fullname, address, email, creditcard);
- account = new AccountDataBean(0, 0, null, new Timestamp(System.currentTimeMillis()), openBalance, openBalance, userID);
- profile.setAccount(account);
- account.setProfile(profile);
- try {
- entityManager.getTransaction().begin();
- entityManager.persist(profile);
- entityManager.persist(account);
- entityManager.getTransaction().commit();
- } catch (Exception e) {
- getLog().error("createQuote - rollback - exception creating Quote", e);
- entityManager.getTransaction().rollback();
- throw new RuntimeException(e);
- } finally {
- entityManager.close();
- }
- if (getLog().isTraceEnabled())
- getLog().trace("register-->" + account);
- return account;
- }
-
- private OrderDataBean buy(String userID, String symbol, double quantity, int orderProcessingMode) {
- OrderDataBean order = null;
- BigDecimal total;
- EntityManager entityManager = emf.createEntityManager();
- assertNotNull(entityManager);
-
- try {
- if (getLog().isTraceEnabled())
- getLog().trace("buy-->userID=" + userID);
-
- entityManager.getTransaction().begin();
-
- AccountProfileDataBean profile = entityManager.find(AccountProfileDataBean.class, userID);
- assertNotNull(profile);
- AccountDataBean account = profile.getAccount();
- assertNotNull(account);
-
- QuoteDataBean quote = entityManager.find(QuoteDataBean.class, symbol);
- assertNotNull(quote);
-
- HoldingDataBean holding = null; // The holding will be created by this buy order
-
- order = createOrder(account, quote, holding, "buy", quantity, entityManager);
- assertNotNull(order);
-
- // order = createOrder(account, quote, holding, "buy", quantity);
- // UPDATE - account should be credited during completeOrder
-
- BigDecimal price = quote.getPrice();
- BigDecimal orderFee = order.getOrderFee();
- BigDecimal balance = account.getBalance();
- total = (new BigDecimal(quantity).multiply(price)).add(orderFee);
- account.setBalance(balance.subtract(total));
-
- // commit the transaction before calling completeOrder
- entityManager.getTransaction().commit();
-
- // if (orderProcessingMode == TradeConfig.SYNCH)
- completeOrder(order.getOrderID(), false);
- } catch (Exception e) {
- getLog().error("buy(" + userID + "," + symbol + "," + quantity + ") --> failed", e);
- // On exception - cancel the order
- // TODO figure out how to do this with JPA
- if (order != null)
- order.cancel();
-
- entityManager.getTransaction().rollback();
- entityManager.close();
- entityManager = null;
-
- // throw new EJBException(e);
- throw new RuntimeException(e);
- }
- if (entityManager != null) {
- entityManager.close();
- entityManager = null;
- }
-
- // after the purchase or sell of a stock, update the stocks volume and price
- updateQuotePriceVolume(symbol, TradeConfig.getRandomPriceChangeFactor(), quantity);
-
- return order;
- }
-
- private OrderDataBean createOrder(AccountDataBean account,
- QuoteDataBean quote, HoldingDataBean holding, String orderType,
- double quantity, EntityManager entityManager) {
- OrderDataBean order;
- if (getLog().isTraceEnabled())
- getLog().trace("createOrder(orderID=" + " account="
- + ((account == null) ? null : account.getAccountID())
- + " quote=" + ((quote == null) ? null : quote.getSymbol())
- + " orderType=" + orderType + " quantity=" + quantity);
- try {
- order = new OrderDataBean(orderType,
- "open",
- new Timestamp(System.currentTimeMillis()),
- null,
- quantity,
- // quote.getPrice().setScale(FinancialUtils.SCALE, FinancialUtils.ROUND),
- quote.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP),
- TradeConfig.getOrderFee(orderType),
- account,
- quote,
- holding);
- entityManager.persist(order);
- } catch (Exception e) {
- getLog().error("createOrder - failed to create Order", e);
- throw new RuntimeException("createOrder - failed to create Order", e);
- }
- return order;
- }
-
- private OrderDataBean completeOrder(Integer orderID, boolean twoPhase) throws Exception {
- EntityManager entityManager = emf.createEntityManager();
- OrderDataBean order = null;
-
- if (getLog().isTraceEnabled())
- getLog().trace("completeOrder - orderID=" + orderID + " twoPhase=" + twoPhase);
-
- order = entityManager.find(OrderDataBean.class, orderID);
- assertNotNull(order);
- order.getQuote();
- if (order == null) {
- getLog().error("completeOrder - Unable to find Order " + orderID + " FBPK returned " + order);
- return null;
- }
- if (order.isCompleted()) {
- throw new RuntimeException("completeOrder - attempt to complete Order that is already completed\n" + order);
- }
- AccountDataBean account = order.getAccount();
- assertNotNull(account);
- QuoteDataBean quote = order.getQuote();
- assertNotNull(quote);
- HoldingDataBean holding = order.getHolding();
- BigDecimal price = order.getPrice();
- double quantity = order.getQuantity();
-
- String userID = account.getProfile().getUserID();
- assertNotNull(userID);
-
- if (getLog().isTraceEnabled())
- getLog().trace("completeOrder--> Completing Order "
- + order.getOrderID() + "\n\t Order info: " + order
- + "\n\t Account info: " + account + "\n\t Quote info: "
- + quote + "\n\t Holding info: " + holding);
-
- HoldingDataBean newHolding = null;
- if (order.isBuy()) {
- newHolding = createHolding(account, quote, quantity, price, entityManager);
- assertNotNull(newHolding);
- }
- try {
- entityManager.getTransaction().begin();
- if (newHolding != null) {
- order.setHolding(newHolding);
- }
- if (order.isSell()) {
- if (holding == null) {
- getLog().error("completeOrder - error " + order.getOrderID() + " holding already sold");
- order.cancel();
- entityManager.getTransaction().commit();
- return order;
- }
- else {
- entityManager.remove(holding);
- order.setHolding(null);
- }
+ if (scenario.performUserTasks(userID) == false) {
+ fail("TestDaytrader.testTrade() call to TradeScenario.performUserTask(" + userID + ") failed");
}
- order.setOrderStatus("closed");
- order.setCompletionDate(new java.sql.Timestamp(System.currentTimeMillis()));
- if (getLog().isTraceEnabled())
- getLog().trace("completeOrder--> Completed Order "
- + order.getOrderID() + "\n\t Order info: " + order
- + "\n\t Account info: " + account + "\n\t Quote info: "
- + quote + "\n\t Holding info: " + holding);
- entityManager.getTransaction().commit();
- }
- catch (Exception e) {
- getLog().error(e);
- entityManager.getTransaction().rollback();
- entityManager.close();
- entityManager = null;
- }
- if (entityManager != null) {
- entityManager.close();
- entityManager = null;
- }
- return order;
- }
-
- private HoldingDataBean createHolding(AccountDataBean account,
- QuoteDataBean quote, double quantity, BigDecimal purchasePrice,
- EntityManager entityManager) throws Exception {
-
- HoldingDataBean newHolding = new HoldingDataBean(quantity,
- purchasePrice, new Timestamp(System.currentTimeMillis()),
- account, quote);
- assertNotNull(newHolding);
- try {
- entityManager.getTransaction().begin();
- entityManager.persist(newHolding);
- entityManager.getTransaction().commit();
- } catch (Exception e) {
- entityManager.getTransaction().rollback();
}
- return newHolding;
- }
-
- public QuoteDataBean updateQuotePriceVolume(String symbol, BigDecimal changeFactor, double sharesTraded) {
- if (!TradeConfig.getUpdateQuotePrices())
- return new QuoteDataBean();
- if (getLog().isTraceEnabled())
- getLog().trace("updateQuote - symbol=" + symbol + " changeFactor=" + changeFactor);
-
- EntityManager entityManager = emf.createEntityManager();
- QuoteDataBean quote = null;
- if (TradeConfig.jpaLayer == TradeConfig.HIBERNATE) {
- quote = entityManager.find(QuoteDataBean.class, symbol);
- } else if (TradeConfig.jpaLayer == TradeConfig.OPENJPA) {
- Query q = entityManager.createNamedQuery("quoteejb.quoteForUpdate");
- q.setParameter(1, symbol);
- quote = (QuoteDataBean) q.getSingleResult();
- }
- BigDecimal oldPrice = quote.getPrice();
- if (quote.getPrice().equals(TradeConfig.PENNY_STOCK_PRICE)) {
- changeFactor = TradeConfig.PENNY_STOCK_RECOVERY_MIRACLE_MULTIPLIER;
- }
- BigDecimal newPrice = changeFactor.multiply(oldPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
-
- try {
- quote.setPrice(newPrice);
- quote.setVolume(quote.getVolume() + sharesTraded);
- quote.setChange((newPrice.subtract(quote.getOpen()).doubleValue()));
-
- entityManager.getTransaction().begin();
- entityManager.merge(quote);
- entityManager.getTransaction().commit();
- } catch (Exception e) {
- entityManager.getTransaction().rollback();
- } finally {
- if (entityManager != null) {
- entityManager.close();
- entityManager = null;
- }
- }
- this.publishQuotePriceChange(quote, oldPrice, changeFactor, sharesTraded);
- return quote;
- }
-
- private void publishQuotePriceChange(QuoteDataBean quote, BigDecimal oldPrice,
- BigDecimal changeFactor, double sharesTraded) {
- if (!TradeConfig.getPublishQuotePriceChange())
- return;
- getLog().error("publishQuotePriceChange - is not implemented for this runtime mode");
- throw new UnsupportedOperationException("publishQuotePriceChange - is not implemented for this runtime mode");
+ log.info("TestDaytrader.testTrade() completed");
}
}
Added: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeAction.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeAction.java?rev=1025762&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeAction.java (added)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeAction.java Wed Oct 20 21:20:23 2010
@@ -0,0 +1,459 @@
+/**
+ * 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.openjpa.integration.daytrader;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.math.BigDecimal;
+
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.openjpa.lib.log.Log;
+
+/**
+ * OpenJPA created TradeAction, which was adapted from TradeServletAction.
+ * 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 TradeAction} methods to actually perform each trading operation.
+ *
+ */
+public class TradeAction extends TradeJPADirect {
+
+ public TradeAction(Log log, EntityManagerFactory emf) {
+ super(log, emf);
+ }
+
+ /**
+ * Display User Profile information such as address, email, etc. for the
+ * given Trader Dispatch to the Trade Account JSP for display
+ *
+ */
+ void doAccount(StringBuilder sb, String userID, String results)
+ throws RuntimeException, java.io.IOException {
+ setAttribute(sb, "Page", "Account");
+ try {
+ AccountDataBean accountData = getAccountData(userID);
+ AccountProfileDataBean accountProfileData = getAccountProfileData(userID);
+ ArrayList orderDataBeans = (TradeConfig.getLongRun() ?
+ new ArrayList() : (ArrayList)getOrders(userID));
+ setAttribute(sb, "accountData", accountData);
+ setAttribute(sb, "accountProfileData", accountProfileData);
+ setAttribute(sb, "orderDataBeans", orderDataBeans);
+ setAttribute(sb, "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
+ setAttribute(sb, "results", results + "could not find account for userID = " + userID);
+ // redirect to home page
+ // log the exception with an error level of 3 which means, handled
+ // exception but would invalidate a automation run
+ setAttribute(sb, "Exception", e);
+ } catch (Exception e) {
+ // log the exception with error page
+ sb.append("TradeServletAction.doAccount(...)" + " exception user =" + userID);
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("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
+ *
+ */
+ void doAccountUpdate(StringBuilder sb, String userID, String password,
+ String cpassword, String fullName, String address,
+ String creditcard, String email)
+ throws RuntimeException, java.io.IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Account Update");
+ // 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;
+ }
+ AccountProfileDataBean accountProfileData = new AccountProfileDataBean(
+ userID, password, fullName, address, email, creditcard);
+ try {
+ if (doUpdate) {
+ accountProfileData = updateAccountProfile(accountProfileData);
+ 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
+ setAttribute(sb, "results",
+ results + "invalid argument, check userID is correct, and the database is populated" + userID);
+ setAttribute(sb, "Exception", e);
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "results", "TradeServletAction.doAccountUpdate(...)" + " exception user =" + userID);
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("TradeServletAction.doAccountUpdate(...)" + " exception user =" + userID, e);
+ } finally {
+ sb.append(results);
+ }
+ doAccount(sb, userID, results);
+ }
+
+ /**
+ * Buy a new holding of shares for the given trader Dispatch to the Trade
+ * Portfolio JSP for display
+ *
+ */
+ void doBuy(StringBuilder sb, String userID, String symbol,
+ String quantity) throws RuntimeException, IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Buy");
+ try {
+ OrderDataBean orderData = buy(userID, symbol, new Double(
+ quantity).doubleValue(), TradeConfig.orderProcessingMode);
+ setAttribute(sb, "orderData", orderData);
+ setAttribute(sb, "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
+ setAttribute(sb, "results", results + "illegal argument. userID=" + userID + ", symbol=" + symbol);
+ setAttribute(sb, "Exception", e);
+ // 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
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("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
+ *
+ */
+ void doHome(StringBuilder sb, String userID, String results)
+ throws RuntimeException, java.io.IOException {
+ BigDecimal balance;
+ String result = "";
+ setAttribute(sb, "Page", "Home");
+ try {
+ AccountDataBean accountData = getAccountData(userID);
+ Collection holdingDataBeans = 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.
+ MarketSummaryDataBean marketSummaryData = getMarketSummary();
+
+ setAttribute(sb, "accountData", accountData);
+ setAttribute(sb, "holdingDataBeans", holdingDataBeans);
+ // See Edge Caching above
+ setAttribute(sb, "marketSummaryData", marketSummaryData);
+ setAttribute(sb, "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
+ setAttribute(sb, "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
+ setAttribute(sb, "Exception", e);
+ } catch (RuntimeException e) {
+ // this is a user error so I will
+ // forward them to another page rather than throw a 500
+ setAttribute(sb, "results", results + " Could not find account for + " + userID);
+ // requestDispatch(ctx, req, resp, TradeConfig.getPage(TradeConfig.HOME_PAGE));
+ // log the exception with an error level of 3 which means, handled
+ // exception but would invalidate a automation run
+ setAttribute(sb, "Exception", e);
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("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
+ *
+ */
+ boolean doLogin(StringBuilder sb, String userID, String passwd)
+ throws RuntimeException, java.io.IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Login");
+ try {
+ // Got a valid userID and passwd, attempt login
+ AccountDataBean accountData = login(userID, passwd);
+ if (accountData != null) {
+ // HttpSession session = req.getSession(true);
+ setAttribute(sb, "uidBean", userID);
+ setAttribute(sb, "sessionCreationDate", new java.util.Date());
+ results = "Ready to Trade";
+ doHome(sb, userID, results);
+ return true;
+ } else {
+ setAttribute(sb, "results", results + " Could not find account for + " + userID);
+ // log the exception with an error level of 3 which means,
+ // handled exception but would invalidate a automation run
+ }
+ } catch (java.lang.IllegalArgumentException e) {
+ // this is a user error so I will
+ // forward them to another page rather than throw a 500
+ setAttribute(sb, "results", results + "illegal argument. userID=" + userID + ", passwd=" + passwd);
+ // log the exception with an error level of 3 which means, handled
+ // exception but would invalidate a automation run
+ setAttribute(sb, "Exception", e);
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("TradeServletAction.doLogin(...)"
+ + "Exception logging in user " + userID + "with password"
+ + passwd, e);
+ }
+ // requestDispatch(ctx, req, resp, userID, TradeConfig.getPage(TradeConfig.WELCOME_PAGE));
+ return false;
+ }
+
+ /**
+ * Logout a Trade User Dispatch to the Trade Welcome JSP for display
+ *
+ */
+ void doLogout(StringBuilder sb, String userID) throws RuntimeException,
+ IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Logout");
+ try {
+ 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.
+ setAttribute(sb, "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
+ setAttribute(sb, "Exception", e);
+ } catch (Exception e) {
+ // log the exception and foward to a error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("TradeServletAction.doLogout(...)"
+ + "exception logging out user " + userID, e);
+ }
+ // 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
+ *
+ */
+ void doPortfolio(StringBuilder sb, String userID, String results)
+ throws RuntimeException, IOException {
+ setAttribute(sb, "Page", "Portfolio");
+ try {
+ // Get the holdiings for this user
+ Collection quoteDataBeans = new ArrayList();
+ Collection holdingDataBeans = 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 = getQuote(holdingData.getQuoteID());
+ quoteDataBeans.add(quoteData);
+ }
+ } else {
+ results = results + ". Your portfolio is empty.";
+ }
+ setAttribute(sb, "results", results);
+ setAttribute(sb, "holdingDataBeans", holdingDataBeans);
+ setAttribute(sb, "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
+ setAttribute(sb, "results", results + "illegal argument for userID=" + userID);
+ setAttribute(sb, "Exception", e);
+ // 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
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("TradeServletAction.doPortfolio(...)"
+ + " exception user =" + userID, e);
+ }
+ }
+
+ /**
+ * Retrieve the current Quote for the given stock symbol Dispatch to the
+ * Trade Quote JSP for display
+ *
+ */
+ void doQuotes(StringBuilder sb, String userID, String symbols)
+ throws RuntimeException, IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Quotes");
+ // 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));
+ try {
+ Collection<OrderDataBean> closedOrders = getClosedOrders(userID);
+ // quote.jsp displays closed orders
+ if (closedOrders.size() > 0) {
+ setAttribute(sb, "closedOrders", closedOrders);
+ } else {
+ results = results + ". You have no closed orders.";
+ }
+ // quote.jsp displays quotes for the given symbol(s)
+ setAttribute(sb, "symbols", symbols);
+ QuoteDataBean quote = getQuote(symbols);
+ setAttribute(sb, "quote", quote);
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("TradeServletAction.doQuotes(...)"
+ + " exception user =" + userID + ", symbols=" + symbols, e);
+ }
+ }
+
+ /**
+ * Register a new trader given the provided user Profile information such as
+ * address, email, etc. Dispatch to the Trade Home JSP for display
+ *
+ */
+ void doRegister(StringBuilder sb, String userID, String passwd,
+ String cpasswd, String fullname, String ccn,
+ String openBalanceString, String email, String address)
+ throws RuntimeException, IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Register");
+ try {
+ // Validate user passwords match and are at least 1 char in length
+ if ((passwd.equals(cpasswd)) && (passwd.length() >= 1)) {
+ AccountDataBean accountData = register(userID, passwd,
+ fullname, address, email, ccn, new BigDecimal(
+ openBalanceString));
+ if (accountData == null) {
+ results = "Registration operation failed;";
+ setAttribute(sb, "results", results);
+ // requestDispatch(ctx, req, resp, userID, TradeConfig.getPage(TradeConfig.REGISTER_PAGE));
+ } else {
+ doLogin(sb, userID, passwd);
+ results = "Registration operation succeeded; Account "
+ + accountData.getAccountID() + " has been created.";
+ setAttribute(sb, "results", results);
+ }
+ } else {
+ // Password validation failed
+ results = "Registration operation failed, your passwords did not match";
+ System.out.println(results);
+ setAttribute(sb, "results", results);
+ // requestDispatch(ctx, req, resp, userID, TradeConfig.getPage(TradeConfig.REGISTER_PAGE));
+ }
+
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("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
+ *
+ */
+ void doSell(StringBuilder sb, String userID, Integer holdingID)
+ throws RuntimeException, IOException {
+ String results = "";
+ setAttribute(sb, "Page", "Sell");
+ try {
+ OrderDataBean orderData = sell(userID, holdingID, TradeConfig.orderProcessingMode);
+
+ setAttribute(sb, "orderData", orderData);
+ setAttribute(sb, "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
+ setAttribute(sb, "Exception", e);
+ } catch (Exception e) {
+ // log the exception with error page
+ setAttribute(sb, "Exception", e);
+ throw new RuntimeException("TradeServletAction.doSell(...)"
+ + " exception selling holding " + holdingID + " for user ="
+ + userID, e);
+ }
+ // requestDispatch(ctx, req, resp, userID, TradeConfig.getPage(TradeConfig.ORDER_PAGE));
+ }
+
+ void doWelcome(StringBuilder sb, String status) throws RuntimeException,
+ IOException {
+ setAttribute(sb, "Page", "Welcome");
+ setAttribute(sb, "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 RuntimeException, IOException {
+
+ ctx.getRequestDispatcher(page).include(req, resp);
+ }
+ */
+
+ /*
+ private void sendRedirect(HttpServletResponse resp, String page)
+ throws RuntimeException, IOException {
+ resp.sendRedirect(resp.encodeRedirectURL(page));
+ }
+ */
+
+ private void setAttribute(StringBuilder sb, String attribute, Object value) {
+ if (log != null && log.isTraceEnabled()) {
+ sb.append(attribute);
+ sb.append(" = ");
+ sb.append(value);
+ sb.append(System.getProperty("line.separator"));
+ }
+ }
+}
\ No newline at end of file
Propchange: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeAction.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeBuildDB.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeBuildDB.java?rev=1025762&r1=1025761&r2=1025762&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeBuildDB.java (original)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeBuildDB.java Wed Oct 20 21:20:23 2010
@@ -43,39 +43,33 @@ import org.apache.openjpa.lib.log.Log;
*/
public class TradeBuildDB {
- private TradeConfig tCfg = new TradeConfig();
- private TradeJPADirect trade = null;
- private Log log = null;
-
+ private TradeAction trade = null;
+
/**
* Re-create the DayTrader db tables and populate them OR just populate a
* DayTrader DB, logging to the provided output stream
*/
- public TradeBuildDB(Log log, EntityManagerFactory emf) throws Exception {
- this.log = log;
+ public TradeBuildDB(Log log, TradeAction trade) throws Exception {
+ this.trade = trade;
// update config
- tCfg.setRunTimeMode(TradeConfig.JPA);
- tCfg.setLog(log);
// always use TradeJPADirect mode
- trade = new TradeJPADirect(log, emf);
// removed - createDBTables
// removed - Attempt to delete all of the Trade users and Trade Quotes first
- // create MAX_QUOTES
- createQuotes();
-
- // create MAX_USERS
- createAccounts();
}
- private void createQuotes() {
+ public void setup(int quotes, int users) {
+ createQuotes(quotes);
+ createAccounts(users);
+ }
+ private void createQuotes(int quotes) {
int errorCount = 0;
String symbol, companyName;
- log.info("TradeBuildDB.createQuotes(" + TradeConfig.getMAX_QUOTES() + ")");
- for (int i = 0; i < TradeConfig.getMAX_QUOTES(); i++) {
+ TradeConfig.log.info("TradeBuildDB.createQuotes(" + quotes + ")");
+ for (int i = 0; i < quotes; i++) {
symbol = "s:" + i;
companyName = "S" + i + " Incorporated";
try {
@@ -83,7 +77,7 @@ public class TradeBuildDB {
new java.math.BigDecimal(TradeConfig.rndPrice()));
} catch (Exception e) {
if (errorCount++ >= 10) {
- log.error("createQuotes - aborting after 10 create quote errors", e);
+ TradeConfig.log.error("createQuotes - aborting after 10 create quote errors", e);
throw new RuntimeException(e);
}
}
@@ -91,9 +85,9 @@ public class TradeBuildDB {
}
- private void createAccounts() {
- log.info("TradeBuildDB.createAccounts(" + TradeConfig.getMAX_USERS() + ")");
- for (int i = 0; i < TradeConfig.getMAX_USERS(); i++) {
+ private void createAccounts(int users) {
+ TradeConfig.log.info("TradeBuildDB.createAccounts(" + users + ")");
+ for (int i = 0; i < users; i++) {
String userID = "uid:" + i;
String fullname = TradeConfig.rndFullName();
String email = TradeConfig.rndEmail(userID);
@@ -119,10 +113,11 @@ public class TradeBuildDB {
quantity = TradeConfig.rndQuantity();
orderData = trade.buy(userID, symbol, quantity, TradeConfig.orderProcessingMode);
}
- if (log.isTraceEnabled()) {
- log.trace("createAccounts - created " + holdings + " for userID=" + userID + " order=" + orderData);
+ if (TradeConfig.log.isTraceEnabled()) {
+ TradeConfig.log.trace("createAccounts - created " + holdings + " for userID=" + userID + " order=" + orderData);
}
} else {
+ TradeConfig.log.error("createAccounts - userID=" + userID + " already registered.");
throw new RuntimeException("createAccounts - userID=" + userID + " already registered.");
}
}
Modified: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeConfig.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeConfig.java?rev=1025762&r1=1025761&r2=1025762&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeConfig.java (original)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeConfig.java Wed Oct 20 21:20:23 2010
@@ -38,7 +38,8 @@ public class TradeConfig {
public static final int UNKNOWN = -1;
/* Trade Runtime Mode parameters */
- public static String[] runTimeModeNames = {"Full EJB3", "Direct (JDBC)", "Session (EJB3) To Direct", "Web JDBC", "Web JPA"};
+ public static String[] runTimeModeNames = {"Full EJB3", "Direct (JDBC)", "Session (EJB3) To Direct",
+ "Web JDBC", "Web JPA"};
public static final int EJB3 = 0;
public static final int DIRECT = 1;
public static final int SESSION3 = 2;
Modified: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeJPADirect.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeJPADirect.java?rev=1025762&r1=1025761&r2=1025762&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeJPADirect.java (original)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeJPADirect.java Wed Oct 20 21:20:23 2010
@@ -24,7 +24,6 @@ import java.util.Iterator;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
-import javax.persistence.Persistence;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
@@ -68,7 +67,7 @@ public class TradeJPADirect {
private static boolean initialized = false;
- private static Log log = null;
+ protected static Log log = null;
// constructor for OpenJPA junit tests
@@ -183,20 +182,13 @@ public class TradeJPADirect {
entityManager.getTransaction().begin();
- AccountProfileDataBean profile = entityManager.find(
- AccountProfileDataBean.class, userID);
+ AccountProfileDataBean profile = entityManager.find(AccountProfileDataBean.class, userID);
AccountDataBean account = profile.getAccount();
-
- QuoteDataBean quote = entityManager.find(QuoteDataBean.class,
- symbol);
-
+ QuoteDataBean quote = entityManager.find(QuoteDataBean.class, symbol);
HoldingDataBean holding = null; // The holding will be created by this buy order
-
order = createOrder(account, quote, holding, "buy", quantity, entityManager);
-
// order = createOrder(account, quote, holding, "buy", quantity);
// UPDATE - account should be credited during completeOrder
-
BigDecimal price = quote.getPrice();
BigDecimal orderFee = order.getOrderFee();
BigDecimal balance = account.getBalance();
@@ -210,16 +202,14 @@ public class TradeJPADirect {
completeOrder(order.getOrderID(), false);
else if (orderProcessingMode == TradeConfig.ASYNCH_2PHASE)
queueOrder(order.getOrderID(), true);
- }
- catch (Exception e) {
+ } catch (Exception e) {
log.error("TradeJPADirect:buy(" + userID + "," + symbol + "," + quantity + ") --> failed", e);
/* On exception - cancel the order */
// TODO figure out how to do this with JPA
if (order != null)
order.cancel();
-
- entityManager.getTransaction().rollback();
-
+ if (entityManager.getTransaction().isActive())
+ entityManager.getTransaction().rollback();
// throw new EJBException(e);
throw new RuntimeException(e);
} finally {
@@ -227,13 +217,10 @@ public class TradeJPADirect {
entityManager.close();
entityManager = null;
}
-
}
-
// after the purchase or sell of a stock, update the stocks volume and
// price
updateQuotePriceVolume(symbol, TradeConfig.getRandomPriceChangeFactor(), quantity);
-
return order;
}
@@ -248,12 +235,10 @@ public class TradeJPADirect {
if (log.isTraceEnabled())
log.trace("TradeJPADirect:sell - userID=" + userID + " holding=" + holdingID);
- AccountProfileDataBean profile = entityManager.find(
- AccountProfileDataBean.class, userID);
+ AccountProfileDataBean profile = entityManager.find(AccountProfileDataBean.class, userID);
AccountDataBean account = profile.getAccount();
- HoldingDataBean holding = entityManager.find(HoldingDataBean.class,
- holdingID);
+ HoldingDataBean holding = entityManager.find(HoldingDataBean.class, holdingID);
if (holding == null) {
log.error("TradeJPADirect:sell User " + userID
@@ -300,9 +285,7 @@ public class TradeJPADirect {
// TODO figure out JPA cancel
if (order != null)
order.cancel();
-
entityManager.getTransaction().rollback();
-
throw new RuntimeException("TradeJPADirect:sell(" + userID + "," + holdingID + ")", e);
} finally {
if (entityManager != null) {
@@ -319,10 +302,8 @@ public class TradeJPADirect {
}
public void queueOrder(Integer orderID, boolean twoPhase) {
- log
- .error("TradeJPADirect:queueOrder() not implemented for this runtime mode");
- throw new UnsupportedOperationException(
- "TradeJPADirect:queueOrder() not implemented for this runtime mode");
+ log.error("TradeJPADirect:queueOrder() not implemented for this runtime mode");
+ throw new UnsupportedOperationException("TradeJPADirect:queueOrder() not implemented for this runtime mode");
}
public OrderDataBean completeOrder(Integer orderID, boolean twoPhase)
@@ -333,43 +314,42 @@ public class TradeJPADirect {
if (log.isTraceEnabled())
log.trace("TradeJPADirect:completeOrder - orderId=" + orderID + " twoPhase=" + twoPhase);
- order = entityManager.find(OrderDataBean.class, orderID);
- order.getQuote();
-
- if (order == null) {
- log.error("TradeJPADirect:completeOrder -- Unable to find Order " + orderID + " FBPK returned " + order);
- return null;
- }
+ try {
+ order = entityManager.find(OrderDataBean.class, orderID);
+ order.getQuote();
- if (order.isCompleted()) {
- throw new RuntimeException("Error: attempt to complete Order that is already completed\n" + order);
- }
+ if (order == null) {
+ log.error("TradeJPADirect:completeOrder -- Unable to find orderID=" + orderID);
+ return null;
+ }
- AccountDataBean account = order.getAccount();
- QuoteDataBean quote = order.getQuote();
- HoldingDataBean holding = order.getHolding();
- BigDecimal price = order.getPrice();
- double quantity = order.getQuantity();
+ if (order.isCompleted()) {
+ throw new RuntimeException("Error: attempt to complete Order that is already completed\n" + order);
+ }
- String userID = account.getProfile().getUserID();
+ AccountDataBean account = order.getAccount();
+ QuoteDataBean quote = order.getQuote();
+ HoldingDataBean holding = order.getHolding();
+ BigDecimal price = order.getPrice();
+ double quantity = order.getQuantity();
- if (log.isTraceEnabled())
- log.trace("TradeJPADirect:completeOrder--> Completing Order "
- + order.getOrderID() + "\n\t Order info: " + order
- + "\n\t Account info: " + account + "\n\t Quote info: "
- + quote + "\n\t Holding info: " + holding);
+ String userID = account.getProfile().getUserID();
- HoldingDataBean newHolding = null;
- if (order.isBuy()) {
- /*
- * Complete a Buy operation - create a new Holding for the Account -
- * deduct the Order cost from the Account balance
- */
+ if (log.isTraceEnabled())
+ log.trace("TradeJPADirect:completeOrder--> Completing Order "
+ + order.getOrderID() + "\n\t Order info: " + order
+ + "\n\t Account info: " + account + "\n\t Quote info: "
+ + quote + "\n\t Holding info: " + holding);
- newHolding = createHolding(account, quote, quantity, price, entityManager);
- }
+ HoldingDataBean newHolding = null;
+ if (order.isBuy()) {
+ /*
+ * Complete a Buy operation - create a new Holding for the Account -
+ * deduct the Order cost from the Account balance
+ */
+ newHolding = createHolding(account, quote, quantity, price, entityManager);
+ }
- try {
entityManager.getTransaction().begin();
if (newHolding != null) {
@@ -382,7 +362,8 @@ public class TradeJPADirect {
* deposit the Order proceeds to the Account balance
*/
if (holding == null) {
- log.error("TradeJPADirect:completeOrder -- Unable to sell order " + order.getOrderID() + " holding already sold");
+ log.error("TradeJPADirect:completeOrder -- Unable to sell order " + order.getOrderID()
+ + ", holding already sold (null)");
order.cancel();
entityManager.getTransaction().commit();
return order;
@@ -394,20 +375,20 @@ public class TradeJPADirect {
}
order.setOrderStatus("closed");
-
order.setCompletionDate(new java.sql.Timestamp(System.currentTimeMillis()));
-
+ entityManager.persist(order);
+ entityManager.getTransaction().commit();
+
if (log.isTraceEnabled())
log.trace("TradeJPADirect:completeOrder--> Completed Order "
+ order.getOrderID() + "\n\t Order info: " + order
+ "\n\t Account info: " + account + "\n\t Quote info: "
- + quote + "\n\t Holding info: " + holding);
+ + quote + "\n\t Holding info: " + newHolding);
- entityManager.getTransaction().commit();
- }
- catch (Exception e) {
- e.printStackTrace();
- entityManager.getTransaction().rollback();
+ } catch (Exception e) {
+ log.error("TradeJPADirect:completeOrder() failed for orderID=" + orderID, e);
+ if (entityManager.getTransaction().isActive())
+ entityManager.getTransaction().rollback();
} finally {
if (entityManager != null) {
entityManager.close();
@@ -510,25 +491,24 @@ public class TradeJPADirect {
* with annotated query "orderejb.completeClosedOrders" defined
* in OrderDatabean
*/
- Query findaccountid = entityManager
- .createNativeQuery(
- "select "
- + "a.ACCOUNTID, "
- + "a.LOGINCOUNT, "
- + "a.LOGOUTCOUNT, "
- + "a.LASTLOGIN, "
- + "a.CREATIONDATE, "
- + "a.BALANCE, "
- + "a.OPENBALANCE, "
- + "a.PROFILE_USERID "
- + "from accountejb a where a.profile_userid = ?",
- // org.apache.geronimo.samples.daytrader.beans.AccountDataBean.class);
- org.apache.openjpa.integration.daytrader.AccountDataBean.class);
+ Query findaccountid = entityManager.createNativeQuery(
+ "select "
+ + "a.ACCOUNTID, "
+ + "a.LOGINCOUNT, "
+ + "a.LOGOUTCOUNT, "
+ + "a.LASTLOGIN, "
+ + "a.CREATIONDATE, "
+ + "a.BALANCE, "
+ + "a.OPENBALANCE, "
+ + "a.PROFILE_USERID "
+ + "from accountejb a where a.profile_userid = ?",
+ org.apache.openjpa.integration.daytrader.AccountDataBean.class);
findaccountid.setParameter(1, userID);
AccountDataBean account = (AccountDataBean) findaccountid.getSingleResult();
Integer accountid = account.getAccountID();
- Query updateStatus = entityManager.createNativeQuery("UPDATE orderejb o SET o.orderStatus = 'completed' WHERE "
- + "o.orderStatus = 'closed' AND o.ACCOUNT_ACCOUNTID = ?");
+ Query updateStatus = entityManager.createNativeQuery(
+ "UPDATE orderejb o SET o.orderStatus = 'completed' WHERE "
+ + "o.orderStatus = 'closed' AND o.ACCOUNT_ACCOUNTID = ?");
updateStatus.setParameter(1, accountid.intValue());
updateStatus.executeUpdate();
}
@@ -554,32 +534,23 @@ public class TradeJPADirect {
public QuoteDataBean createQuote(String symbol, String companyName,
BigDecimal price) {
EntityManager entityManager = emf.createEntityManager();
+ QuoteDataBean quote = null;
try {
- QuoteDataBean quote = new QuoteDataBean(symbol, companyName, 0, price, price, price, price, 0);
+ quote = new QuoteDataBean(symbol, companyName, 0, price, price, price, price, 0);
/*
* managed transaction
*/
- try {
entityManager.getTransaction().begin();
entityManager.persist(quote);
entityManager.getTransaction().commit();
- }
- catch (Exception e) {
- entityManager.getTransaction().rollback();
- }
if (log.isTraceEnabled())
log.trace("TradeJPADirect:createQuote-->" + quote);
-
- if (entityManager != null) {
- entityManager.close();
- entityManager = null;
- }
return quote;
} catch (Exception e) {
- log.error("TradeJPADirect:createQuote -- exception creating Quote", e);
- entityManager.close();
- entityManager = null;
+ log.error("TradeJPADirect:createQuote -- exception creating Quote=" + quote, e);
+ if (entityManager.getTransaction().isActive())
+ entityManager.getTransaction().rollback();
throw new RuntimeException(e);
} finally {
if (entityManager != null) {
@@ -856,14 +827,12 @@ public class TradeJPADirect {
EntityManager entityManager = emf.createEntityManager();
if (log.isTraceEnabled()) {
- // Log.trace("TradeJPADirect:register", userID, password, fullname, address, email, creditcard, openBalance);
+ //Log.trace("TradeJPADirect:register", userID, password, fullname, address, email, creditcard, openBalance);
log.trace("TradeJPADirect:register - userID=" + userID);
}
// Check to see if a profile with the desired userID already exists
-
profile = entityManager.find(AccountProfileDataBean.class, userID);
-
if (profile != null) {
log.error("Failed to register new Account - AccountProfile with userID(" + userID + ") already exists");
return null;
@@ -871,7 +840,8 @@ public class TradeJPADirect {
else {
profile = new AccountProfileDataBean(userID, password, fullname,
address, email, creditcard);
- account = new AccountDataBean(0, 0, null, new Timestamp(System.currentTimeMillis()), openBalance, openBalance, userID);
+ account = new AccountDataBean(0, 0, null, new Timestamp(System.currentTimeMillis()),
+ openBalance, openBalance, userID);
profile.setAccount(account);
account.setProfile(profile);
/*
@@ -884,6 +854,7 @@ public class TradeJPADirect {
entityManager.getTransaction().commit();
}
catch (Exception e) {
+ log.error("Failed to create account and profile for userId=" + userID, e);
entityManager.getTransaction().rollback();
} finally {
entityManager.close();
@@ -910,7 +881,8 @@ public class TradeJPADirect {
if (!TradeConfig.getPublishQuotePriceChange())
return;
log.error("TradeJPADirect:publishQuotePriceChange - is not implemented for this runtime mode");
- throw new UnsupportedOperationException("TradeJPADirect:publishQuotePriceChange - is not implemented for this runtime mode");
+ throw new UnsupportedOperationException(
+ "TradeJPADirect:publishQuotePriceChange - is not implemented for this runtime mode");
}
/*
@@ -959,13 +931,15 @@ public class TradeJPADirect {
entityManager.getTransaction().begin();
entityManager.persist(newHolding);
entityManager.getTransaction().commit();
+ if (log.isTraceEnabled())
+ log.trace("TradeJPADirect:createHolding(account=" + ((account == null) ? null : account.getAccountID())
+ + " quote=" + ((quote == null) ? null : quote.getSymbol())
+ + " quantity=" + quantity + " purchasePrice=" + purchasePrice + ")");
}
catch (Exception e) {
+ log.error("createHolding() failed for newHolding=" + newHolding, e);
entityManager.getTransaction().rollback();
- } finally {
- entityManager.close();
}
-
return newHolding;
}
@@ -980,9 +954,9 @@ public class TradeJPADirect {
}
public QuoteDataBean pingTwoPhase(String symbol) throws Exception {
- log
- .error("TradeJPADirect:pingTwoPhase - is not implemented for this runtime mode");
- throw new UnsupportedOperationException("TradeJPADirect:pingTwoPhase - is not implemented for this runtime mode");
+ log.error("TradeJPADirect:pingTwoPhase - is not implemented for this runtime mode");
+ throw new UnsupportedOperationException(
+ "TradeJPADirect:pingTwoPhase - is not implemented for this runtime mode");
}
class quotePriceComparator implements java.util.Comparator {
Added: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeScenario.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeScenario.java?rev=1025762&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeScenario.java (added)
+++ openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeScenario.java Wed Oct 20 21:20:23 2010
@@ -0,0 +1,254 @@
+/**
+ * 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.openjpa.integration.daytrader;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.io.IOException;
+
+/**
+ * TradeScenarioServlet emulates a population of web users by generating a specific Trade operation
+ * for a randomly chosen user on each access to the URL. Test this servlet by clicking Trade Scenario
+ * and hit "Reload" on your browser to step through a Trade Scenario. To benchmark using this URL aim
+ * your favorite web load generator (such as AKStress) at the Trade Scenario URL and fire away.
+ */
+public class TradeScenario {
+
+ private TradeAction tAction = null;
+
+ public TradeScenario(TradeAction tAction) {
+ this.tAction = tAction;
+ }
+
+ /**
+ * Perform the following 15 tasks for the given userID:
+ * login, home, account, update, home, portfolio, sell, buy, home, portfolio, sell, buy, home, account, logout
+ *
+ * @param userID
+ * @return
+ */
+ public boolean performUserTasks(String userID) {
+ StringBuilder sb = new StringBuilder(16384);
+ boolean brc = false;
+
+ if (TradeConfig.log.isTraceEnabled()) {
+ TradeConfig.log.trace("TradeScenario.performUserTasks(" + userID + ")");
+ }
+
+ try {
+ // login
+ log(sb, performTask("l", userID));
+ // home page
+ log(sb, performTask("h", userID));
+ // account info and orders
+ log(sb, performTask("a", userID));
+ // update account info
+ log(sb, performTask("u", userID));
+ // home page
+ log(sb, performTask("h", userID));
+ // portfolio holdings
+ log(sb, performTask("p", userID));
+ // sell
+ log(sb, performTask("s", userID));
+ // buy
+ log(sb, performTask("b", userID));
+ // home page
+ log(sb, performTask("h", userID));
+ // portfolio holdings
+ log(sb, performTask("p", userID));
+ // sell
+ log(sb, performTask("s", userID));
+ // buy
+ log(sb, performTask("b", userID));
+ // home page
+ log(sb, performTask("h", userID));
+ // account info and orders
+ log(sb, performTask("a", userID));
+ // logout
+ log(sb, performTask("o", userID));
+ brc = true;
+ if (TradeConfig.log.isTraceEnabled()) {
+ TradeConfig.log.trace(sb.toString());
+ }
+ } catch (Exception e) {
+ TradeConfig.log.error("TradeScenario.performUserTasks(" + userID + ") failed", e);
+ }
+ return brc;
+ }
+
+ /**
+ * Main service method for TradeScenarioServlet
+ *
+ * @param request Object that encapsulates the request to the servlet
+ * @param response Object that encapsulates the response from the servlet
+ */
+ public String performTask(String scenarioAction, String userID) throws IOException {
+ StringBuilder sb = new StringBuilder(256);
+ String results = "";
+ // Scenario generator for Trade2
+ char action = ' ';
+
+ // String to create full dispatch path to TradeAppServlet w/ request Parameters
+ String dispPath = null; // Dispatch Path to TradeAppServlet
+
+ if ((scenarioAction != null) && (scenarioAction.length() >= 1))
+ {
+ action = scenarioAction.charAt(0);
+ if (action == 'n')
+ { //null;
+ try
+ {
+ log(sb, "TradeScenario.performTask() scenarioAction=" + scenarioAction + ", userID=" + userID);
+ }
+ catch (Exception e)
+ {
+ log(sb, "ERROR - TradeScenario.performTask() - Exception ", e);
+ } finally {
+ return sb.toString();
+ }
+ } //end of action=='n'
+ }
+
+ if (userID == null || userID.trim().length() == 0) {
+ // These operations require the user to be logged in. Verify the user and if not logged in
+ // change the operation to a login
+ userID = null;
+ action = 'l';
+ TradeConfig.incrementScenarioCount();
+ } else if (action == ' ') {
+ //action is not specified perform a random operation according to current mix
+ // Tell getScenarioAction if we are an original user or a registered user
+ // -- sellDeficits should only be compensated for with original users.
+ action = TradeConfig.getScenarioAction(
+ userID.startsWith(TradeConfig.newUserPrefix));
+ }
+
+ switch (action) {
+ case 'q' : //quote
+ tAction.doQuotes(sb, userID, TradeConfig.rndSymbols());
+ break;
+ case 'a' : //account
+ tAction.doAccount(sb, userID, results);
+ break;
+ case 'u' : //update account profile
+ String fullName = "rnd" + System.currentTimeMillis();
+ String address = "rndAddress";
+ String password = "xxx";
+ String email = "rndEmail";
+ String creditcard = "rndCC";
+ tAction.doAccountUpdate(sb, userID, password, password, fullName, address, creditcard, email);
+ break;
+ case 'h' : //home
+ tAction.doHome(sb, userID, results);
+ break;
+ case 'l' : //login
+ userID = TradeConfig.getUserID();
+ String password2 = "xxx";
+ boolean brc = tAction.doLogin(sb, userID, password2);
+ // login is successful if the userID is written to the HTTP session
+ if (!brc) {
+ log(sb, "TradeScenario login failed. Reset DB between runs.");
+ }
+ break;
+ case 'o' : //logout
+ tAction.doLogout(sb, userID);
+ break;
+ case 'p' : //portfolio
+ tAction.doPortfolio(sb, userID, results);
+ break;
+ case 'r' : //register
+ //Logout the current user to become a new user
+ // see note in TradeServletAction
+ tAction.doLogout(sb, userID);
+
+ userID = TradeConfig.rndNewUserID();
+ String passwd = "yyy";
+ fullName = TradeConfig.rndFullName();
+ creditcard = TradeConfig.rndCreditCard();
+ String money = TradeConfig.rndBalance();
+ email = TradeConfig.rndEmail(userID);
+ String smail = TradeConfig.rndAddress();
+ tAction.doRegister(sb, userID, passwd, passwd, fullName, creditcard, money, email, smail);
+ break;
+ case 's' : //sell
+ Collection<HoldingDataBean> holdings = tAction.getHoldings(userID);
+ int numHoldings = holdings.size();
+ if (numHoldings > 0)
+ {
+ //sell first available security out of holding
+ Iterator it = holdings.iterator();
+ boolean foundHoldingToSell = false;
+ while (it.hasNext())
+ {
+ HoldingDataBean holdingData = (HoldingDataBean) it.next();
+ if ( !(holdingData.getPurchaseDate().equals(new java.util.Date(0))) )
+ {
+ Integer holdingID = holdingData.getHoldingID();
+ tAction.doSell(sb, userID, holdingID);
+ foundHoldingToSell = true;
+ break;
+ }
+ }
+ if (foundHoldingToSell) break;
+ tAction.log.warn("TradeScenario: No holdings sold for userID=" + userID +
+ ", holdings=" + numHoldings);
+ } else {
+ tAction.log.warn("TradeScenario: No holdings to sell for userID=" + userID);
+ }
+ // At this point: A TradeScenario Sell was requested with No Stocks in Portfolio
+ // This can happen when a new registered user happens to request a sell before a buy
+ // In this case, fall through and perform a buy instead
+ tAction.log.warn("TradeScenario: No holdings sold - switching to buy -- userID=" + userID);
+
+ /* Trade 2.037: Added sell_deficit counter to maintain correct buy/sell mix.
+ * When a users portfolio is reduced to 0 holdings, a buy is requested instead of a sell.
+ * This throws off the buy/sell mix by 1. This results in unwanted holding table growth
+ * To fix we increment a sell deficit counter to maintain the correct ratio in getScenarioAction
+ * The 'z' action from getScenario denotes that this is a sell action that was switched from a buy
+ * to reduce a sellDeficit
+ */
+ if (userID.startsWith(TradeConfig.newUserPrefix) == false)
+ {
+ TradeConfig.incrementSellDeficit();
+ }
+ case 'b' : //buy
+ String symbol = TradeConfig.rndSymbol();
+ String amount = TradeConfig.rndQuantity() + "";
+ tAction.doQuotes(sb, userID, symbol);
+ tAction.doBuy(sb, userID, symbol, amount);
+ break;
+ } //end of switch statement
+ log(sb, "Results", results);
+ return sb.toString();
+ }
+
+ private void log(StringBuilder sb, String msg) {
+ if (tAction.log != null && tAction.log.isTraceEnabled()) {
+ sb.append(msg);
+ sb.append(System.getProperty("line.separator"));
+ }
+ }
+
+ private void log(StringBuilder sb, String msg, Object obj) {
+ if (tAction.log != null && tAction.log.isTraceEnabled()) {
+ sb.append(msg);
+ sb.append(" = ");
+ sb.append(obj);
+ sb.append(System.getProperty("line.separator"));
+ }
+ }
+}
Propchange: openjpa/trunk/openjpa-integration/daytrader/src/test/java/org/apache/openjpa/integration/daytrader/TradeScenario.java
------------------------------------------------------------------------------
svn:eol-style = native