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