001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.samples.daytrader.direct; 018 019 import java.math.BigDecimal; 020 import java.util.Collection; 021 import java.util.ArrayList; 022 import javax.naming.InitialContext; 023 import javax.transaction.UserTransaction; 024 import javax.jms.*; 025 026 import javax.sql.DataSource; 027 028 import org.apache.geronimo.samples.daytrader.ejb.Trade; 029 import org.apache.geronimo.samples.daytrader.ejb.TradeHome; 030 import org.apache.geronimo.samples.daytrader.util.*; 031 032 import java.rmi.RemoteException; 033 import java.sql.Connection; 034 import java.sql.DatabaseMetaData; 035 import java.sql.PreparedStatement; 036 import java.sql.ResultSet; 037 import java.sql.SQLException; 038 import java.sql.Statement; 039 import java.sql.Timestamp; 040 041 import org.apache.geronimo.samples.daytrader.*;; 042 043 /** 044 * TradeDirect uses direct JDBC and JMS access to a <code>javax.sql.DataSource</code> to implement the business methods 045 * of the Trade online broker application. These business methods represent the features and operations that 046 * can be performed by customers of the brokerage such as login, logout, get a stock quote, buy or sell a stock, etc. 047 * and are specified in the {@link org.apache.geronimo.samples.daytrader.TradeServices} interface 048 * 049 * Note: In order for this class to be thread-safe, a new TradeJDBC must be created 050 * for each call to a method from the TradeInterface interface. Otherwise, pooled 051 * connections may not be released. 052 * 053 * @see org.apache.geronimo.samples.daytrader.TradeServices 054 * @see org.apache.geronimo.samples.daytrader.ejb.Trade 055 * 056 */ 057 058 public class TradeDirect implements TradeServices 059 060 { 061 062 private static String dsName = TradeConfig.DATASOURCE; 063 private static DataSource datasource = null; 064 private static BigDecimal ZERO = new BigDecimal(0.0); 065 private boolean inGlobalTxn = false; 066 private boolean inSession = false; 067 068 069 /** 070 * Zero arg constructor for TradeDirect 071 */ 072 public TradeDirect() { 073 if (initialized==false) init(); 074 } 075 076 public TradeDirect(boolean inSession) { 077 if (initialized == false) 078 init(); 079 080 this.inSession = inSession; 081 } 082 083 /** 084 * @see TradeServices#getMarketSummary() 085 */ 086 public MarketSummaryDataBean getMarketSummary() throws Exception { 087 088 MarketSummaryDataBean marketSummaryData = null; 089 Connection conn=null; 090 try 091 { 092 if (Log.doTrace()) Log.trace("TradeDirect:getMarketSummary - inSession(" + this.inSession + ")"); 093 094 conn = getConn(); 095 PreparedStatement stmt = getStatement(conn, getTSIAQuotesOrderByChangeSQL, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); 096 097 ArrayList topGainersData = new ArrayList(5); 098 ArrayList topLosersData = new ArrayList(5); 099 100 ResultSet rs = stmt.executeQuery(); 101 102 int count = 0; 103 while (rs.next() && (count++ < 5) ) 104 { 105 QuoteDataBean quoteData = getQuoteDataFromResultSet(rs); 106 topLosersData.add(quoteData); 107 } 108 109 110 stmt.close(); 111 stmt = getStatement(conn, "select * from quoteejb q where q.symbol like 's:1__' order by q.change1 DESC", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); 112 rs = stmt.executeQuery(); 113 114 count = 0; 115 while (rs.next() && (count++ < 5) ) 116 { 117 QuoteDataBean quoteData = getQuoteDataFromResultSet(rs); 118 topGainersData.add(quoteData); 119 } 120 121 122 /* 123 rs.last(); 124 count = 0; 125 while (rs.previous() && (count++ < 5) ) 126 { 127 QuoteDataBean quoteData = getQuoteDataFromResultSet(rs); 128 topGainersData.add(quoteData); 129 }*/ 130 131 stmt.close(); 132 133 BigDecimal TSIA = ZERO; 134 BigDecimal openTSIA = ZERO; 135 double volume=0.0; 136 137 if ( (topGainersData.size() > 0) || (topLosersData.size() > 0)){ 138 139 stmt = getStatement(conn, getTSIASQL); 140 rs = stmt.executeQuery(); 141 142 if (!rs.next() ) 143 Log.error("TradeDirect:getMarketSummary -- error w/ getTSIASQL -- no results"); 144 else 145 TSIA = rs.getBigDecimal("TSIA"); 146 stmt.close(); 147 148 149 stmt = getStatement(conn, getOpenTSIASQL); 150 rs = stmt.executeQuery(); 151 152 if (!rs.next() ) 153 Log.error("TradeDirect:getMarketSummary -- error w/ getOpenTSIASQL -- no results"); 154 else 155 openTSIA = rs.getBigDecimal("openTSIA"); 156 stmt.close(); 157 158 stmt = getStatement(conn, getTSIATotalVolumeSQL); 159 rs = stmt.executeQuery(); 160 161 if (!rs.next() ) 162 Log.error("TradeDirect:getMarketSummary -- error w/ getTSIATotalVolumeSQL -- no results"); 163 else 164 volume = rs.getDouble("totalVolume"); 165 stmt.close(); 166 } 167 commit(conn); 168 169 marketSummaryData = new MarketSummaryDataBean(TSIA, openTSIA, volume, topGainersData, topLosersData); 170 171 } 172 173 catch (Exception e) 174 { 175 Log.error("TradeDirect:login -- error logging in user", e); 176 rollBack(conn, e); 177 } 178 finally 179 { 180 releaseConn(conn); 181 } 182 return marketSummaryData; 183 184 } 185 186 /** 187 * @see TradeServices#buy(String, String, double) 188 */ 189 public OrderDataBean buy(String userID, String symbol, double quantity, int orderProcessingMode) 190 throws Exception { 191 192 Connection conn=null; 193 OrderDataBean orderData = null; 194 UserTransaction txn = null; 195 196 /* 197 * total = (quantity * purchasePrice) + orderFee 198 */ 199 BigDecimal total; 200 201 202 try 203 { 204 if (Log.doTrace()) 205 Log.trace("TradeDirect:buy - inSession(" + this.inSession + ")", userID, symbol, new Double(quantity)); 206 207 if ( !inSession && orderProcessingMode == TradeConfig.ASYNCH_2PHASE ) 208 { 209 if ( Log.doTrace() ) 210 Log.trace("TradeDirect:buy create/begin global transaction"); 211 //FUTURE the UserTransaction be looked up once 212 txn = (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction"); 213 txn.begin(); 214 setInGlobalTxn(true); 215 } 216 217 conn = getConn(); 218 219 AccountDataBean accountData = getAccountData(conn, userID); 220 QuoteDataBean quoteData = getQuoteData(conn, symbol); 221 HoldingDataBean holdingData = null; // the buy operation will create the holding 222 223 orderData = createOrder(conn, accountData, quoteData, holdingData, "buy", quantity); 224 225 //Update -- account should be credited during completeOrder 226 BigDecimal price = quoteData.getPrice(); 227 BigDecimal orderFee = orderData.getOrderFee(); 228 total = (new BigDecimal(quantity).multiply(price)).add(orderFee); 229 // subtract total from account balance 230 creditAccountBalance(conn, accountData, total.negate()); 231 232 try { 233 if (orderProcessingMode == TradeConfig.SYNCH) 234 completeOrder(conn, orderData.getOrderID()); 235 else if (orderProcessingMode == TradeConfig.ASYNCH) 236 queueOrder(orderData.getOrderID(), false); // 1-phase commit 237 else //TradeConfig.ASYNC_2PHASE 238 queueOrder(orderData.getOrderID(), true); // 2-phase commit 239 } 240 catch (JMSException je) 241 { 242 Log.error("TradeBean:buy("+userID+","+symbol+","+quantity+") --> failed to queueOrder", je); 243 /* On exception - cancel the order */ 244 245 cancelOrder(conn, orderData.getOrderID()); 246 } 247 248 orderData = getOrderData(conn, orderData.getOrderID().intValue()); 249 250 if (txn != null) { 251 if ( Log.doTrace() ) 252 Log.trace("TradeDirect:buy committing global transaction"); 253 txn.commit(); 254 setInGlobalTxn(false); 255 } 256 else 257 commit(conn); 258 } 259 catch (Exception e) 260 { 261 Log.error("TradeDirect:buy error - rolling back", e); 262 if ( getInGlobalTxn() ) 263 txn.rollback(); 264 else 265 rollBack(conn, e); 266 } 267 finally 268 { 269 releaseConn(conn); 270 } 271 272 return orderData; 273 } 274 275 /** 276 * @see TradeServices#sell(String, Integer) 277 */ 278 public OrderDataBean sell(String userID, Integer holdingID, int orderProcessingMode) 279 throws Exception { 280 Connection conn=null; 281 OrderDataBean orderData = null; 282 UserTransaction txn = null; 283 284 /* 285 * total = (quantity * purchasePrice) + orderFee 286 */ 287 BigDecimal total; 288 289 try 290 { 291 if (Log.doTrace()) 292 Log.trace("TradeDirect:sell - inSession(" + this.inSession + ")", userID, holdingID); 293 294 if ( !inSession && orderProcessingMode == TradeConfig.ASYNCH_2PHASE ) 295 { 296 if ( Log.doTrace() ) 297 Log.trace("TradeDirect:sell create/begin global transaction"); 298 //FUTURE the UserTransaction be looked up once 299 300 txn = (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction"); 301 txn.begin(); 302 setInGlobalTxn(true); 303 } 304 305 conn = getConn(); 306 307 AccountDataBean accountData = getAccountData(conn, userID); 308 HoldingDataBean holdingData = getHoldingData(conn, holdingID.intValue() ); 309 QuoteDataBean quoteData = null; 310 if ( holdingData != null) quoteData = getQuoteData(conn, holdingData.getQuoteID()); 311 312 if ( (accountData==null) || (holdingData==null) || (quoteData==null) ) 313 { 314 String error = "TradeDirect:sell -- error selling stock -- unable to find: \n\taccount=" +accountData + "\n\tholding=" + holdingData + "\n\tquote="+quoteData + "\nfor user: " + userID + " and holdingID: " + holdingID; 315 Log.error(error); 316 if ( getInGlobalTxn() ) 317 txn.rollback(); 318 else 319 rollBack(conn, new Exception(error)); 320 return orderData; 321 } 322 323 double quantity = holdingData.getQuantity(); 324 325 orderData = createOrder(conn, accountData, quoteData, holdingData, "sell", quantity); 326 327 // Set the holdingSymbol purchaseDate to selling to signify the sell is "inflight" 328 updateHoldingStatus(conn, holdingData.getHoldingID(), holdingData.getQuoteID()); 329 330 //UPDATE -- account should be credited during completeOrder 331 BigDecimal price = quoteData.getPrice(); 332 BigDecimal orderFee = orderData.getOrderFee(); 333 total = (new BigDecimal(quantity).multiply(price)).subtract(orderFee); 334 creditAccountBalance(conn, accountData, total); 335 336 try { 337 if (orderProcessingMode == TradeConfig.SYNCH) 338 completeOrder(conn, orderData.getOrderID()); 339 else if (orderProcessingMode == TradeConfig.ASYNCH) 340 queueOrder(orderData.getOrderID(), false); // 1-phase commit 341 else //TradeConfig.ASYNC_2PHASE 342 queueOrder(orderData.getOrderID(), true); // 2-phase commit 343 } 344 catch (JMSException je) 345 { 346 Log.error("TradeBean:sell("+userID+","+holdingID+") --> failed to queueOrder", je); 347 /* On exception - cancel the order */ 348 349 cancelOrder(conn, orderData.getOrderID()); 350 } 351 352 orderData = getOrderData(conn, orderData.getOrderID().intValue()); 353 354 if (txn != null) { 355 if ( Log.doTrace() ) 356 Log.trace("TradeDirect:sell committing global transaction"); 357 txn.commit(); 358 setInGlobalTxn(false); 359 } 360 else 361 commit(conn); 362 } 363 catch (Exception e) 364 { 365 Log.error("TradeDirect:sell error", e); 366 if ( getInGlobalTxn() ) 367 txn.rollback(); 368 else 369 rollBack(conn, e); 370 } 371 finally 372 { 373 releaseConn(conn); 374 } 375 376 return orderData; 377 } 378 379 /** 380 * @see TradeServices#queueOrder(Integer) 381 */ 382 public void queueOrder(Integer orderID, boolean twoPhase) throws Exception 383 { 384 if (Log.doTrace() ) Log.trace("TradeDirect:queueOrder - inSession(" + this.inSession + ")", orderID); 385 386 javax.jms.Connection conn = null; 387 Session sess = null; 388 389 try 390 { 391 conn = qConnFactory.createConnection(); 392 sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); 393 MessageProducer producer = sess.createProducer(queue); 394 395 TextMessage message = sess.createTextMessage(); 396 397 String command= "neworder"; 398 message.setStringProperty("command", command); 399 message.setIntProperty("orderID", orderID.intValue()); 400 message.setBooleanProperty("twoPhase", twoPhase); 401 message.setBooleanProperty("direct", true); 402 message.setLongProperty("publishTime", System.currentTimeMillis()); 403 message.setText("neworder: orderID="+orderID + " runtimeMode=Direct twoPhase="+twoPhase); 404 405 if (Log.doTrace()) 406 Log.trace("TradeDirectBean:queueOrder Sending message: " + message.getText()); 407 producer.send(message); 408 sess.close(); 409 } 410 411 catch (Exception e) 412 { 413 throw e; // pass the exception back 414 } 415 416 finally 417 { 418 if (sess != null) 419 sess.close(); 420 } 421 } 422 423 424 /** 425 * @see TradeServices#completeOrder(Integer) 426 */ 427 public OrderDataBean completeOrder(Integer orderID, boolean twoPhase) throws Exception 428 { 429 OrderDataBean orderData = null; 430 Connection conn=null; 431 432 if (!twoPhase) 433 { 434 if (Log.doTrace()) 435 Log.trace("TradeDirect:completeOrder -- completing order in 1-phase, calling tradeEJB to start new txn. orderID="+orderID); 436 return tradeEJB.completeOrderOnePhaseDirect(orderID); 437 } 438 try //twoPhase 439 { 440 441 if (Log.doTrace()) Log.trace("TradeDirect:completeOrder - inSession(" + this.inSession + ")", orderID); 442 setInGlobalTxn(!inSession && twoPhase); 443 conn = getConn(); 444 orderData = completeOrder(conn, orderID); 445 commit(conn); 446 447 } 448 catch (Exception e) 449 { 450 Log.error("TradeDirect:completeOrder -- error completing order", e); 451 rollBack(conn, e); 452 cancelOrder(orderID, twoPhase); 453 } 454 finally 455 { 456 releaseConn(conn); 457 } 458 459 return orderData; 460 461 } 462 public OrderDataBean completeOrderOnePhase(Integer orderID) throws Exception 463 { 464 OrderDataBean orderData = null; 465 Connection conn=null; 466 try 467 { 468 if (Log.doTrace()) Log.trace("TradeDirect:completeOrderOnePhase - inSession(" + this.inSession + ")", orderID); 469 setInGlobalTxn(false); 470 conn = getConn(); 471 orderData = completeOrder(conn, orderID); 472 473 commit(conn); 474 475 } 476 catch (Exception e) 477 { 478 Log.error("TradeDirect:completeOrderOnePhase -- error completing order", e); 479 rollBack(conn, e); 480 cancelOrder(orderID, false); 481 } 482 finally 483 { 484 releaseConn(conn); 485 } 486 487 return orderData; 488 489 } 490 491 private OrderDataBean completeOrder(Connection conn, Integer orderID) 492 throws Exception 493 { 494 495 OrderDataBean orderData = null; 496 if (Log.doTrace()) Log.trace("TradeDirect:completeOrderInternal - inSession(" + this.inSession + ")", orderID); 497 498 PreparedStatement stmt = getStatement(conn, getOrderSQL); 499 stmt.setInt(1, orderID.intValue()); 500 501 ResultSet rs = stmt.executeQuery(); 502 503 if ( !rs.next() ) 504 { 505 Log.error("TradeDirect:completeOrder -- unable to find order: " + orderID); 506 stmt.close(); 507 return orderData; 508 } 509 orderData = getOrderDataFromResultSet(rs); 510 511 String orderType = orderData.getOrderType(); 512 String orderStatus = orderData.getOrderStatus(); 513 514 //if (order.isCompleted()) 515 if ( (orderStatus.compareToIgnoreCase("completed") == 0) || 516 (orderStatus.compareToIgnoreCase("alertcompleted") == 0) || 517 (orderStatus.compareToIgnoreCase("cancelled") == 0) ) 518 throw new Exception("TradeDirect:completeOrder -- attempt to complete Order that is already completed"); 519 520 int accountID = rs.getInt("account_accountID"); 521 String quoteID = rs.getString("quote_symbol"); 522 int holdingID = rs.getInt("holding_holdingID"); 523 524 BigDecimal price = orderData.getPrice(); 525 double quantity = orderData.getQuantity(); 526 BigDecimal orderFee = orderData.getOrderFee(); 527 528 //get the data for the account and quote 529 //the holding will be created for a buy or extracted for a sell 530 531 532 /* Use the AccountID and Quote Symbol from the Order 533 AccountDataBean accountData = getAccountData(accountID, conn); 534 QuoteDataBean quoteData = getQuoteData(conn, quoteID); 535 */ 536 String userID = getAccountProfileData(conn, new Integer(accountID)).getUserID(); 537 538 HoldingDataBean holdingData = null; 539 540 if (Log.doTrace()) Log.trace( 541 "TradeDirect:completeOrder--> Completing Order " + orderData.getOrderID() 542 + "\n\t Order info: " + orderData 543 + "\n\t Account info: " + accountID 544 + "\n\t Quote info: " + quoteID); 545 546 //if (order.isBuy()) 547 if ( orderType.compareToIgnoreCase("buy") == 0 ) 548 { 549 /* Complete a Buy operation 550 * - create a new Holding for the Account 551 * - deduct the Order cost from the Account balance 552 */ 553 554 holdingData = createHolding(conn, accountID, quoteID, quantity, price); 555 updateOrderHolding(conn, orderID.intValue(), holdingData.getHoldingID().intValue()); 556 } 557 558 //if (order.isSell()) { 559 if ( orderType.compareToIgnoreCase("sell") == 0 ) 560 { 561 /* Complete a Sell operation 562 * - remove the Holding from the Account 563 * - deposit the Order proceeds to the Account balance 564 */ 565 holdingData = getHoldingData(conn, holdingID); 566 if ( holdingData == null ) 567 Log.debug("TradeDirect:completeOrder:sell -- user: " + userID + " already sold holding: " + holdingID); 568 else 569 removeHolding(conn, holdingID, orderID.intValue()); 570 571 } 572 573 updateOrderStatus(conn, orderData.getOrderID(), "closed"); 574 575 if (Log.doTrace()) Log.trace( 576 "TradeDirect:completeOrder--> Completed Order " + orderData.getOrderID() 577 + "\n\t Order info: " + orderData 578 + "\n\t Account info: " + accountID 579 + "\n\t Quote info: " + quoteID 580 + "\n\t Holding info: " + holdingData); 581 582 stmt.close(); 583 584 commit(conn); 585 586 //signify this order for user userID is complete 587 TradeAction tradeAction = new TradeAction(this); 588 tradeAction.orderCompleted(userID, orderID); 589 590 return orderData; 591 } 592 593 /** 594 * @see TradeServices#cancelOrder(Integer, boolean) 595 */ 596 public void cancelOrder(Integer orderID, boolean twoPhase) 597 throws Exception 598 { 599 OrderDataBean orderData = null; 600 Connection conn=null; 601 try 602 { 603 if (Log.doTrace()) Log.trace("TradeDirect:cancelOrder - inSession(" + this.inSession + ")", orderID); 604 setInGlobalTxn(!inSession && twoPhase); 605 conn = getConn(); 606 cancelOrder(conn, orderID); 607 commit(conn); 608 609 } 610 catch (Exception e) 611 { 612 Log.error("TradeDirect:cancelOrder -- error cancelling order: "+orderID, e); 613 rollBack(conn, e); 614 } 615 finally 616 { 617 releaseConn(conn); 618 } 619 } 620 public void cancelOrderOnePhase(Integer orderID) 621 throws Exception 622 { 623 OrderDataBean orderData = null; 624 Connection conn=null; 625 try 626 { 627 if (Log.doTrace()) Log.trace("TradeDirect:cancelOrderOnePhase - inSession(" + this.inSession + ")", orderID); 628 setInGlobalTxn(false); 629 conn = getConn(); 630 cancelOrder(conn, orderID); 631 commit(conn); 632 633 } 634 catch (Exception e) 635 { 636 Log.error("TradeDirect:cancelOrderOnePhase -- error cancelling order: "+orderID, e); 637 rollBack(conn, e); 638 } 639 finally 640 { 641 releaseConn(conn); 642 } 643 } 644 private void cancelOrder(Connection conn, Integer orderID) 645 throws Exception 646 { 647 updateOrderStatus(conn, orderID, "cancelled"); 648 } 649 650 651 public void orderCompleted(String userID, Integer orderID) 652 throws Exception 653 { 654 throw new UnsupportedOperationException("TradeDirect:orderCompleted method not supported"); 655 } 656 657 658 private HoldingDataBean createHolding(Connection conn, int accountID, String symbol, double quantity, BigDecimal purchasePrice) 659 throws Exception 660 { 661 HoldingDataBean holdingData = null; 662 663 Timestamp purchaseDate = new Timestamp(System.currentTimeMillis()); 664 PreparedStatement stmt = getStatement(conn, createHoldingSQL); 665 666 Integer holdingID = KeySequenceDirect.getNextID(conn, "holding", inSession, getInGlobalTxn()); 667 stmt.setInt(1, holdingID.intValue()); 668 stmt.setTimestamp(2, purchaseDate); 669 stmt.setBigDecimal(3, purchasePrice); 670 stmt.setDouble(4, quantity); 671 stmt.setString(5, symbol); 672 stmt.setInt(6, accountID); 673 int rowCount = stmt.executeUpdate(); 674 675 stmt.close(); 676 677 return getHoldingData(conn, holdingID.intValue()); 678 } 679 private void removeHolding(Connection conn, int holdingID, int orderID) 680 throws Exception 681 { 682 PreparedStatement stmt = getStatement(conn, removeHoldingSQL); 683 684 stmt.setInt(1, holdingID); 685 int rowCount = stmt.executeUpdate(); 686 stmt.close(); 687 688 // set the HoldingID to NULL for the purchase and sell order now that 689 // the holding as been removed 690 stmt = getStatement(conn, removeHoldingFromOrderSQL); 691 692 stmt.setInt(1, holdingID); 693 rowCount = stmt.executeUpdate(); 694 stmt.close(); 695 696 } 697 698 private OrderDataBean createOrder(Connection conn, AccountDataBean accountData, QuoteDataBean quoteData, HoldingDataBean holdingData, String orderType, double quantity) 699 throws Exception 700 { 701 OrderDataBean orderData = null; 702 703 Timestamp currentDate = new Timestamp(System.currentTimeMillis()); 704 705 PreparedStatement stmt = getStatement(conn, createOrderSQL); 706 707 708 Integer orderID = KeySequenceDirect.getNextID(conn, "order", inSession, getInGlobalTxn()); 709 stmt.setInt(1, orderID.intValue()); 710 stmt.setString(2, orderType); 711 stmt.setString(3, "open"); 712 stmt.setTimestamp(4, currentDate); 713 stmt.setDouble(5, quantity); 714 stmt.setBigDecimal(6, quoteData.getPrice().setScale(FinancialUtils.SCALE, FinancialUtils.ROUND)); 715 stmt.setBigDecimal(7, TradeConfig.getOrderFee(orderType)); 716 stmt.setInt(8, accountData.getAccountID().intValue()); 717 if (holdingData == null ) stmt.setNull(9, java.sql.Types.INTEGER); 718 else stmt.setInt(9, holdingData.getHoldingID().intValue()); 719 stmt.setString(10, quoteData.getSymbol()); 720 int rowCount = stmt.executeUpdate(); 721 722 stmt.close(); 723 724 return getOrderData(conn, orderID.intValue()); 725 } 726 727 728 /** 729 * @see TradeServices#getOrders(String) 730 */ 731 public Collection getOrders(String userID) throws Exception { 732 Collection orderDataBeans = new ArrayList(); 733 Connection conn=null; 734 try 735 { 736 if (Log.doTrace()) Log.trace("TradeDirect:getOrders - inSession(" + this.inSession + ")", userID); 737 738 conn = getConn(); 739 PreparedStatement stmt = getStatement(conn, getOrdersByUserSQL); 740 stmt.setString(1, userID); 741 742 ResultSet rs = stmt.executeQuery(); 743 744 //TODO: return top 5 orders for now -- next version will add a getAllOrders method 745 // also need to get orders sorted by order id descending 746 int i=0; 747 while ( (rs.next()) && (i++ < 5) ) 748 { 749 OrderDataBean orderData = getOrderDataFromResultSet(rs); 750 orderDataBeans.add(orderData); 751 } 752 753 stmt.close(); 754 commit(conn); 755 756 } 757 catch (Exception e) 758 { 759 Log.error("TradeDirect:getOrders -- error getting user orders", e); 760 rollBack(conn, e); 761 } 762 finally 763 { 764 releaseConn(conn); 765 } 766 return orderDataBeans; 767 } 768 769 /** 770 * @see TradeServices#getClosedOrders(String) 771 */ 772 public Collection getClosedOrders(String userID) throws Exception { 773 Collection orderDataBeans = new ArrayList(); 774 Connection conn=null; 775 try 776 { 777 if (Log.doTrace()) Log.trace("TradeDirect:getClosedOrders - inSession(" + this.inSession + ")", userID); 778 779 conn = getConn(); 780 PreparedStatement stmt = getStatement(conn, getClosedOrdersSQL); 781 stmt.setString(1, userID); 782 783 ResultSet rs = stmt.executeQuery(); 784 785 while ( rs.next() ) 786 { 787 OrderDataBean orderData = getOrderDataFromResultSet(rs); 788 orderData.setOrderStatus("completed"); 789 updateOrderStatus(conn, orderData.getOrderID(), orderData.getOrderStatus()); 790 orderDataBeans.add(orderData); 791 792 } 793 794 stmt.close(); 795 commit(conn); 796 } 797 catch (Exception e) 798 { 799 Log.error("TradeDirect:getOrders -- error getting user orders", e); 800 rollBack(conn, e); 801 } 802 finally 803 { 804 releaseConn(conn); 805 } 806 return orderDataBeans; 807 } 808 809 /** 810 * @see TradeServices#createQuote(String, String, BigDecimal) 811 */ 812 public QuoteDataBean createQuote( 813 String symbol, 814 String companyName, 815 BigDecimal price) 816 throws Exception { 817 818 QuoteDataBean quoteData = null; 819 Connection conn=null; 820 try 821 { 822 if (Log.doTrace()) Log.traceEnter("TradeDirect:createQuote - inSession(" + this.inSession + ")"); 823 824 price = price.setScale(FinancialUtils.SCALE, FinancialUtils.ROUND); 825 double volume=0.0, change=0.0; 826 827 conn = getConn(); 828 PreparedStatement stmt = getStatement(conn, createQuoteSQL); 829 stmt.setString(1, symbol); // symbol 830 stmt.setString(2, companyName); // companyName 831 stmt.setDouble(3, volume); // volume 832 stmt.setBigDecimal(4, price); // price 833 stmt.setBigDecimal(5, price); // open 834 stmt.setBigDecimal(6, price); // low 835 stmt.setBigDecimal(7, price); // high 836 stmt.setDouble(8, change); // change 837 838 stmt.executeUpdate(); 839 stmt.close(); 840 commit(conn); 841 842 quoteData = new QuoteDataBean(symbol, companyName, volume, price, price, price, price, change); 843 if (Log.doTrace()) Log.traceExit("TradeDirect:createQuote"); 844 } 845 catch (Exception e) 846 { 847 Log.error("TradeDirect:createQuote -- error creating quote", e); 848 } 849 finally 850 { 851 releaseConn(conn); 852 } 853 return quoteData; 854 } 855 856 /** 857 * @see TradeServices#getQuote(String) 858 */ 859 860 public QuoteDataBean getQuote(String symbol) throws Exception { 861 QuoteDataBean quoteData = null; 862 Connection conn=null; 863 UserTransaction txn = null; 864 try 865 { 866 if (Log.doTrace()) Log.trace("TradeDirect:getQuote - inSession(" + this.inSession + ")", symbol); 867 868 conn = getConn(); 869 quoteData = getQuote(conn, symbol); 870 commit(conn); 871 } 872 catch (Exception e) 873 { 874 Log.error("TradeDirect:getQuote -- error getting quote", e); 875 rollBack(conn, e); 876 } 877 finally 878 { 879 releaseConn(conn); 880 } 881 return quoteData; 882 } 883 884 private QuoteDataBean getQuote(Connection conn, String symbol) 885 throws Exception 886 { 887 QuoteDataBean quoteData = null; 888 PreparedStatement stmt = getStatement(conn, getQuoteSQL); 889 stmt.setString(1, symbol); // symbol 890 891 ResultSet rs = stmt.executeQuery(); 892 893 if ( !rs.next() ) 894 Log.error("TradeDirect:getQuote -- failure no result.next() for symbol: " + symbol); 895 896 else 897 quoteData = getQuoteDataFromResultSet(rs); 898 899 stmt.close(); 900 901 return quoteData; 902 } 903 904 private QuoteDataBean getQuoteForUpdate(Connection conn, String symbol) 905 throws Exception 906 { 907 QuoteDataBean quoteData = null; 908 PreparedStatement stmt = getStatement(conn, getQuoteForUpdateSQL); 909 stmt.setString(1, symbol); // symbol 910 911 ResultSet rs = stmt.executeQuery(); 912 913 if ( !rs.next() ) 914 Log.error("TradeDirect:getQuote -- failure no result.next()"); 915 916 else 917 quoteData = getQuoteDataFromResultSet(rs); 918 919 stmt.close(); 920 921 return quoteData; 922 } 923 924 /** 925 * @see TradeServices#getAllQuotes(String) 926 */ 927 public Collection getAllQuotes() throws Exception { 928 Collection quotes = new ArrayList(); 929 QuoteDataBean quoteData = null; 930 931 Connection conn = null; 932 try { 933 conn = getConn(); 934 935 PreparedStatement stmt = getStatement(conn, getAllQuotesSQL); 936 937 ResultSet rs = stmt.executeQuery(); 938 939 while (!rs.next()) { 940 quoteData = getQuoteDataFromResultSet(rs); 941 quotes.add(quoteData); 942 } 943 944 stmt.close(); 945 } 946 catch (Exception e) { 947 Log.error("TradeDirect:getAllQuotes", e); 948 rollBack(conn, e); 949 } 950 finally { 951 releaseConn(conn); 952 } 953 954 return quotes; 955 } 956 957 /** 958 * @see TradeServices#getHoldings(String) 959 */ 960 public Collection getHoldings(String userID) throws Exception { 961 Collection holdingDataBeans = new ArrayList(); 962 Connection conn=null; 963 try 964 { 965 if (Log.doTrace()) Log.trace("TradeDirect:getHoldings - inSession(" + this.inSession + ")", userID); 966 967 conn = getConn(); 968 PreparedStatement stmt = getStatement(conn, getHoldingsForUserSQL); 969 stmt.setString(1, userID); 970 971 ResultSet rs = stmt.executeQuery(); 972 973 while ( rs.next() ) 974 { 975 HoldingDataBean holdingData = getHoldingDataFromResultSet(rs); 976 holdingDataBeans.add(holdingData); 977 } 978 979 stmt.close(); 980 commit(conn); 981 982 } 983 catch (Exception e) 984 { 985 Log.error("TradeDirect:getHoldings -- error getting user holings", e); 986 rollBack(conn, e); 987 } 988 finally 989 { 990 releaseConn(conn); 991 } 992 return holdingDataBeans; 993 } 994 995 /** 996 * @see TradeServices#getHolding(Integer) 997 */ 998 public HoldingDataBean getHolding(Integer holdingID) throws Exception { 999 HoldingDataBean holdingData = null; 1000 Connection conn=null; 1001 try 1002 { 1003 if (Log.doTrace()) Log.trace("TradeDirect:getHolding - inSession(" + this.inSession + ")", holdingID); 1004 1005 conn = getConn(); 1006 holdingData = getHoldingData(holdingID.intValue()); 1007 1008 commit(conn); 1009 1010 } 1011 catch (Exception e) 1012 { 1013 Log.error("TradeDirect:getHolding -- error getting holding " + holdingID + "", e); 1014 rollBack(conn, e); 1015 } 1016 finally 1017 { 1018 releaseConn(conn); 1019 } 1020 return holdingData; 1021 } 1022 1023 /** 1024 * @see TradeServices#getAccountData(String) 1025 */ 1026 public AccountDataBean getAccountData(String userID) 1027 throws RemoteException 1028 { 1029 try{ 1030 AccountDataBean accountData = null; 1031 Connection conn=null; 1032 try 1033 { 1034 if (Log.doTrace()) Log.trace("TradeDirect:getAccountData - inSession(" + this.inSession + ")", userID); 1035 1036 conn = getConn(); 1037 accountData = getAccountData(conn, userID); 1038 commit(conn); 1039 1040 } 1041 catch (Exception e) 1042 { 1043 Log.error("TradeDirect:getAccountData -- error getting account data", e); 1044 rollBack(conn, e); 1045 } 1046 finally 1047 { 1048 releaseConn(conn); 1049 } 1050 return accountData; 1051 }catch (Exception e){ 1052 throw new RemoteException(e.getMessage(),e); 1053 } 1054 } 1055 private AccountDataBean getAccountData(Connection conn, String userID) 1056 throws Exception 1057 { 1058 PreparedStatement stmt = getStatement(conn, getAccountForUserSQL); 1059 stmt.setString(1, userID); 1060 ResultSet rs = stmt.executeQuery(); 1061 AccountDataBean accountData = getAccountDataFromResultSet(rs); 1062 stmt.close(); 1063 return accountData; 1064 } 1065 1066 private AccountDataBean getAccountDataForUpdate(Connection conn, String userID) 1067 throws Exception 1068 { 1069 PreparedStatement stmt = getStatement(conn, getAccountForUserForUpdateSQL); 1070 stmt.setString(1, userID); 1071 ResultSet rs = stmt.executeQuery(); 1072 AccountDataBean accountData = getAccountDataFromResultSet(rs); 1073 stmt.close(); 1074 return accountData; 1075 } 1076 /** 1077 * @see TradeServices#getAccountData(String) 1078 */ 1079 public AccountDataBean getAccountData(int accountID) 1080 throws Exception 1081 { 1082 AccountDataBean accountData = null; 1083 Connection conn=null; 1084 try 1085 { 1086 if (Log.doTrace()) Log.trace("TradeDirect:getAccountData - inSession(" + this.inSession + ")", new Integer(accountID)); 1087 1088 conn = getConn(); 1089 accountData = getAccountData(accountID, conn); 1090 commit(conn); 1091 1092 } 1093 catch (Exception e) 1094 { 1095 Log.error("TradeDirect:getAccountData -- error getting account data", e); 1096 rollBack(conn, e); 1097 } 1098 finally 1099 { 1100 releaseConn(conn); 1101 } 1102 return accountData; 1103 } 1104 private AccountDataBean getAccountData(int accountID, Connection conn) 1105 throws Exception 1106 { 1107 PreparedStatement stmt = getStatement(conn, getAccountSQL); 1108 stmt.setInt(1, accountID); 1109 ResultSet rs = stmt.executeQuery(); 1110 AccountDataBean accountData = getAccountDataFromResultSet(rs); 1111 stmt.close(); 1112 return accountData; 1113 } 1114 private AccountDataBean getAccountDataForUpdate(int accountID, Connection conn) 1115 throws Exception 1116 { 1117 PreparedStatement stmt = getStatement(conn, getAccountForUpdateSQL); 1118 stmt.setInt(1, accountID); 1119 ResultSet rs = stmt.executeQuery(); 1120 AccountDataBean accountData = getAccountDataFromResultSet(rs); 1121 stmt.close(); 1122 return accountData; 1123 } 1124 1125 private QuoteDataBean getQuoteData(String symbol) 1126 throws Exception 1127 { 1128 QuoteDataBean quoteData = null; 1129 Connection conn=null; 1130 try 1131 { 1132 conn = getConn(); 1133 quoteData = getQuoteData(conn, symbol); 1134 commit(conn); 1135 } 1136 catch (Exception e) 1137 { 1138 Log.error("TradeDirect:getQuoteData -- error getting data", e); 1139 rollBack(conn, e); 1140 } 1141 finally 1142 { 1143 releaseConn(conn); 1144 } 1145 return quoteData; 1146 } 1147 private QuoteDataBean getQuoteData(Connection conn, String symbol) 1148 throws Exception 1149 { 1150 QuoteDataBean quoteData = null; 1151 PreparedStatement stmt = getStatement(conn, getQuoteSQL); 1152 stmt.setString(1, symbol); 1153 ResultSet rs = stmt.executeQuery(); 1154 if (!rs.next()) 1155 Log.error("TradeDirect:getQuoteData -- could not find quote for symbol="+symbol); 1156 else 1157 quoteData = getQuoteDataFromResultSet(rs); 1158 stmt.close(); 1159 return quoteData; 1160 } 1161 1162 private HoldingDataBean getHoldingData(int holdingID) 1163 throws Exception 1164 { 1165 HoldingDataBean holdingData = null; 1166 Connection conn=null; 1167 try 1168 { 1169 conn = getConn(); 1170 holdingData = getHoldingData(conn, holdingID); 1171 commit(conn); 1172 } 1173 catch (Exception e) 1174 { 1175 Log.error("TradeDirect:getHoldingData -- error getting data", e); 1176 rollBack(conn, e); 1177 } 1178 finally 1179 { 1180 releaseConn(conn); 1181 } 1182 return holdingData; 1183 } 1184 private HoldingDataBean getHoldingData(Connection conn, int holdingID) 1185 throws Exception 1186 { 1187 HoldingDataBean holdingData = null; 1188 PreparedStatement stmt = getStatement(conn, getHoldingSQL); 1189 stmt.setInt(1, holdingID); 1190 ResultSet rs = stmt.executeQuery(); 1191 if (!rs.next()) 1192 Log.error("TradeDirect:getHoldingData -- no results -- holdingID="+holdingID); 1193 else 1194 holdingData = getHoldingDataFromResultSet(rs); 1195 1196 stmt.close(); 1197 return holdingData; 1198 } 1199 1200 private OrderDataBean getOrderData(int orderID) 1201 throws Exception 1202 { 1203 OrderDataBean orderData = null; 1204 Connection conn=null; 1205 try 1206 { 1207 conn = getConn(); 1208 orderData = getOrderData(conn, orderID); 1209 commit(conn); 1210 } 1211 catch (Exception e) 1212 { 1213 Log.error("TradeDirect:getOrderData -- error getting data", e); 1214 rollBack(conn, e); 1215 } 1216 finally 1217 { 1218 releaseConn(conn); 1219 } 1220 return orderData; 1221 } 1222 private OrderDataBean getOrderData(Connection conn, int orderID) 1223 throws Exception 1224 { 1225 OrderDataBean orderData = null; 1226 if (Log.doTrace()) Log.trace("TradeDirect:getOrderData(conn, " + orderID + ")"); 1227 PreparedStatement stmt = getStatement(conn, getOrderSQL); 1228 stmt.setInt(1, orderID); 1229 ResultSet rs = stmt.executeQuery(); 1230 if (!rs.next()) 1231 Log.error("TradeDirect:getOrderData -- no results for orderID:" + orderID); 1232 else 1233 orderData = getOrderDataFromResultSet(rs); 1234 stmt.close(); 1235 return orderData; 1236 } 1237 1238 1239 /** 1240 * @see TradeServices#getAccountProfileData(String) 1241 */ 1242 public AccountProfileDataBean getAccountProfileData(String userID) 1243 throws Exception 1244 { 1245 AccountProfileDataBean accountProfileData = null; 1246 Connection conn=null; 1247 1248 try 1249 { 1250 if (Log.doTrace()) Log.trace("TradeDirect:getAccountProfileData - inSession(" + this.inSession + ")", userID); 1251 1252 conn = getConn(); 1253 accountProfileData = getAccountProfileData(conn, userID); 1254 commit(conn); 1255 } 1256 catch (Exception e) 1257 { 1258 Log.error("TradeDirect:getAccountProfileData -- error getting profile data", e); 1259 rollBack(conn, e); 1260 } 1261 finally 1262 { 1263 releaseConn(conn); 1264 } 1265 return accountProfileData; 1266 } 1267 private AccountProfileDataBean getAccountProfileData(Connection conn, String userID) 1268 throws Exception 1269 { 1270 PreparedStatement stmt = getStatement(conn, getAccountProfileSQL); 1271 stmt.setString(1, userID); 1272 1273 ResultSet rs = stmt.executeQuery(); 1274 1275 AccountProfileDataBean accountProfileData = getAccountProfileDataFromResultSet(rs); 1276 stmt.close(); 1277 return accountProfileData; 1278 } 1279 1280 1281 private AccountProfileDataBean getAccountProfileData(Integer accountID) 1282 throws Exception 1283 { 1284 AccountProfileDataBean accountProfileData = null; 1285 Connection conn=null; 1286 1287 try 1288 { 1289 if (Log.doTrace()) Log.trace("TradeDirect:getAccountProfileData", accountID); 1290 1291 conn = getConn(); 1292 accountProfileData = getAccountProfileData(conn, accountID); 1293 commit(conn); 1294 } 1295 catch (Exception e) 1296 { 1297 Log.error("TradeDirect:getAccountProfileData -- error getting profile data", e); 1298 rollBack(conn, e); 1299 } 1300 finally 1301 { 1302 releaseConn(conn); 1303 } 1304 return accountProfileData; 1305 } 1306 private AccountProfileDataBean getAccountProfileData(Connection conn, Integer accountID) 1307 throws Exception 1308 { 1309 PreparedStatement stmt = getStatement(conn, getAccountProfileForAccountSQL); 1310 stmt.setInt(1, accountID.intValue()); 1311 1312 ResultSet rs = stmt.executeQuery(); 1313 1314 AccountProfileDataBean accountProfileData = getAccountProfileDataFromResultSet(rs); 1315 stmt.close(); 1316 return accountProfileData; 1317 } 1318 1319 1320 /** 1321 * @see TradeServices#updateAccountProfile(AccountProfileDataBean) 1322 */ 1323 public AccountProfileDataBean updateAccountProfile(AccountProfileDataBean profileData) 1324 throws Exception { 1325 AccountProfileDataBean accountProfileData = null; 1326 Connection conn=null; 1327 1328 try 1329 { 1330 if (Log.doTrace()) Log.trace("TradeDirect:updateAccountProfileData - inSession(" + this.inSession + ")", profileData.getUserID()); 1331 1332 conn = getConn(); 1333 updateAccountProfile(conn, profileData); 1334 1335 accountProfileData = getAccountProfileData(conn, profileData.getUserID()); 1336 commit(conn); 1337 } 1338 catch (Exception e) 1339 { 1340 Log.error("TradeDirect:getAccountProfileData -- error getting profile data", e); 1341 rollBack(conn, e); 1342 } 1343 finally 1344 { 1345 releaseConn(conn); 1346 } 1347 return accountProfileData; 1348 } 1349 1350 private void creditAccountBalance(Connection conn, AccountDataBean accountData, BigDecimal credit) 1351 throws Exception 1352 { 1353 PreparedStatement stmt = getStatement(conn, creditAccountBalanceSQL); 1354 1355 stmt.setBigDecimal(1, credit); 1356 stmt.setInt(2, accountData.getAccountID().intValue()); 1357 1358 int count = stmt.executeUpdate(); 1359 stmt.close(); 1360 1361 } 1362 1363 1364 // Set Timestamp to zero to denote sell is inflight 1365 // UPDATE -- could add a "status" attribute to holding 1366 private void updateHoldingStatus(Connection conn, Integer holdingID, String symbol) 1367 throws Exception 1368 { 1369 Timestamp ts = new Timestamp(0); 1370 PreparedStatement stmt = getStatement(conn, "update holdingejb set purchasedate= ? where holdingid = ?"); 1371 1372 stmt.setTimestamp(1, ts); 1373 stmt.setInt(2, holdingID.intValue()); 1374 int count = stmt.executeUpdate(); 1375 stmt.close(); 1376 } 1377 1378 private void updateOrderStatus(Connection conn, Integer orderID, String status) 1379 throws Exception 1380 { 1381 PreparedStatement stmt = getStatement(conn, updateOrderStatusSQL); 1382 1383 stmt.setString(1, status); 1384 stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis())); 1385 stmt.setInt(3, orderID.intValue()); 1386 int count = stmt.executeUpdate(); 1387 stmt.close(); 1388 } 1389 1390 private void updateOrderHolding(Connection conn, int orderID, int holdingID) 1391 throws Exception 1392 { 1393 PreparedStatement stmt = getStatement(conn, updateOrderHoldingSQL); 1394 1395 stmt.setInt(1, holdingID); 1396 stmt.setInt(2, orderID); 1397 int count = stmt.executeUpdate(); 1398 stmt.close(); 1399 } 1400 1401 private void updateAccountProfile(Connection conn, AccountProfileDataBean profileData) 1402 throws Exception 1403 { 1404 PreparedStatement stmt = getStatement(conn, updateAccountProfileSQL); 1405 1406 stmt.setString(1, profileData.getPassword()); 1407 stmt.setString(2, profileData.getFullName()); 1408 stmt.setString(3, profileData.getAddress()); 1409 stmt.setString(4, profileData.getEmail()); 1410 stmt.setString(5, profileData.getCreditCard()); 1411 stmt.setString(6, profileData.getUserID()); 1412 1413 int count = stmt.executeUpdate(); 1414 stmt.close(); 1415 } 1416 1417 private void updateQuoteVolume(Connection conn, QuoteDataBean quoteData, double quantity) 1418 throws Exception 1419 { 1420 PreparedStatement stmt = getStatement(conn, updateQuoteVolumeSQL); 1421 1422 stmt.setDouble(1, quantity); 1423 stmt.setString(2, quoteData.getSymbol()); 1424 1425 int count = stmt.executeUpdate(); 1426 stmt.close(); 1427 } 1428 1429 public QuoteDataBean updateQuotePriceVolume(String symbol, BigDecimal changeFactor, double sharesTraded) throws Exception { 1430 return updateQuotePriceVolumeInt(symbol, changeFactor, sharesTraded, publishQuotePriceChange); 1431 } 1432 1433 /** 1434 * Update a quote's price and volume 1435 * @param symbol The PK of the quote 1436 * @param changeFactor the percent to change the old price by (between 50% and 150%) 1437 * @param sharedTraded the ammount to add to the current volume 1438 * @param publishQuotePriceChange used by the PingJDBCWrite Primitive to ensure no JMS is used, should 1439 * be true for all normal calls to this API 1440 */ 1441 public QuoteDataBean updateQuotePriceVolumeInt(String symbol, BigDecimal changeFactor, double sharesTraded, boolean publishQuotePriceChange) 1442 throws Exception 1443 { 1444 1445 if ( TradeConfig.getUpdateQuotePrices() == false ) 1446 return new QuoteDataBean(); 1447 1448 QuoteDataBean quoteData = null; 1449 Connection conn=null; 1450 UserTransaction txn = null; 1451 try 1452 { 1453 if (Log.doTrace()) Log.trace("TradeDirect:updateQuotePriceVolume - inSession(" + this.inSession + ")", symbol, changeFactor, new Double(sharesTraded)); 1454 1455 conn = getConn(); 1456 1457 quoteData = getQuoteForUpdate(conn, symbol); 1458 BigDecimal oldPrice = quoteData.getPrice(); 1459 double newVolume = quoteData.getVolume() + sharesTraded; 1460 1461 if (oldPrice.equals(TradeConfig.PENNY_STOCK_PRICE)) { 1462 changeFactor = TradeConfig.PENNY_STOCK_RECOVERY_MIRACLE_MULTIPLIER; 1463 } 1464 1465 BigDecimal newPrice = changeFactor.multiply(oldPrice).setScale(2, BigDecimal.ROUND_HALF_UP); 1466 1467 updateQuotePriceVolume(conn, quoteData.getSymbol(), newPrice, newVolume); 1468 quoteData = getQuote(conn, symbol); 1469 1470 commit(conn); 1471 1472 if (publishQuotePriceChange) { 1473 publishQuotePriceChange(quoteData, oldPrice, changeFactor, sharesTraded); 1474 } 1475 1476 } 1477 catch (Exception e) 1478 { 1479 Log.error("TradeDirect:updateQuotePriceVolume -- error updating quote price/volume for symbol:" + symbol); 1480 rollBack(conn, e); 1481 throw e; 1482 } 1483 finally 1484 { 1485 releaseConn(conn); 1486 } 1487 return quoteData; 1488 } 1489 1490 private void updateQuotePriceVolume(Connection conn, String symbol, BigDecimal newPrice, double newVolume) 1491 throws Exception 1492 { 1493 1494 PreparedStatement stmt = getStatement(conn, updateQuotePriceVolumeSQL); 1495 1496 stmt.setBigDecimal(1, newPrice); 1497 stmt.setBigDecimal(2, newPrice); 1498 stmt.setDouble(3, newVolume); 1499 stmt.setString(4, symbol); 1500 1501 int count = stmt.executeUpdate(); 1502 stmt.close(); 1503 } 1504 private void publishQuotePriceChange(QuoteDataBean quoteData, BigDecimal oldPrice, BigDecimal changeFactor, double sharesTraded) 1505 throws Exception 1506 { 1507 if (Log.doTrace()) 1508 Log.trace("TradeDirect:publishQuotePrice PUBLISHING to MDB quoteData = " + quoteData); 1509 1510 javax.jms.Connection conn = null; 1511 Session sess = null; 1512 1513 try 1514 { 1515 conn = tConnFactory.createConnection(); 1516 sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); 1517 MessageProducer producer = sess.createProducer(streamerTopic); 1518 TextMessage message = sess.createTextMessage(); 1519 1520 String command = "updateQuote"; 1521 message.setStringProperty("command", command); 1522 message.setStringProperty("symbol", quoteData.getSymbol() ); 1523 message.setStringProperty("company", quoteData.getCompanyName() ); 1524 message.setStringProperty("price", quoteData.getPrice().toString()); 1525 message.setStringProperty("oldPrice",oldPrice.toString()); 1526 message.setStringProperty("open", quoteData.getOpen().toString()); 1527 message.setStringProperty("low", quoteData.getLow().toString()); 1528 message.setStringProperty("high", quoteData.getHigh().toString()); 1529 message.setDoubleProperty("volume", quoteData.getVolume()); 1530 1531 message.setStringProperty("changeFactor", changeFactor.toString()); 1532 message.setDoubleProperty("sharesTraded", sharesTraded); 1533 message.setLongProperty("publishTime", System.currentTimeMillis()); 1534 message.setText("Update Stock price for " + quoteData.getSymbol() + " old price = " + oldPrice + " new price = " + quoteData.getPrice()); 1535 1536 producer.send(message); 1537 } 1538 catch (Exception e) 1539 { 1540 throw e; //pass exception back 1541 1542 } 1543 1544 finally 1545 { 1546 if (conn != null) 1547 conn.close(); 1548 if (sess != null) 1549 sess.close(); 1550 } 1551 } 1552 1553 1554 /** 1555 * @see TradeServices#login(String, String) 1556 */ 1557 1558 public AccountDataBean login(String userID, String password) 1559 throws Exception { 1560 1561 AccountDataBean accountData = null; 1562 Connection conn=null; 1563 try 1564 { 1565 if (Log.doTrace()) Log.trace("TradeDirect:login - inSession(" + this.inSession + ")", userID, password); 1566 1567 conn = getConn(); 1568 PreparedStatement stmt = getStatement(conn, getAccountProfileSQL); 1569 stmt.setString(1, userID); 1570 1571 ResultSet rs = stmt.executeQuery(); 1572 if ( !rs.next() ) 1573 { 1574 Log.error("TradeDirect:login -- failure to find account for" + userID); 1575 throw new javax.ejb.FinderException("Cannot find account for" + userID); 1576 } 1577 1578 String pw = rs.getString("passwd"); 1579 stmt.close(); 1580 if ( (pw==null) || (pw.equals(password) == false) ) 1581 { 1582 String error = "TradeDirect:Login failure for user: " + userID + 1583 "\n\tIncorrect password-->" + userID + ":" + password; 1584 Log.error(error); 1585 throw new Exception(error); 1586 } 1587 1588 stmt = getStatement(conn, loginSQL); 1589 stmt.setTimestamp(1, new Timestamp(System.currentTimeMillis())); 1590 stmt.setString(2, userID); 1591 1592 int rows = stmt.executeUpdate(); 1593 //?assert rows==1? 1594 stmt.close(); 1595 1596 stmt = getStatement(conn, getAccountForUserSQL); 1597 stmt.setString(1, userID); 1598 rs = stmt.executeQuery(); 1599 1600 accountData = getAccountDataFromResultSet(rs); 1601 1602 stmt.close(); 1603 1604 commit(conn); 1605 } 1606 catch (Exception e) 1607 { 1608 Log.error("TradeDirect:login -- error logging in user", e); 1609 rollBack(conn, e); 1610 } 1611 finally 1612 { 1613 releaseConn(conn); 1614 } 1615 return accountData; 1616 1617 /* 1618 setLastLogin( new Timestamp(System.currentTimeMillis()) ); 1619 setLoginCount( getLoginCount() + 1 ); 1620 */ 1621 } 1622 1623 /** 1624 * @see TradeServices#logout(String) 1625 */ 1626 public void logout(String userID) throws Exception { 1627 if (Log.doTrace()) Log.trace("TradeDirect:logout - inSession(" + this.inSession + ")", userID); 1628 Connection conn=null; 1629 try 1630 { 1631 conn = getConn(); 1632 PreparedStatement stmt = getStatement(conn, logoutSQL); 1633 stmt.setString(1, userID); 1634 stmt.executeUpdate(); 1635 stmt.close(); 1636 1637 commit(conn); 1638 } 1639 catch (Exception e) 1640 { 1641 Log.error("TradeDirect:logout -- error logging out user", e); 1642 rollBack(conn, e); 1643 } 1644 finally 1645 { 1646 releaseConn(conn); 1647 } 1648 } 1649 1650 /** 1651 * @see TradeServices#register(String, String, String, String, String, String, BigDecimal, boolean) 1652 */ 1653 1654 public AccountDataBean register( 1655 String userID, 1656 String password, 1657 String fullname, 1658 String address, 1659 String email, 1660 String creditcard, 1661 BigDecimal openBalance) 1662 throws Exception { 1663 1664 AccountDataBean accountData = null; 1665 Connection conn=null; 1666 try 1667 { 1668 if (Log.doTrace()) Log.traceEnter("TradeDirect:register - inSession(" + this.inSession + ")"); 1669 1670 conn = getConn(); 1671 PreparedStatement stmt = getStatement(conn, createAccountSQL); 1672 1673 Integer accountID = KeySequenceDirect.getNextID(conn, "account", inSession, getInGlobalTxn()); 1674 BigDecimal balance = openBalance; 1675 Timestamp creationDate = new Timestamp(System.currentTimeMillis()); 1676 Timestamp lastLogin = creationDate; 1677 int loginCount = 0; 1678 int logoutCount = 0; 1679 1680 stmt.setInt(1, accountID.intValue()); 1681 stmt.setTimestamp(2, creationDate); 1682 stmt.setBigDecimal(3, openBalance); 1683 stmt.setBigDecimal(4, balance); 1684 stmt.setTimestamp(5, lastLogin); 1685 stmt.setInt(6, loginCount); 1686 stmt.setInt(7, logoutCount); 1687 stmt.setString(8, userID); 1688 stmt.executeUpdate(); 1689 stmt.close(); 1690 1691 stmt = getStatement(conn, createAccountProfileSQL); 1692 stmt.setString(1, userID); 1693 stmt.setString(2, password); 1694 stmt.setString(3, fullname); 1695 stmt.setString(4, address); 1696 stmt.setString(5, email); 1697 stmt.setString(6, creditcard); 1698 stmt.executeUpdate(); 1699 stmt.close(); 1700 1701 commit(conn); 1702 1703 accountData = new AccountDataBean(accountID, loginCount, logoutCount, lastLogin, creationDate, balance, openBalance, userID); 1704 if (Log.doTrace()) Log.traceExit("TradeDirect:register"); 1705 } 1706 catch (Exception e) 1707 { 1708 Log.error("TradeDirect:register -- error registering new user", e); 1709 } 1710 finally 1711 { 1712 releaseConn(conn); 1713 } 1714 return accountData; 1715 } 1716 1717 private AccountDataBean getAccountDataFromResultSet(ResultSet rs) 1718 throws Exception 1719 { 1720 AccountDataBean accountData = null; 1721 1722 1723 if (!rs.next() ) 1724 Log.error("TradeDirect:getAccountDataFromResultSet -- cannot find account data"); 1725 1726 else 1727 accountData = new AccountDataBean( 1728 new Integer(rs.getInt("accountID")), 1729 rs.getInt("loginCount"), 1730 rs.getInt("logoutCount"), 1731 rs.getTimestamp("lastLogin"), 1732 rs.getTimestamp("creationDate"), 1733 rs.getBigDecimal("balance"), 1734 rs.getBigDecimal("openBalance"), 1735 rs.getString("profile_userID") 1736 ); 1737 return accountData; 1738 } 1739 1740 private AccountProfileDataBean getAccountProfileDataFromResultSet(ResultSet rs) 1741 throws Exception 1742 { 1743 AccountProfileDataBean accountProfileData = null; 1744 1745 if (!rs.next() ) 1746 Log.error("TradeDirect:getAccountProfileDataFromResultSet -- cannot find accountprofile data"); 1747 else 1748 accountProfileData = new AccountProfileDataBean( 1749 rs.getString("userID"), 1750 rs.getString("passwd"), 1751 rs.getString("fullName"), 1752 rs.getString("address"), 1753 rs.getString("email"), 1754 rs.getString("creditCard") 1755 ); 1756 1757 return accountProfileData; 1758 } 1759 1760 private HoldingDataBean getHoldingDataFromResultSet(ResultSet rs) 1761 throws Exception 1762 { 1763 HoldingDataBean holdingData = null; 1764 1765 holdingData = new HoldingDataBean( 1766 new Integer(rs.getInt("holdingID")), 1767 rs.getDouble("quantity"), 1768 rs.getBigDecimal("purchasePrice"), 1769 rs.getTimestamp("purchaseDate"), 1770 rs.getString("quote_symbol") 1771 ); 1772 return holdingData; 1773 } 1774 1775 private QuoteDataBean getQuoteDataFromResultSet(ResultSet rs) 1776 throws Exception 1777 { 1778 QuoteDataBean quoteData = null; 1779 1780 quoteData = new QuoteDataBean( 1781 rs.getString("symbol"), 1782 rs.getString("companyName"), 1783 rs.getDouble("volume"), 1784 rs.getBigDecimal("price"), 1785 rs.getBigDecimal("open1"), 1786 rs.getBigDecimal("low"), 1787 rs.getBigDecimal("high"), 1788 rs.getDouble("change1") 1789 ); 1790 return quoteData; 1791 } 1792 1793 private OrderDataBean getOrderDataFromResultSet(ResultSet rs) 1794 throws Exception 1795 { 1796 OrderDataBean orderData = null; 1797 1798 orderData = new OrderDataBean( 1799 new Integer(rs.getInt("orderID")), 1800 rs.getString("orderType"), 1801 rs.getString("orderStatus"), 1802 rs.getTimestamp("openDate"), 1803 rs.getTimestamp("completionDate"), 1804 rs.getDouble("quantity"), 1805 rs.getBigDecimal("price"), 1806 rs.getBigDecimal("orderFee"), 1807 rs.getString("quote_symbol") 1808 ); 1809 return orderData; 1810 } 1811 1812 public String checkDBProductName() throws Exception 1813 { 1814 Connection conn = null; 1815 String dbProductName = null; 1816 1817 try 1818 { 1819 if (Log.doTrace()) Log.traceEnter("TradeDirect:checkDBProductName"); 1820 1821 conn = getConn(); 1822 DatabaseMetaData dbmd = conn.getMetaData(); 1823 dbProductName = dbmd.getDatabaseProductName(); 1824 } 1825 catch (SQLException e) 1826 { 1827 Log.error(e,"TradeDirect:checkDBProductName() -- Error checking the Daytrader Database Product Name"); 1828 } 1829 finally 1830 { 1831 releaseConn(conn); 1832 } 1833 return dbProductName; 1834 } 1835 1836 public boolean recreateDBTables(Object[] sqlBuffer, java.io.PrintWriter out) throws Exception 1837 { 1838 //Clear MDB Statistics 1839 MDBStats.getInstance().reset(); 1840 1841 Connection conn = null; 1842 boolean success = false; 1843 try 1844 { 1845 if (Log.doTrace()) Log.traceEnter("TradeDirect:recreateDBTables"); 1846 1847 conn = getConn(); 1848 Statement stmt = conn.createStatement(); 1849 int bufferLength = sqlBuffer.length; 1850 for (int i = 0; i< bufferLength; i++) 1851 { 1852 try 1853 { 1854 stmt.executeUpdate((String)sqlBuffer[i]); 1855 //commit(conn); 1856 } 1857 catch(SQLException ex) 1858 { 1859 Log.error("TradeDirect:recreateDBTables SQL Exception thrown on executing the foll sql command: " + sqlBuffer[i], ex); 1860 out.println("<BR>SQL Exception thrown on executing the foll sql command: <I>" + sqlBuffer[i] + "</I> . Check log for details.</BR>"); 1861 } 1862 } 1863 stmt.close(); 1864 commit(conn); 1865 success = true; 1866 } 1867 catch (Exception e) 1868 { 1869 Log.error(e,"TradeDirect:recreateDBTables() -- Error dropping and recreating the database tables"); 1870 } 1871 finally 1872 { 1873 releaseConn(conn); 1874 } 1875 return success; 1876 } 1877 1878 public RunStatsDataBean resetTrade(boolean deleteAll) 1879 throws Exception 1880 { 1881 //Clear MDB Statistics 1882 MDBStats.getInstance().reset(); 1883 // Reset Trade 1884 1885 RunStatsDataBean runStatsData = new RunStatsDataBean(); 1886 Connection conn=null; 1887 try 1888 { 1889 if (Log.doTrace()) Log.traceEnter("TradeDirect:resetTrade deleteAll rows=" + deleteAll); 1890 1891 conn = getConn(); 1892 PreparedStatement stmt=null; 1893 ResultSet rs = null; 1894 1895 if (deleteAll) 1896 { 1897 try 1898 { 1899 stmt = getStatement(conn, "delete from quoteejb"); 1900 stmt.executeUpdate(); 1901 stmt.close(); 1902 stmt = getStatement(conn, "delete from accountejb"); 1903 stmt.executeUpdate(); 1904 stmt.close(); 1905 stmt = getStatement(conn, "delete from accountprofileejb"); 1906 stmt.executeUpdate(); 1907 stmt.close(); 1908 stmt = getStatement(conn, "delete from holdingejb"); 1909 stmt.executeUpdate(); 1910 stmt.close(); 1911 stmt = getStatement(conn, "delete from orderejb"); 1912 stmt.executeUpdate(); 1913 stmt.close(); 1914 // FUTURE: - DuplicateKeyException - For now, don't start at 1915 // zero as KeySequenceDirect and KeySequenceBean will still give out 1916 // the cached Block and then notice this change. Better solution is 1917 // to signal both classes to drop their cached blocks 1918 //stmt = getStatement(conn, "delete from keygenejb"); 1919 //stmt.executeUpdate(); 1920 //stmt.close(); 1921 commit(conn); 1922 } 1923 catch (Exception e) 1924 { 1925 Log.error(e,"TradeDirect:resetTrade(deleteAll) -- Error deleting Trade users and stock from the Trade database"); 1926 } 1927 return runStatsData; 1928 } 1929 1930 stmt = getStatement(conn, "delete from holdingejb where holdingejb.account_accountid is null"); 1931 int x = stmt.executeUpdate(); 1932 stmt.close(); 1933 1934 //Count and Delete newly registered users (users w/ id that start "ru:%": 1935 stmt = getStatement(conn, "delete from accountprofileejb where userid like 'ru:%'"); 1936 int rowCount = stmt.executeUpdate(); 1937 stmt.close(); 1938 1939 stmt = getStatement(conn, "delete from orderejb where account_accountid in (select accountid from accountejb a where a.profile_userid like 'ru:%')"); 1940 rowCount = stmt.executeUpdate(); 1941 stmt.close(); 1942 1943 stmt = getStatement(conn, "delete from holdingejb where account_accountid in (select accountid from accountejb a where a.profile_userid like 'ru:%')"); 1944 rowCount = stmt.executeUpdate(); 1945 stmt.close(); 1946 1947 stmt = getStatement(conn, "delete from accountejb where profile_userid like 'ru:%'"); 1948 int newUserCount = stmt.executeUpdate(); 1949 runStatsData.setNewUserCount(newUserCount); 1950 stmt.close(); 1951 1952 //Count of trade users 1953 stmt = getStatement(conn, "select count(accountid) as \"tradeUserCount\" from accountejb a where a.profile_userid like 'uid:%'"); 1954 rs = stmt.executeQuery(); 1955 rs.next(); 1956 int tradeUserCount = rs.getInt("tradeUserCount"); 1957 runStatsData.setTradeUserCount(tradeUserCount); 1958 stmt.close(); 1959 1960 rs.close(); 1961 //Count of trade stocks 1962 stmt = getStatement(conn, "select count(symbol) as \"tradeStockCount\" from quoteejb a where a.symbol like 's:%'"); 1963 rs = stmt.executeQuery(); 1964 rs.next(); 1965 int tradeStockCount = rs.getInt("tradeStockCount"); 1966 runStatsData.setTradeStockCount(tradeStockCount); 1967 stmt.close(); 1968 1969 1970 //Count of trade users login, logout 1971 stmt = getStatement(conn, "select sum(loginCount) as \"sumLoginCount\", sum(logoutCount) as \"sumLogoutCount\" from accountejb a where a.profile_userID like 'uid:%'"); 1972 rs = stmt.executeQuery(); 1973 rs.next(); 1974 int sumLoginCount = rs.getInt("sumLoginCount"); 1975 int sumLogoutCount = rs.getInt("sumLogoutCount"); 1976 runStatsData.setSumLoginCount(sumLoginCount); 1977 runStatsData.setSumLogoutCount(sumLogoutCount); 1978 stmt.close(); 1979 1980 rs.close(); 1981 //Update logoutcount and loginCount back to zero 1982 1983 stmt = getStatement(conn, "update accountejb set logoutCount=0,loginCount=0 where profile_userID like 'uid:%'"); 1984 rowCount = stmt.executeUpdate(); 1985 stmt.close(); 1986 1987 //count holdings for trade users 1988 stmt = getStatement(conn, "select count(holdingid) as \"holdingCount\" from holdingejb h where h.account_accountid in " 1989 + "(select accountid from accountejb a where a.profile_userid like 'uid:%')"); 1990 1991 rs = stmt.executeQuery(); 1992 rs.next(); 1993 int holdingCount = rs.getInt("holdingCount"); 1994 runStatsData.setHoldingCount(holdingCount); 1995 stmt.close(); 1996 rs.close(); 1997 1998 1999 //count orders for trade users 2000 stmt = getStatement(conn, "select count(orderid) as \"orderCount\" from orderejb o where o.account_accountid in " 2001 + "(select accountid from accountejb a where a.profile_userid like 'uid:%')"); 2002 2003 rs = stmt.executeQuery(); 2004 rs.next(); 2005 int orderCount = rs.getInt("orderCount"); 2006 runStatsData.setOrderCount(orderCount); 2007 stmt.close(); 2008 rs.close(); 2009 2010 //count orders by type for trade users 2011 stmt = getStatement(conn, "select count(orderid) \"buyOrderCount\"from orderejb o where (o.account_accountid in " 2012 + "(select accountid from accountejb a where a.profile_userid like 'uid:%')) AND " 2013 + " (o.orderType='buy')"); 2014 2015 rs = stmt.executeQuery(); 2016 rs.next(); 2017 int buyOrderCount = rs.getInt("buyOrderCount"); 2018 runStatsData.setBuyOrderCount(buyOrderCount); 2019 stmt.close(); 2020 rs.close(); 2021 2022 2023 //count orders by type for trade users 2024 stmt = getStatement(conn, "select count(orderid) \"sellOrderCount\"from orderejb o where (o.account_accountid in " 2025 + "(select accountid from accountejb a where a.profile_userid like 'uid:%')) AND " 2026 + " (o.orderType='sell')"); 2027 2028 rs = stmt.executeQuery(); 2029 rs.next(); 2030 int sellOrderCount = rs.getInt("sellOrderCount"); 2031 runStatsData.setSellOrderCount(sellOrderCount); 2032 stmt.close(); 2033 rs.close(); 2034 2035 2036 //Delete cancelled orders 2037 stmt = getStatement(conn, "delete from orderejb where orderStatus='cancelled'"); 2038 int cancelledOrderCount = stmt.executeUpdate(); 2039 runStatsData.setCancelledOrderCount(cancelledOrderCount); 2040 stmt.close(); 2041 rs.close(); 2042 2043 //count open orders by type for trade users 2044 stmt = getStatement(conn, "select count(orderid) \"openOrderCount\"from orderejb o where (o.account_accountid in " 2045 + "(select accountid from accountejb a where a.profile_userid like 'uid:%')) AND " 2046 + " (o.orderStatus='open')"); 2047 2048 rs = stmt.executeQuery(); 2049 rs.next(); 2050 int openOrderCount = rs.getInt("openOrderCount"); 2051 runStatsData.setOpenOrderCount(openOrderCount); 2052 2053 2054 stmt.close(); 2055 rs.close(); 2056 //Delete orders for holding which have been purchased and sold 2057 stmt = getStatement(conn, "delete from orderejb where holding_holdingid is null"); 2058 int deletedOrderCount = stmt.executeUpdate(); 2059 runStatsData.setDeletedOrderCount(deletedOrderCount); 2060 stmt.close(); 2061 rs.close(); 2062 2063 commit(conn); 2064 2065 System.out.println("TradeDirect:reset Run stats data\n\n" + runStatsData); 2066 } 2067 catch (Exception e) 2068 { 2069 Log.error(e, "Failed to reset Trade"); 2070 rollBack(conn, e); 2071 throw e; 2072 } 2073 finally 2074 { 2075 releaseConn(conn); 2076 } 2077 return runStatsData; 2078 2079 } 2080 2081 private void releaseConn(Connection conn) 2082 throws Exception 2083 { 2084 try 2085 { 2086 if ( conn!= null ) 2087 { 2088 conn.close(); 2089 if (Log.doTrace()) 2090 { 2091 synchronized(lock) 2092 { 2093 connCount--; 2094 } 2095 Log.trace("TradeDirect:releaseConn -- connection closed, connCount="+connCount); 2096 } 2097 } 2098 } 2099 catch (Exception e) 2100 { 2101 Log.error("TradeDirect:releaseConnection -- failed to close connection", e); 2102 } 2103 } 2104 2105 /* 2106 * Lookup the TradeData datasource 2107 * 2108 */ 2109 private void getDataSource() throws Exception 2110 { 2111 datasource = (DataSource) context.lookup(dsName); 2112 } 2113 2114 2115 /* 2116 * Allocate a new connection to the datasource 2117 * 2118 */ 2119 private static int connCount=0; 2120 private static Integer lock = new Integer(0); 2121 private Connection getConn() throws Exception 2122 { 2123 2124 Connection conn = null; 2125 if ( datasource == null ) 2126 getDataSource(); 2127 conn = datasource.getConnection(); 2128 conn.setAutoCommit(false); 2129 if (Log.doTrace()) 2130 { 2131 synchronized(lock) 2132 { 2133 connCount++; 2134 } 2135 Log.trace("TradeDirect:getConn -- new connection allocated, IsolationLevel=" + conn.getTransactionIsolation() + " connectionCount = " + connCount); 2136 } 2137 2138 return conn; 2139 } 2140 2141 /* 2142 * Commit the provided connection if not under Global Transaction scope 2143 * - conn.commit() is not allowed in a global transaction. the txn manager will 2144 * perform the commit 2145 */ 2146 private void commit(Connection conn) 2147 throws Exception 2148 { 2149 if (!inSession) { 2150 if ( (getInGlobalTxn()==false) && (conn != null) ) 2151 conn.commit(); 2152 } 2153 } 2154 2155 2156 /* 2157 * Rollback the statement for the given connection 2158 * 2159 */ 2160 private void rollBack(Connection conn, Exception e) 2161 throws Exception 2162 { 2163 if (!inSession) { 2164 Log.log("TradeDirect:rollBack -- rolling back conn due to previously caught exception -- inGlobalTxn=" + getInGlobalTxn()); 2165 if ( (getInGlobalTxn()==false) && (conn != null) ) 2166 conn.rollback(); 2167 else 2168 throw e; // Throw the exception 2169 // so the Global txn manager will rollBack 2170 } 2171 } 2172 2173 /* 2174 * Allocate a new prepared statment for this connection 2175 * 2176 */ 2177 private PreparedStatement getStatement(Connection conn, String sql) throws Exception { 2178 return conn.prepareStatement(sql); 2179 } 2180 private PreparedStatement getStatement(Connection conn, String sql, int type, int concurrency) throws Exception { 2181 return conn.prepareStatement(sql, type, concurrency ); 2182 } 2183 2184 2185 private static final String createQuoteSQL = 2186 "insert into quoteejb " + 2187 "( symbol, companyName, volume, price, open1, low, high, change1 ) " + 2188 "VALUES ( ? , ? , ? , ? , ? , ? , ? , ? )"; 2189 2190 private static final String createAccountSQL = 2191 "insert into accountejb " + 2192 "( accountid, creationDate, openBalance, balance, lastLogin, loginCount, logoutCount, profile_userid) " + 2193 "VALUES ( ? , ? , ? , ? , ? , ? , ? , ? )"; 2194 2195 private static final String createAccountProfileSQL = 2196 "insert into accountprofileejb " + 2197 "( userid, passwd, fullname, address, email, creditcard ) " + 2198 "VALUES ( ? , ? , ? , ? , ? , ? )"; 2199 2200 private static final String createHoldingSQL = 2201 "insert into holdingejb " + 2202 "( holdingid, purchaseDate, purchasePrice, quantity, quote_symbol, account_accountid ) " + 2203 "VALUES ( ? , ? , ? , ? , ? , ? )"; 2204 2205 private static final String createOrderSQL = 2206 "insert into orderejb " + 2207 "( orderid, ordertype, orderstatus, opendate, quantity, price, orderfee, account_accountid, holding_holdingid, quote_symbol) " + 2208 "VALUES ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ?)"; 2209 2210 private static final String removeHoldingSQL = 2211 "delete from holdingejb where holdingid = ?"; 2212 2213 private static final String removeHoldingFromOrderSQL = 2214 "update orderejb set holding_holdingid=null where holding_holdingid = ?"; 2215 2216 private final static String updateAccountProfileSQL = 2217 "update accountprofileejb set " + 2218 "passwd = ?, fullname = ?, address = ?, email = ?, creditcard = ? " + 2219 "where userid = (select profile_userid from accountejb a " + 2220 "where a.profile_userid=?)"; 2221 2222 private final static String loginSQL= 2223 "update accountejb set lastLogin=?, logincount=logincount+1 " + 2224 "where profile_userid=?"; 2225 2226 private static final String logoutSQL = 2227 "update accountejb set logoutcount=logoutcount+1 " + 2228 "where profile_userid=?"; 2229 2230 private static final String getAccountSQL = 2231 "select * from accountejb a where a.accountid = ?"; 2232 2233 private static final String getAccountForUpdateSQL = 2234 "select * from accountejb a where a.accountid = ? for update"; 2235 2236 private final static String getAccountProfileSQL = 2237 "select * from accountprofileejb ap where ap.userid = " + 2238 "(select profile_userid from accountejb a where a.profile_userid=?)"; 2239 2240 private final static String getAccountProfileForAccountSQL = 2241 "select * from accountprofileejb ap where ap.userid = " + 2242 "(select profile_userid from accountejb a where a.accountid=?)"; 2243 2244 private static final String getAccountForUserSQL = 2245 "select * from accountejb a where a.profile_userid = " + 2246 "( select userid from accountprofileejb ap where ap.userid = ?)"; 2247 2248 private static final String getAccountForUserForUpdateSQL = 2249 "select * from accountejb a where a.profile_userid = " + 2250 "( select userid from accountprofileejb ap where ap.userid = ?) for update"; 2251 2252 private static final String getHoldingSQL = 2253 "select * from holdingejb h where h.holdingid = ?"; 2254 2255 private static final String getHoldingsForUserSQL = 2256 "select * from holdingejb h where h.account_accountid = " + 2257 "(select a.accountid from accountejb a where a.profile_userid = ?)"; 2258 2259 private static final String getOrderSQL = 2260 "select * from orderejb o where o.orderid = ?"; 2261 2262 private static final String getOrdersByUserSQL = 2263 "select * from orderejb o where o.account_accountid = " + 2264 "(select a.accountid from accountejb a where a.profile_userid = ?)"; 2265 2266 private static final String getClosedOrdersSQL = 2267 "select * from orderejb o " + 2268 "where o.orderstatus = 'closed' AND o.account_accountid = " + 2269 "(select a.accountid from accountejb a where a.profile_userid = ?)"; 2270 2271 private static final String getQuoteSQL = 2272 "select * from quoteejb q where q.symbol=?"; 2273 2274 private static final String getAllQuotesSQL = 2275 "select * from quoteejb q"; 2276 2277 private static final String getQuoteForUpdateSQL = 2278 "select * from quoteejb q where q.symbol=? For Update"; 2279 2280 private static final String getTSIAQuotesOrderByChangeSQL = 2281 "select * from quoteejb q " + 2282 "where q.symbol like 's:1__' order by q.change1"; 2283 2284 private static final String getTSIASQL = 2285 "select SUM(price)/count(*) as TSIA from quoteejb q " + 2286 "where q.symbol like 's:1__'"; 2287 2288 private static final String getOpenTSIASQL = 2289 "select SUM(open1)/count(*) as openTSIA from quoteejb q " + 2290 "where q.symbol like 's:1__'"; 2291 2292 private static final String getTSIATotalVolumeSQL = 2293 "select SUM(volume) as totalVolume from quoteejb q " + 2294 "where q.symbol like 's:1__'"; 2295 2296 private static final String creditAccountBalanceSQL = 2297 "update accountejb set " + 2298 "balance = balance + ? " + 2299 "where accountid = ?"; 2300 2301 private static final String updateOrderStatusSQL = 2302 "update orderejb set " + 2303 "orderstatus = ?, completiondate = ? " + 2304 "where orderid = ?"; 2305 2306 private static final String updateOrderHoldingSQL = 2307 "update orderejb set " + 2308 "holding_holdingID = ? " + 2309 "where orderid = ?"; 2310 2311 private static final String updateQuoteVolumeSQL = 2312 "update quoteejb set " + 2313 "volume = volume + ? " + 2314 "where symbol = ?"; 2315 2316 private static final String updateQuotePriceVolumeSQL = 2317 "update quoteejb set " + 2318 "price = ?, change1 = ? - open1, volume = ? " + 2319 "where symbol = ?"; 2320 2321 2322 2323 2324 private static boolean initialized = false; 2325 public static synchronized void init() 2326 { 2327 TradeHome tradeHome=null; 2328 if (initialized) return; 2329 if (Log.doTrace()) 2330 Log.trace("TradeDirect:init -- *** initializing"); 2331 try 2332 { 2333 if (Log.doTrace()) 2334 Log.trace("TradeDirect: init"); 2335 context = new InitialContext(); 2336 datasource = (DataSource) context.lookup(dsName); 2337 } 2338 catch (Exception e) 2339 { 2340 Log.error("TradeDirect:init -- error on JNDI lookups of DataSource -- TradeDirect will not work", e); 2341 return; 2342 } 2343 2344 try { 2345 2346 tradeHome = (TradeHome) ( javax.rmi.PortableRemoteObject.narrow( 2347 context.lookup("java:comp/env/ejb/Trade"), TradeHome.class)); 2348 } 2349 catch (Exception e) 2350 { 2351 Log.error("TradeDirect:init -- error on JNDI lookup of Trade Session Bean -- TradeDirect will not work", e); 2352 return; 2353 } 2354 2355 try 2356 { 2357 qConnFactory = (ConnectionFactory) context.lookup("java:comp/env/jms/QueueConnectionFactory"); 2358 } 2359 catch (Exception e) 2360 { 2361 Log.error("TradeDirect:init Unable to locate QueueConnectionFactory.\n\t -- Asynchronous mode will not work correctly and Quote Price change publishing will be disabled"); 2362 publishQuotePriceChange = false; 2363 } 2364 2365 try 2366 { 2367 queue = (Queue) context.lookup("java:comp/env/jms/TradeBrokerQueue"); 2368 } 2369 catch (Exception e) 2370 { 2371 Log.error("TradeDirect:init Unable to locate TradeBrokerQueue.\n\t -- Asynchronous mode will not work correctly and Quote Price change publishing will be disabled"); 2372 publishQuotePriceChange = false; 2373 } 2374 2375 try 2376 { 2377 tConnFactory = (ConnectionFactory) context.lookup("java:comp/env/jms/TopicConnectionFactory"); 2378 } 2379 catch (Exception e) 2380 { 2381 Log.error("TradeDirect:init Unable to locate TopicConnectionFactory.\n\t -- Asynchronous mode will not work correctly and Quote Price change publishing will be disabled"); 2382 publishQuotePriceChange = false; 2383 } 2384 2385 try 2386 { 2387 streamerTopic = (Topic) context.lookup("java:comp/env/jms/TradeStreamerTopic"); 2388 } 2389 catch (Exception e) 2390 { 2391 Log.error("TradeDirect:init Unable to locate TradeStreamerTopic.\n\t -- Asynchronous mode will not work correctly and Quote Price change publishing will be disabled"); 2392 publishQuotePriceChange = false; 2393 } 2394 2395 2396 try 2397 { 2398 tradeEJB = (Trade) tradeHome.create(); 2399 } 2400 catch (Exception e) 2401 { 2402 Log.error("TradeDirect:init -- error looking up TradeEJB -- Asynchronous 1-phase will not work", e); 2403 } 2404 if (Log.doTrace()) 2405 Log.trace("TradeDirect:init -- +++ initialized"); 2406 2407 initialized = true; 2408 } 2409 public static void destroy() 2410 { 2411 try 2412 { 2413 if (!initialized) return; 2414 Log.trace("TradeDirect:destroy"); 2415 } 2416 catch (Exception e) 2417 { 2418 Log.error("TradeDirect:destroy", e); 2419 } 2420 } 2421 2422 2423 private static InitialContext context; 2424 private static ConnectionFactory qConnFactory; 2425 private static Queue queue; 2426 private static ConnectionFactory tConnFactory; 2427 private static Topic streamerTopic; 2428 private static Trade tradeEJB; 2429 private static boolean publishQuotePriceChange = true; 2430 /** 2431 * Gets the inGlobalTxn 2432 * @return Returns a boolean 2433 */ 2434 private boolean getInGlobalTxn() { 2435 return inGlobalTxn; 2436 } 2437 /** 2438 * Sets the inGlobalTxn 2439 * @param inGlobalTxn The inGlobalTxn to set 2440 */ 2441 private void setInGlobalTxn(boolean inGlobalTxn) { 2442 this.inGlobalTxn = inGlobalTxn; 2443 } 2444 2445 }