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.web; 018 019 import javax.servlet.*; 020 import javax.servlet.http.*; 021 022 import org.apache.geronimo.samples.daytrader.soap.*; 023 import org.apache.geronimo.samples.daytrader.util.*; 024 025 import java.io.IOException; 026 import java.util.Collection; 027 import java.util.Iterator; 028 import java.util.ArrayList; 029 import java.math.BigDecimal; 030 import org.apache.geronimo.samples.daytrader.*; 031 032 /** 033 * TradeServletAction provides servlet specific client side access to each of 034 * the Trade brokerage user operations. These include login, logout, buy, sell, 035 * getQuote, etc. TradeServletAction manages a web interface to Trade handling 036 * HttpRequests/HttpResponse objects and forwarding results to the appropriate 037 * JSP page for the web interface. TradeServletAction invokes 038 * {@link TradeAction} methods to actually perform each trading operation. 039 * 040 */ 041 public class TradeServletAction { 042 043 private TradeServices tAction = null; 044 045 TradeServletAction() { 046 if (TradeConfig.getAccessMode() == TradeConfig.STANDARD) 047 tAction = new TradeAction(); 048 else if (TradeConfig.getAccessMode() == TradeConfig.WEBSERVICES) 049 tAction = new TradeWebSoapProxy(); 050 } 051 052 /** 053 * Display User Profile information such as address, email, etc. for the 054 * given Trader Dispatch to the Trade Account JSP for display 055 * 056 * @param userID 057 * The User to display profile info 058 * @param ctx 059 * the servlet context 060 * @param req 061 * the HttpRequest object 062 * @param resp 063 * the HttpResponse object 064 * @param results 065 * A short description of the results/success of this web request 066 * provided on the web page 067 * @exception javax.servlet.ServletException 068 * If a servlet specific exception is encountered 069 * @exception javax.io.IOException 070 * If an exception occurs while writing results back to the 071 * user 072 * 073 */ 074 void doAccount(ServletContext ctx, HttpServletRequest req, 075 HttpServletResponse resp, String userID, String results) 076 throws javax.servlet.ServletException, java.io.IOException { 077 try { 078 079 AccountDataBean accountData = tAction.getAccountData(userID); 080 AccountProfileDataBean accountProfileData = tAction 081 .getAccountProfileData(userID); 082 ArrayList orderDataBeans = (TradeConfig.getLongRun() ? new ArrayList() : (ArrayList) tAction.getOrders(userID)); 083 084 req.setAttribute("accountData", accountData); 085 req.setAttribute("accountProfileData", accountProfileData); 086 req.setAttribute("orderDataBeans", orderDataBeans); 087 req.setAttribute("results", results); 088 requestDispatch(ctx, req, resp, userID, TradeConfig 089 .getPage(TradeConfig.ACCOUNT_PAGE)); 090 } catch (java.lang.IllegalArgumentException e) { // this is a user 091 // error so I will 092 // forward them to another page rather than throw a 500 093 req.setAttribute("results", results 094 + "could not find account for userID = " + userID); 095 requestDispatch(ctx, req, resp, userID, TradeConfig 096 .getPage(TradeConfig.HOME_PAGE)); 097 // log the exception with an error level of 3 which means, handled 098 // exception but would invalidate a automation run 099 Log 100 .error( 101 "TradeServletAction.doAccount(...)", 102 "illegal argument, information should be in exception string", 103 e); 104 } catch (Exception e) { 105 // log the exception with error page 106 throw new ServletException("TradeServletAction.doAccount(...)" 107 + " exception user =" + userID, e); 108 } 109 110 } 111 112 /** 113 * Update User Profile information such as address, email, etc. for the 114 * given Trader Dispatch to the Trade Account JSP for display If any in put 115 * is incorrect revert back to the account page w/ an appropriate message 116 * 117 * @param userID 118 * The User to upddate profile info 119 * @param password 120 * The new User password 121 * @param cpassword 122 * Confirm password 123 * @param fullname 124 * The new User fullname info 125 * @param address 126 * The new User address info 127 * @param cc 128 * The new User credit card info 129 * @param email 130 * The new User email info 131 * @param ctx 132 * the servlet context 133 * @param req 134 * the HttpRequest object 135 * @param resp 136 * the HttpResponse object 137 * @exception javax.servlet.ServletException 138 * If a servlet specific exception is encountered 139 * @exception javax.io.IOException 140 * If an exception occurs while writing results back to the 141 * user 142 * 143 */ 144 void doAccountUpdate(ServletContext ctx, HttpServletRequest req, 145 HttpServletResponse resp, String userID, String password, 146 String cpassword, String fullName, String address, 147 String creditcard, String email) 148 throws javax.servlet.ServletException, java.io.IOException { 149 String results = ""; 150 151 // First verify input data 152 boolean doUpdate = true; 153 if (password.equals(cpassword) == false) { 154 results = "Update profile error: passwords do not match"; 155 doUpdate = false; 156 } else if (password.length() <= 0 || fullName.length() <= 0 157 || address.length() <= 0 || creditcard.length() <= 0 158 || email.length() <= 0) { 159 results = "Update profile error: please fill in all profile information fields"; 160 doUpdate = false; 161 } 162 AccountProfileDataBean accountProfileData = new AccountProfileDataBean( 163 userID, password, fullName, address, email, creditcard); 164 try { 165 if (doUpdate) { 166 accountProfileData = tAction 167 .updateAccountProfile(accountProfileData); 168 results = "Account profile update successful"; 169 } 170 171 } catch (java.lang.IllegalArgumentException e) { // this is a user 172 // error so I will 173 // forward them to another page rather than throw a 500 174 req 175 .setAttribute( 176 "results", 177 results 178 + "invalid argument, check userID is correct, and the database is populated" 179 + userID); 180 Log 181 .error( 182 e, 183 "TradeServletAction.doAccount(...)", 184 "illegal argument, information should be in exception string", 185 "treating this as a user error and forwarding on to a new page"); 186 } catch (Exception e) { 187 // log the exception with error page 188 throw new ServletException( 189 "TradeServletAction.doAccountUpdate(...)" 190 + " exception user =" + userID, e); 191 } 192 doAccount(ctx, req, resp, userID, results); 193 } 194 195 /** 196 * Buy a new holding of shares for the given trader Dispatch to the Trade 197 * Portfolio JSP for display 198 * 199 * @param userID 200 * The User buying shares 201 * @param symbol 202 * The stock to purchase 203 * @param amount 204 * The quantity of shares to purchase 205 * @param ctx 206 * the servlet context 207 * @param req 208 * the HttpRequest object 209 * @param resp 210 * the HttpResponse object 211 * @exception javax.servlet.ServletException 212 * If a servlet specific exception is encountered 213 * @exception javax.io.IOException 214 * If an exception occurs while writing results back to the 215 * user 216 * 217 */ 218 void doBuy(ServletContext ctx, HttpServletRequest req, 219 HttpServletResponse resp, String userID, String symbol, 220 String quantity) throws ServletException, IOException { 221 222 String results = ""; 223 224 try { 225 OrderDataBean orderData = tAction.buy(userID, symbol, new Double( 226 quantity).doubleValue(), TradeConfig.orderProcessingMode); 227 228 req.setAttribute("orderData", orderData); 229 req.setAttribute("results", results); 230 } catch (java.lang.IllegalArgumentException e) { // this is a user 231 // error so I will 232 // forward them to another page rather than throw a 500 233 req.setAttribute("results", results + "illegal argument:"); 234 requestDispatch(ctx, req, resp, userID, TradeConfig 235 .getPage(TradeConfig.HOME_PAGE)); 236 // log the exception with an error level of 3 which means, handled 237 // exception but would invalidate a automation run 238 Log.error(e, "TradeServletAction.doBuy(...)", 239 "illegal argument. userID = " + userID, "symbol = " 240 + symbol); 241 } catch (Exception e) { 242 // log the exception with error page 243 throw new ServletException("TradeServletAction.buy(...)" 244 + " exception buying stock " + symbol + " for user " 245 + userID, e); 246 } 247 requestDispatch(ctx, req, resp, userID, TradeConfig 248 .getPage(TradeConfig.ORDER_PAGE)); 249 } 250 251 /** 252 * Create the Trade Home page with personalized information such as the 253 * traders account balance Dispatch to the Trade Home JSP for display 254 * 255 * @param ctx 256 * the servlet context 257 * @param req 258 * the HttpRequest object 259 * @param resp 260 * the HttpResponse object 261 * @param results 262 * A short description of the results/success of this web request 263 * provided on the web page 264 * @exception javax.servlet.ServletException 265 * If a servlet specific exception is encountered 266 * @exception javax.io.IOException 267 * If an exception occurs while writing results back to the 268 * user 269 * 270 */ 271 void doHome(ServletContext ctx, HttpServletRequest req, 272 HttpServletResponse resp, String userID, String results) 273 throws javax.servlet.ServletException, java.io.IOException { 274 BigDecimal balance; 275 String result = ""; 276 try { 277 AccountDataBean accountData = tAction.getAccountData(userID); 278 Collection holdingDataBeans = tAction.getHoldings(userID); 279 280 // Edge Caching: 281 // Getting the MarketSummary has been moved to the JSP 282 // MarketSummary.jsp. This makes the MarketSummary a 283 // standalone "fragment", and thus is a candidate for 284 // Edge caching. 285 // marketSummaryData = tAction.getMarketSummary(); 286 287 req.setAttribute("accountData", accountData); 288 req.setAttribute("holdingDataBeans", holdingDataBeans); 289 // See Edge Caching above 290 // req.setAttribute("marketSummaryData", marketSummaryData); 291 req.setAttribute("results", results); 292 } catch (java.lang.IllegalArgumentException e) { // this is a user 293 // error so I will 294 // forward them to another page rather than throw a 500 295 req.setAttribute("results", results + "check userID = " + userID 296 + " and that the database is populated"); 297 requestDispatch(ctx, req, resp, userID, TradeConfig 298 .getPage(TradeConfig.HOME_PAGE)); 299 // log the exception with an error level of 3 which means, handled 300 // exception but would invalidate a automation run 301 Log 302 .error( 303 "TradeServletAction.doHome(...)" 304 + "illegal argument, information should be in exception string" 305 + "treating this as a user error and forwarding on to a new page", 306 e); 307 } catch (javax.ejb.FinderException e) { 308 // this is a user error so I will 309 // forward them to another page rather than throw a 500 310 req.setAttribute("results", results 311 + "\nCould not find account for + " + userID); 312 // requestDispatch(ctx, req, resp, 313 // TradeConfig.getPage(TradeConfig.HOME_PAGE)); 314 // log the exception with an error level of 3 which means, handled 315 // exception but would invalidate a automation run 316 Log 317 .error( 318 "TradeServletAction.doHome(...)" 319 + "Error finding account for user " 320 + userID 321 + "treating this as a user error and forwarding on to a new page", 322 e); 323 } catch (Exception e) { 324 // log the exception with error page 325 throw new ServletException("TradeServletAction.doHome(...)" 326 + " exception user =" + userID, e); 327 } 328 329 requestDispatch(ctx, req, resp, userID, TradeConfig 330 .getPage(TradeConfig.HOME_PAGE)); 331 } 332 333 /** 334 * Login a Trade User. Dispatch to the Trade Home JSP for display 335 * 336 * @param userID 337 * The User to login 338 * @param passwd 339 * The password supplied by the trader used to authenticate 340 * @param ctx 341 * the servlet context 342 * @param req 343 * the HttpRequest object 344 * @param resp 345 * the HttpResponse object 346 * @param results 347 * A short description of the results/success of this web request 348 * provided on the web page 349 * @exception javax.servlet.ServletException 350 * If a servlet specific exception is encountered 351 * @exception javax.io.IOException 352 * If an exception occurs while writing results back to the 353 * user 354 * 355 */ 356 void doLogin(ServletContext ctx, HttpServletRequest req, 357 HttpServletResponse resp, String userID, String passwd) 358 throws javax.servlet.ServletException, java.io.IOException { 359 360 String results = ""; 361 try { 362 // Got a valid userID and passwd, attempt login 363 364 AccountDataBean accountData = tAction.login(userID, passwd); 365 366 if (accountData != null) { 367 HttpSession session = req.getSession(true); 368 session.setAttribute("uidBean", userID); 369 session.setAttribute("sessionCreationDate", 370 new java.util.Date()); 371 results = "Ready to Trade"; 372 doHome(ctx, req, resp, userID, results); 373 return; 374 } else { 375 req.setAttribute("results", results 376 + "\nCould not find account for + " + userID); 377 // log the exception with an error level of 3 which means, 378 // handled exception but would invalidate a automation run 379 Log.log( 380 "TradeServletAction.doLogin(...)", 381 "Error finding account for user " + userID + "", 382 "user entered a bad username or the database is not populated"); 383 } 384 } catch (java.lang.IllegalArgumentException e) { // this is a user 385 // error so I will 386 // forward them to another page rather than throw a 500 387 req.setAttribute("results", results + "illegal argument:" 388 + e.getMessage()); 389 // log the exception with an error level of 3 which means, handled 390 // exception but would invalidate a automation run 391 Log 392 .error( 393 e, 394 "TradeServletAction.doLogin(...)", 395 "illegal argument, information should be in exception string", 396 "treating this as a user error and forwarding on to a new page"); 397 398 } catch (Exception e) { 399 // log the exception with error page 400 throw new ServletException("TradeServletAction.doLogin(...)" 401 + "Exception logging in user " + userID + "with password" 402 + passwd, e); 403 } 404 405 requestDispatch(ctx, req, resp, userID, TradeConfig 406 .getPage(TradeConfig.WELCOME_PAGE)); 407 408 } 409 410 /** 411 * Logout a Trade User Dispatch to the Trade Welcome JSP for display 412 * 413 * @param userID 414 * The User to logout 415 * @param ctx 416 * the servlet context 417 * @param req 418 * the HttpRequest object 419 * @param resp 420 * the HttpResponse object 421 * @param results 422 * A short description of the results/success of this web request 423 * provided on the web page 424 * @exception javax.servlet.ServletException 425 * If a servlet specific exception is encountered 426 * @exception javax.io.IOException 427 * If an exception occurs while writing results back to the 428 * user 429 * 430 */ 431 void doLogout(ServletContext ctx, HttpServletRequest req, 432 HttpServletResponse resp, String userID) throws ServletException, 433 IOException { 434 String results = ""; 435 436 try { 437 tAction.logout(userID); 438 439 } catch (java.lang.IllegalArgumentException e) { // this is a user 440 // error so I will 441 // forward them to another page, at the end of the page. 442 req.setAttribute("results", results + "illegal argument:" 443 + e.getMessage()); 444 445 // log the exception with an error level of 3 which means, handled 446 // exception but would invalidate a automation run 447 Log 448 .error( 449 e, 450 "TradeServletAction.doLogout(...)", 451 "illegal argument, information should be in exception string", 452 "treating this as a user error and forwarding on to a new page"); 453 } catch (Exception e) { 454 // log the exception and foward to a error page 455 Log.error(e, "TradeServletAction.doLogout(...):", 456 "Error logging out" + userID, "fowarding to an error page"); 457 // set the status_code to 500 458 throw new ServletException("TradeServletAction.doLogout(...)" 459 + "exception logging out user " + userID, e); 460 } 461 HttpSession session = req.getSession(); 462 if (session != null) { 463 session.invalidate(); 464 } 465 466 Object o = req.getAttribute("TSS-RecreateSessionInLogout"); 467 if (o != null && ((Boolean) o).equals(Boolean.TRUE)) { 468 // Recreate Session object before writing output to the response 469 // Once the response headers are written back to the client the 470 // opportunity 471 // to create a new session in this request may be lost 472 // This is to handle only the TradeScenarioServlet case 473 session = req.getSession(true); 474 } 475 requestDispatch(ctx, req, resp, userID, TradeConfig 476 .getPage(TradeConfig.WELCOME_PAGE)); 477 } 478 479 /** 480 * Retrieve the current portfolio of stock holdings for the given trader 481 * Dispatch to the Trade Portfolio JSP for display 482 * 483 * @param userID 484 * The User requesting to view their portfolio 485 * @param ctx 486 * the servlet context 487 * @param req 488 * the HttpRequest object 489 * @param resp 490 * the HttpResponse object 491 * @param results 492 * A short description of the results/success of this web request 493 * provided on the web page 494 * @exception javax.servlet.ServletException 495 * If a servlet specific exception is encountered 496 * @exception javax.io.IOException 497 * If an exception occurs while writing results back to the 498 * user 499 * 500 */ 501 void doPortfolio(ServletContext ctx, HttpServletRequest req, 502 HttpServletResponse resp, String userID, String results) 503 throws ServletException, IOException { 504 505 try { 506 // Get the holdiings for this user 507 508 Collection quoteDataBeans = new ArrayList(); 509 Collection holdingDataBeans = tAction.getHoldings(userID); 510 511 // Walk through the collection of user 512 // holdings and creating a list of quotes 513 if (holdingDataBeans.size() > 0) { 514 515 Iterator it = holdingDataBeans.iterator(); 516 while (it.hasNext()) { 517 HoldingDataBean holdingData = (HoldingDataBean) it.next(); 518 QuoteDataBean quoteData = tAction.getQuote(holdingData 519 .getQuoteID()); 520 quoteDataBeans.add(quoteData); 521 } 522 } else { 523 results = results + ". Your portfolio is empty."; 524 } 525 req.setAttribute("results", results); 526 req.setAttribute("holdingDataBeans", holdingDataBeans); 527 req.setAttribute("quoteDataBeans", quoteDataBeans); 528 requestDispatch(ctx, req, resp, userID, TradeConfig 529 .getPage(TradeConfig.PORTFOLIO_PAGE)); 530 } catch (java.lang.IllegalArgumentException e) { // this is a user 531 // error so I will 532 // forward them to another page rather than throw a 500 533 req.setAttribute("results", results + "illegal argument:" 534 + e.getMessage()); 535 requestDispatch(ctx, req, resp, userID, TradeConfig 536 .getPage(TradeConfig.PORTFOLIO_PAGE)); 537 // log the exception with an error level of 3 which means, handled 538 // exception but would invalidate a automation run 539 Log 540 .error( 541 e, 542 "TradeServletAction.doPortfolio(...)", 543 "illegal argument, information should be in exception string", 544 "user error"); 545 } catch (Exception e) { 546 // log the exception with error page 547 throw new ServletException("TradeServletAction.doPortfolio(...)" 548 + " exception user =" + userID, e); 549 } 550 } 551 552 /** 553 * Retrieve the current Quote for the given stock symbol Dispatch to the 554 * Trade Quote JSP for display 555 * 556 * @param userID 557 * The stock symbol used to get the current quote 558 * @param ctx 559 * the servlet context 560 * @param req 561 * the HttpRequest object 562 * @param resp 563 * the HttpResponse object 564 * @exception javax.servlet.ServletException 565 * If a servlet specific exception is encountered 566 * @exception javax.io.IOException 567 * If an exception occurs while writing results back to the 568 * user 569 * 570 */ 571 void doQuotes(ServletContext ctx, HttpServletRequest req, 572 HttpServletResponse resp, String userID, String symbols) 573 throws ServletException, IOException { 574 String results = ""; 575 576 // Edge Caching: 577 // Getting Quotes has been moved to the JSP 578 // Quote.jsp. This makes each Quote a 579 // standalone "fragment", and thus is a candidate for 580 // Edge caching. 581 // 582 583 requestDispatch(ctx, req, resp, userID, TradeConfig 584 .getPage(TradeConfig.QUOTE_PAGE)); 585 } 586 587 /** 588 * Register a new trader given the provided user Profile information such as 589 * address, email, etc. Dispatch to the Trade Home JSP for display 590 * 591 * @param userID 592 * The User to create 593 * @param passwd 594 * The User password 595 * @param fullname 596 * The new User fullname info 597 * @param ccn 598 * The new User credit card info 599 * @param money 600 * The new User opening account balance 601 * @param address 602 * The new User address info 603 * @param email 604 * The new User email info 605 * @return The userID of the new trader 606 * @param ctx 607 * the servlet context 608 * @param req 609 * the HttpRequest object 610 * @param resp 611 * the HttpResponse object 612 * @exception javax.servlet.ServletException 613 * If a servlet specific exception is encountered 614 * @exception javax.io.IOException 615 * If an exception occurs while writing results back to the 616 * user 617 * 618 */ 619 void doRegister(ServletContext ctx, HttpServletRequest req, 620 HttpServletResponse resp, String userID, String passwd, 621 String cpasswd, String fullname, String ccn, 622 String openBalanceString, String email, String address) 623 throws ServletException, IOException { 624 String results = ""; 625 626 try { 627 // Validate user passwords match and are atleast 1 char in length 628 if ((passwd.equals(cpasswd)) && (passwd.length() >= 1)) { 629 630 AccountDataBean accountData = tAction.register(userID, passwd, 631 fullname, address, email, ccn, new BigDecimal( 632 openBalanceString)); 633 if (accountData == null) { 634 results = "Registration operation failed;"; 635 System.out.println(results); 636 req.setAttribute("results", results); 637 requestDispatch(ctx, req, resp, userID, TradeConfig 638 .getPage(TradeConfig.REGISTER_PAGE)); 639 } else { 640 doLogin(ctx, req, resp, userID, passwd); 641 results = "Registration operation succeeded; Account " 642 + accountData.getAccountID() + " has been created."; 643 req.setAttribute("results", results); 644 645 } 646 } else { 647 // Password validation failed 648 results = "Registration operation failed, your passwords did not match"; 649 System.out.println(results); 650 req.setAttribute("results", results); 651 requestDispatch(ctx, req, resp, userID, TradeConfig 652 .getPage(TradeConfig.REGISTER_PAGE)); 653 } 654 655 } catch (Exception e) { 656 // log the exception with error page 657 throw new ServletException("TradeServletAction.doRegister(...)" 658 + " exception user =" + userID, e); 659 } 660 } 661 662 /** 663 * Sell a current holding of stock shares for the given trader. Dispatch to 664 * the Trade Portfolio JSP for display 665 * 666 * @param userID 667 * The User buying shares 668 * @param symbol 669 * The stock to sell 670 * @param indx 671 * The unique index identifying the users holding to sell 672 * @param ctx 673 * the servlet context 674 * @param req 675 * the HttpRequest object 676 * @param resp 677 * the HttpResponse object 678 * @exception javax.servlet.ServletException 679 * If a servlet specific exception is encountered 680 * @exception javax.io.IOException 681 * If an exception occurs while writing results back to the 682 * user 683 * 684 */ 685 void doSell(ServletContext ctx, HttpServletRequest req, 686 HttpServletResponse resp, String userID, Integer holdingID) 687 throws ServletException, IOException { 688 String results = ""; 689 try { 690 OrderDataBean orderData = tAction.sell(userID, holdingID, 691 TradeConfig.orderProcessingMode); 692 693 req.setAttribute("orderData", orderData); 694 req.setAttribute("results", results); 695 } catch (java.lang.IllegalArgumentException e) { // this is a user 696 // error so I will 697 // just log the exception and then later on I will redisplay the 698 // portfolio page 699 // because this is just a user exception 700 Log 701 .error( 702 e, 703 "TradeServletAction.doSell(...)", 704 "illegal argument, information should be in exception string", 705 "user error"); 706 } catch (Exception e) { 707 // log the exception with error page 708 throw new ServletException("TradeServletAction.doSell(...)" 709 + " exception selling holding " + holdingID + " for user =" 710 + userID, e); 711 } 712 requestDispatch(ctx, req, resp, userID, TradeConfig 713 .getPage(TradeConfig.ORDER_PAGE)); 714 } 715 716 void doWelcome(ServletContext ctx, HttpServletRequest req, 717 HttpServletResponse resp, String status) throws ServletException, 718 IOException { 719 720 req.setAttribute("results", status); 721 requestDispatch(ctx, req, resp, null, TradeConfig 722 .getPage(TradeConfig.WELCOME_PAGE)); 723 } 724 725 private void requestDispatch(ServletContext ctx, HttpServletRequest req, 726 HttpServletResponse resp, String userID, String page) 727 throws ServletException, IOException { 728 729 ctx.getRequestDispatcher(page).include(req, resp); 730 } 731 732 private void sendRedirect(HttpServletResponse resp, String page) 733 throws ServletException, IOException { 734 resp.sendRedirect(resp.encodeRedirectURL(page)); 735 } 736 }