Mastering™ JSP™
Todd Cook
SYBEX®
Mastering JSP
This page intentionally left blank
Mastering
™
JSP
™
Todd Cook
San Francisco London
Associate Publisher: Richard Mills Acquisitions and Developmental Editor: Tom Cirtin Editor: Pat Coleman Production Editor: Liz Burke Technical Editor: Robert Castaneda Book Designer: Maureen Forys, Happenstance Type-O-Rama Electronic Publishing Specialist: Interactive Composition Corporation Proofreaders: Laurie O’Connell, Nancy Riddiough, Emily Hsuan, Dave Nash, Yariv Rabinovitch Indexer: Ann Rogers CD Coordinator: Dan Mummert CD Technician: Kevin Ly Cover Designer: Design Site Cover Illustrator: Tania Kac, Design Site Copyright © 2002 SYBEX Inc., 1151 Marina Village Parkway, Alameda, CA 94501. World rights reserved. The author(s) created reusable code in this publication expressly for reuse by readers. Sybex grants readers limited permission to reuse the code found in this publication or its accompanying CD-ROM so long as the author(s) are attributed in any application containing the reusable code and the code itself is never distributed, posted online by electronic transmission, sold, or commercially exploited as a stand-alone product. Aside from this specific exception concerning reusable code, No part of this publication may be stored in a retrieval system, transmitted, or reproduced in any way, including but not limited to photocopy, photograph, magnetic, or other record, without the prior agreement and written permission of the publisher. Library of Congress Card Number: 2002106563 ISBN: 0-7821-2940-4 SYBEX and the SYBEX logo are either registered trademarks or trademarks of SYBEX Inc. in the United States and/or other countries. Screen reproductions produced with FullShot 99. FullShot 99 © 1991–1999 Inbit Incorporated. All rights reserved. FullShot is a trademark of Inbit Incorporated. Internet screen shot(s) using Microsoft Internet Explorer 5.0 reprinted by permission from Microsoft Corporation. TRADEMARKS: SYBEX has attempted throughout this book to distinguish proprietary trademarks from descriptive terms by following the capitalization style used by the manufacturer. The author and publisher have made their best efforts to prepare this book, and the content is based upon final release software whenever possible. Portions of the manuscript may be based upon pre-release versions supplied by software manufacturer(s). The author and the publisher make no representation or warranties of any kind with regard to the completeness or accuracy of the contents herein and accept no liability of any kind including but not limited to performance, merchantability, fitness for any particular purpose, or any losses or damages of any kind caused or alleged to be caused directly or indirectly from this book. Manufactured in the United States of America 10 9 8 7 6 5 4 3 2 1
Software License Agreement: Terms and Conditions The media and/or any online materials accompanying this book that are available now or in the future contain programs and/or text files (the “Software”) to be used in connection with the book. SYBEX hereby grants to you a license to use the Software, subject to the terms that follow. Your purchase, acceptance, or use of the Software will constitute your acceptance of such terms. The Software compilation is the property of SYBEX unless otherwise indicated and is protected by copyright to SYBEX or other copyright owner(s) as indicated in the media files (the “Owner(s)”). You are hereby granted a single-user license to use the Software for your personal, noncommercial use only. You may not reproduce, sell, distribute, publish, circulate, or commercially exploit the Software, or any portion thereof, without the written consent of SYBEX and the specific copyright owner(s) of any component software included on this media. In the event that the Software or components include specific license requirements or end-user agreements, statements of condition, disclaimers, limitations or warranties (“End-User License”), those End-User Licenses supersede the terms and conditions herein as to that particular Software component. Your purchase, acceptance, or use of the Software will constitute your acceptance of such End-User Licenses. By purchase, use or acceptance of the Software you further agree to comply with all export laws and regulations of the United States as such laws and regulations may exist from time to time.
Reusable Code in This Book The author(s) created reusable code in this publication expressly for reuse by readers. Sybex grants readers limited permission to reuse the code found in this publication or its accompanying CD-ROM so long as the author(s) are attributed in any application containing the reusable code and the code itself is never distributed, posted online by electronic transmission, sold, or commercially exploited as a stand-alone product.
Software Support Components of the supplemental Software and any offers associated with them may be supported by the specific Owner(s) of that material, but they are not supported by SYBEX. Information regarding any available support may be obtained from the Owner(s) using the information provided in the appropriate read.me files or listed elsewhere on the media. Should the manufacturer(s) or other Owner(s) cease to offer support or decline to honor any offer, SYBEX bears no responsibility. This notice concerning support for the Software is provided for your information only. SYBEX is not the agent or principal of the Owner(s), and SYBEX is in no way responsible for providing any support for the Software, nor is it liable or responsible for any support provided, or not provided, by the Owner(s).
Warranty SYBEX warrants the enclosed media to be free of physical defects for a period of ninety (90) days after purchase. The Software is not
available from SYBEX in any other form or media than that enclosed herein or posted to www.sybex.com. If you discover a defect in the media during this warranty period, you may obtain a replacement of identical format at no charge by sending the defective media, postage prepaid, with proof of purchase to: SYBEX Inc. Product Support Department 1151 Marina Village Parkway Alameda, CA 94501 Web: http://www.sybex.com After the 90-day period, you can obtain replacement media of identical format by sending us the defective disk, proof of purchase, and a check or money order for $10, payable to SYBEX.
Disclaimer SYBEX makes no warranty or representation, either expressed or implied, with respect to the Software or its contents, quality, performance, merchantability, or fitness for a particular purpose. In no event will SYBEX, its distributors, or dealers be liable to you or any other party for direct, indirect, special, incidental, consequential, or other damages arising out of the use of or inability to use the Software or its contents even if advised of the possibility of such damage. In the event that the Software includes an online update feature, SYBEX further disclaims any obligation to provide this feature for any specific duration other than the initial posting. The exclusion of implied warranties is not permitted by some states. Therefore, the above exclusion may not apply to you. This warranty provides you with specific legal rights; there may be other rights that you may have that vary from state to state. The pricing of the book with the Software by SYBEX reflects the allocation of risk and limitations on liability contained in this agreement of Terms and Conditions.
Shareware Distribution This Software may contain various programs that are distributed as shareware. Copyright laws apply to both shareware and ordinary commercial software, and the copyright Owner(s) retains all rights. If you try a shareware program and continue using it, you are expected to register it. Individual programs differ on details of trial periods, registration, and payment. Please observe the requirements stated in appropriate files.
Copy Protection The Software in whole or in part may or may not be copy-protected or encrypted. However, in all cases, reselling or redistributing these files without authorization is expressly forbidden except as specifically provided for by the Owner(s) therein.
This book is dedicated to Mackenzie and eager students of Java everywhere. —Todd Cook
Acknowledgments Many people made this book possible and I would like to thank first my friends and family. In particular, I thank Charles Mohnike for his encouragement and wise advice. I thank my agent, Jimmy Vines, of the Vines Agency for his support and seasoned perspective. Bettina Roth, Parag Agarwal, and Matt Madsen also helped by reading chapters, offering helpful advice, and asking questions. Sybex has an impressive publishing team that works in concert. I would like to thank Tom Cirtin, the acquisitions editor, for his commitment to the project and his belief in my vision for a useful, streamlined, and efficient text. I would like to thank Pat Coleman for her editing skills and watchful eye and Liz Burke, the production editor, who held the project together at the most critical times. The readers I worked with while writing the chapters helped me to ensure that valuable information and tips were included to help both beginners and seasoned programmers.
This page intentionally left blank
Contents at a Glance Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii Part I • JSP Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Chapter 1 • Introducing JavaServer Pages and the JSP Environment . . . . . . . . . . . . . 3 Chapter 2 • HTTP and Servlet Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Chapter 3 • JSP Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Part II • JSP Application Development. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Chapter 4 • Using Scripting Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Chapter 5 • Introducing JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Chapter 6 • Sharing Data: JSP Security, Authentication, and Integrity . . . . . . . . . 153 Chapter 7 • Database Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Chapter 8 • Error Handling and Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Chapter 9 • Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Chapter 10 • Presenting XML With JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Chapter 11 • Integrating Legacy Applications: Wrappers and Interfaces . . . . . . . . 319 Chapter 12 • Integrating Other Extensions and Internationalization . . . . . . . . . . . 357 Part III • Professional JSP Design, Development, and Implementation . . . . . . . . . . . . . 385
Chapter 13 • Web Application Models and Advanced Architectures . . . . . . . . . . 387 Chapter 14 • Advanced Database Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . 437 Chapter 15 • Custom Tags: The Building Blocks of the Java Standard Tag Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475 Chapter 16 • Enterprise JavaBeans and JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
X
CONTENTS AT A GLANCE
Appendices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
Appendix A • Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 Appendix B • JSP and Servlet API References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591 Appendix C • A Java Primer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611 Appendix D • Proposed JSTL API Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623 Appendix E • Web Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .637
Contents Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii Part I • JSP Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 1 • Introducing JavaServer Pages and the JSP Environment . . . . . . . . . 3 The Growth of Server-Side Java and JSP’s Role . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 What Is a JSP Page? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Why Use JSP? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Learning JSP: How Hard Is This Going to Be? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Web Programming Languages Compared . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 ASP (Active Server Pages) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 ColdFusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 PHP: Hypertext Preprocessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 JSP in Various Server Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Which Java Environment? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Fast-Brewing Java on the Client Side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 What You Need to Get Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Chapter 2 • HTTP and Servlet Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Behaviors and Limitations of HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 The HTTP Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 The GET Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 The HEAD Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 The POST Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 The PUT Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 The DELETE Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 The TRACE Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 The OPTIONS Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 HTTP and Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Servlet Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 HTTP Access and Variables Available to a Servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Configurable Servlet Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Property Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 SalaryQuote Servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 The Advantages of Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 What’s New in Servlet Specification 2.3? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Chapter 3 • JSP Processing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 The Tag Elements of a JSP Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 JSP Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Improved Commenting with JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
XII
CONTENTS
The Anatomy of a JSP Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Server Processing of a JSP Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compiling a JSP Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reflection: How a JavaServer Engine Interacts with Other Enterprise Components . . . . Reflection Explained in Depth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Server-Side Object Lifespans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60 61 61 64 66 67 74
Part II • JSP Application Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Chapter 4 • Using Scripting Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Variables in JSPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Using Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Declaring Variables and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Variable Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Understanding Implicit Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Using Flow Control Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Displaying Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 The PrintWriter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Another Kind of Print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Working with Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Creating and Displaying Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Displaying Military Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Putting It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 The JavaBean Code That Supports This Chapter’s Examples . . . . . . . . . . . . . . . . . . . . . . . . 104 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Chapter 5 • Introducing JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 An Overview of JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 The Development of JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 JavaBean Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 JavaBean Design Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 JavaBean Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Naming Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Naming Indexed Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Naming Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Working with Session Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 JavaBean Design Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Reflection: How a JavaServer Engine or an IDE Learns about a JavaBean’s Behavior . . . . . 132 Bugs in JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Restricting the Generation of HTML within a Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 White-Box Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Putting It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
CONTENTS
Chapter 6 • Sharing Data: JSP Security, Authentication, and Integrity . . . . . 153 Sharing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Using Hidden Fields to Pass Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Passing Data with URL Rewriting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Saving and Retrieving Session Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Handling Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Additional Security Concerns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Recovering Source Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Chapter 7 • Database Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Database Connectivity and JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 How JDBC Starts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Using JDBC: A Simple Product, Account, and Order Application . . . . . . . . . . . . . . . . 187 Connection Pooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 A Connection Manager Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 Improving the Chapter’s Sample Application Using the Connection Manager and JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Chapter 8 • Error Handling and Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Debugging the User’s Experience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 “An error? You must be mistaken. We don’t allow that…” . . . . . . . . . . . . . . . . . . . . . . 222 Testing, Testing, Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Updated Help Files: the First Line of Defense . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Types of Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Syntax Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Library Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Dynamic Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Error Prevention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Dealing with Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Handling Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Dealing with Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Logging Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 Chapter 9 • Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Performance: A Usability Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Informing the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 User Expectations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 User Tolerance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Architecting for Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Optimizing for Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Practical JSP Performance: Problems and Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 Performance Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Benchmarking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
XIII
XIV
CONTENTS
Load Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 Using Apache Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 Chapter 10 • Presenting XML With JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Do I Really Have to Learn XML to Write JSPs? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 What Is XML? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 What Does XML Have to Do with HTML? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 A Simple XML Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Verifying XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Using a DTD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Using XML by Itself on the Client Side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 Writing XSL Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 XSL Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Displaying XML/XSL Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Generating Flat HTML from XML Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Data Migration Using XML/XSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Chapter 11 • Integrating Legacy Applications: Wrappers and Interfaces . . . . 319 Java Wrappers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 System Call Wrappers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 Working with Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 Java Native Interface (JNI) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 Remote Method Invocation (RMI) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Chapter 12 • Integrating Other Extensions and Internationalization . . . . . . . 357 Changing Graphic Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 A Watermarking Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 A Servlet-Based Watermarking System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Internationalizing Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 Part III • Professional JSP Design, Development, and Implementation . . . . . . . . . . . . . 385 Chapter 13 • Web Application Models and Advanced Architectures . . . . . . . . 387 Some Helpful Application Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 An Improved Connection Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 The DBConnection Properties File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 An Improved PropStore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Dynamic Authentication: Handling Roles, Permissions, and Access . . . . . . . . . . . . . . . . . . . 398 UserAuth: A Dynamic Authentication JavaBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 Authentication Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 MVC Using JSPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 The Director JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 The Sample JSP-MVC Application with Dynamic Authentication . . . . . . . . . . . . . . . . 418
CONTENTS
Constructing an MVC Using a Controlling Servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Chapter 14 • Advanced Database Programming . . . . . . . . . . . . . . . . . . . . . . . . 437 Problems with java.sql.Connection and java.sql.ResultSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437 RowSet: The JDBC 2.x Solution to ResultSet Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 DittoResultSet—A Robust, Simple Replacement for java.sql.ResultSet . . . . . . . . . . . . . . . . . . . . . 448 Moving Data Access Away from the Presentation Layer: A Quiz Application Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456 A QuizBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 JSPs Supporting the Quiz Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474 Chapter 15 • Custom Tags: The Building Blocks of the Java Standard Tag Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475 Why Use Custom Tags? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 The Tag Interface and Its Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 Creating a Simple Custom Tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 Building the Tag Library Descriptor File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 Potential Pitfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 Transforming a Block of Text with a BodyTag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483 Preventing Errors with a Validation Tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 A Potential Problem with Custom Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 Overview of the Java Standard Tag Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 Chapter 16 • Enterprise JavaBeans and JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 An Overview of EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Session Bean Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Entity Bean Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Using an Entity Bean to Abstract the Data Access Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 A Database-Driven Framework for Abstracting Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 Removing Data Access and Manipulation Code Using the AbstractedQueryAccess Class . . . . . 516 A Simple Entity Bean for Query Access with Read, Write, and Create Functions . . . . . . . . 546 TQueryStoreBean—The Entity Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 Testing an EJB Using a Standalone Test Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557 Using JBoss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573 Installing and Setting Up JBoss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573 Deploying with JBoss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573 Referencing an EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 Appendices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579 Appendix A • Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 Installing the Java Software Development Kit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
XV
XVI
CONTENTS
Installing a JSP/Servlet Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 Deploying JSP Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583 Appendix B • JSP and Servlet API References. . . . . . . . . . . . . . . . . . . . . . . . . . . 591 Commonly Inherited Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591 The javax.servlet Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591 Appendix C • A Java Primer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611 Classes and Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611 Packaging Web Applications: Creating and Reading Java Archives . . . . . . . . . . . . . . . . . . . 614 A Quick Tour of Common Constructions and Idioms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617 Appendix D • Proposed JSTL API Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623 C—Core Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623 FMT—Formatting Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 X—XML Validation Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630 sql—SQL Database Access and Presentation Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633 Appendix E • Web Resources. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .637
Introduction These days employees are being asked to do more work and take on more responsibilities than before. In many cases, versatility has become as important as productivity. This trend has affected every corner of industry, and now even regular employees are being asked to cross over and support specialized domains. Demand has also increased for server-side web programming. More and more I’m being asked to provide instructions and tutorials on the basics of web programming and server-side development for employees from all areas, including C++ programmers, system administrators, programmer analysts, biochemists, and other fields. There’s no reason these people can’t learn about web programming and JSP (JavaServer Pages) and succeed in extending their skills. The more productive and versatile an employee is, the more indispensable the employee can be for a company. The Web is more prevalent than before, and it’s become an integral part of many businesses that don’t even have an open presence on the World Wide Web. More people are comfortable learning HTML (Hypertext Markup Language) and JavaScript to construct basic pages for their work and recreation. People from all areas are interested in expanding their skills to include web programming. Now, with the introduction of Tomcat 4, users can set up and run a JavaServer-enabled web server with virtually one mouse click (after unzipping the files). And with JBoss, an enterprising developer can run a full-fledged Java 2 Enterprise Server right on a desktop computer. Unfortunately, many books on server-side development are not properly geared for easing the transition from casual HTML coding to server-side development. We wrote this book to help beginning and mid-level programmers with some familiarity with HTML, JavaScript, and Java grow to be competent server-side developers. The newer breed of workers often does not have the time to return to classes for a thorough computer science education. Although additional education is always a good idea, often mature students retain more information after they have been exposed to practical examples. That’s one of the beautiful aspects of JSP: it’s centered in the Presentation layer, so it provides immediate results, but it can allow developers to build and access Java objects and architectures of infinite complexity. To educate casual users worried about the new demands of their jobs, and to teach seasoned Java programmers something about building a successful and responsible Presentation layer, this book focuses on preparing professional JSP web applications: ◆ ◆
◆
◆
Real-world examples are used whenever possible. This book contains no useless “Hello World” code. Standard Java classes are used as much as possible. All the examples compile cleanly and in most cases can be run independently of the other chapter examples. There are no mystery classes, and the source code for all the classes is readily available on the CD-ROM. The sample applications are thoroughly documented and commented. The code listings are formatted to encourage the reader to examine and read through the code. Part of becoming a good developer is being able to read source code and comments to get an understanding of what the code is doing before running it or stepping through the code with a debugger. Questions are raised, and solutions are provided, but you are encouraged to weigh the pros and cons and come to the proper decision for your situation. Success in the real world doesn’t come from pat, easy answers, but more often from careful deliberation and decisive action.
XVIII
INTRODUCTION
How This Book Is Organized In this book, Chapter 1 introduces JSP and Servlets, the work environment, and it compares JSP with some of the other competing web-programming technologies. Chapter 2 examines HTTP and discusses how web pages interact with servers. Servlets are introduced and used to show how you can build programs by reacting to HTTP (Hypertext Transfer Protocol) client requests. An example shows how you can dynamically configure a servlet , making it easier to work with and maintain. Chapter 3 focuses on JSP processing and how a JSP is built from predefined tags, much like HTML. Scriptlet tags, which allow Java code to be inserted into JSPs, are also introduced and explained with a wealth of examples. The chapter also covers reflection and class introspection, two important concepts for understanding how Java classes interact on the server side. Chapter 4 shows how scripting elements map the basic interactions between a JSP and Java classes. The concept of JavaBeans is gently introduced, leading to its full explanation in the next chapter. Chapter 5 thoroughly explains how JavaBeans are created and how they interact with JSPs to reuse code and reduce page clutter. The chapter illustrates the use of JavaBeans with a sample application that allows a user to customize and set preferences. Every application should implement some form of security or protection against corruption. Chapter 6 addresses some of the security issues of sharing data between pages. It also discusses authentication and gives some general points on security. Chapter 7 shows how to access a database using JDBC (Java Database Connectivity). The chapter also covers techniques for presenting data and basic connection pooling. A sample application is built to illustrate basic SQL database interactions. Chapter 8 addresses the issues of error handling and debugging. The chapter emphasizes the user’s experience, testing, and how to properly communicate error conditions to users. The chapter documents the types of errors encountered while developing JSPs. It also explains exceptions, structured exception handling, and assertions, a new feature starting with Java 1.4. It looks at the methods for logging errors and redirecting output. A sample JSP and a servlet web application show how you can troubleshoot applications by scanning large log files. Chapter 9 discusses how to measure performance and how to communicate performance expectations to users. The chapter also covers designing for performance, optimizing, self-testing, and stress testing. Chapter 10 describes how to present XML (Extensible Markup Language) documents using JSP. XML can be a complicated subject, so we break it into several stages: understanding XML, displaying XML using CSS (Cascading Style Sheets), writing XSL (Extensible Stylesheet Language) templates, displaying XML with XSL references, generating HTML from XML and XSL, and migrating data with XML/XSL. A working XML application completes the chapter. Chapter 11 addresses how you can use JSP to integrate legacy applications. The chapter covers writing Java wrappers and system call wrappers and discusses some of the common languages used for wrapping calls. It presents a simple program wrapper and guidelines and tips for writing and using larger-scale wrappers. The chapter also gives explanations and examples for working with interfaces, such as JNI (Java Native Interface) and RMI (Remote Method Invocation). RMI is the foundation of EJB (Enterprise JavaBeans) the subject of the last chapter.
INTRODUCTION
Chapter 12 shows how you can integrate Java extensions with JSP. The chapter covers changing graphic displays using the JAI (Java Advanced Imaging) extensions, and generating custom graphics with the Java 2D API (applications programming interface). The chapter also shows how Java supports internationalization and localization. Chapter 13 explains the Model-View-Controller (MVC) web application framework and shows how you can implement it using a JSP or a servlet-based controller. The chapter also introduces some helpful utility classes for deploying applications in the real world. A working database application example shows one way of implementing dynamic authentication and handling roles, permissions, and access. Chapter 14 describes some common problems and provides some possible solutions for working with databases. The chapter explains some potential problems that JSP developers might have with the ResultSet class, and provides two possible solutions. The chapter also presents some strategies for moving data access away from the Presentation layer, which is illustrated by a working database quiz application. Predefined JSP tags do most of the work in constructing JSPs. Fortunately, the JSP architecture is flexible enough that it allows developers to create their own custom tags. Chapter 15 shows how to build and use custom tags. It explains tag interfaces and walks users through building and using the basic types of custom tags. The chapter concludes with an overview of the new JSTL (Java Standard Template Library). Chapter 16 shows how JSPs can interact with EJBs (Enterprise JavaBeans). The chapter also presents strategies for removing data interaction code, and the example applications show a databasedriven framework for abstracting SQL queries. Data abstraction is carried a step further using an EJB Entity Bean. EJB testing and development is encouraged by using the open-source J2EE server JBoss. Appendix A contains information on setting up the Tomcat JavaServer, MySQL database, and the JBoss J2EE server. Appendix B covers the JSP and Servlet API. Appendix C contains a Java primer that serves as a refresher on using the tools for compiling and packaging Java programs. These are the two most commonly used skills required by anyone interested in JavaServer programming. Unfortunately, most Java books do not adequately document the compilation and packaging processes. The primer also explains some of the common constructions found in the text. Appendix D covers the proposed JSTL API, and Appendix E lists helpful resources you’ll find on the Web. The CD contains two directories: software and setup. The software directory contains installation files for: Tomcat, Jboss, MySQL, JODE, Jbuilder, Struts, and mm.mySQL Driver. The SRC directory contains packaged war files that you need to install inside the Tomcat webapps directory. I hope you enjoy the book. You can send me a question or a comment by e-mailing me at
[email protected].
XIX
This page intentionally left blank
Part
JSP Basics In this section: ◆ Chapter 1: Introducing JavaServer Pages and the JSP Environment ◆ Chapter 2: HTTP and Servlet Basics ◆ Chapter 3: JSP Processing
I
This page intentionally left blank
Chapter 1
Introducing JavaServer Pages and the JSP Environment In the early days of the Web (1995), a lot of web pages were black text on a light gray background with maybe a color logo. Then Java applets appeared. They became popular and quickly spread around the world because they attracted the viewer’s eye. Providing information took second place to providing users with entertainment. Quickly new technologies such as Flash and ActiveX and updated scripting languages such as VBScript and JavaScript jockeyed to provide dynamic presentations. However, none of the “eye candy” replacements had the Java advantage: platform independence. This advantage would later make a crucial difference in the proliferation and adoption of Java as the preferred server-side solution, and eventually it was decided that JavaServer Pages would be the official format for presenting enterprise Java on the Web. In this chapter, we’ll discuss the role of JSP and its advantages, and we’ll compare JSP with similar technologies. We’ll also present an overview of web programming as a background for learning JSP. We’ll look at several of the available web server environments for JavaServer engines, and last we’ll look at some of the client-side Integrated Development Environments (IDEs) useful for developing JSP pages. The examples in this book will use the Tomcat Java server. (For Tomcat setup instructions, see Appendix A.) Featured in this chapter: ◆
Web programming overview ◆ Background for learning JSP ◆ The various web server environments ◆ Client-side IDEs
4
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
The Growth of Server-Side Java and JSP’s Role From the beginning, Java’s marketing mantra was “write once, run anywhere,” and properly written, Java could be labeled 100 percent pure Java—meaning that it could run on any platform with a Java virtual machine. Of course, poorly written code might only run on one operating system, if it ran at all. Platform independence is an important feature of Java, and it has helped establish Java as a standard language that can unify all the operating systems serving pages to the World Wide Web. Although supporting plurality is important, statistically the Web is served overwhelmingly by Apache web servers running on Unix, or *nix. Note The abbreviation *nix is often used to refer to the many flavors of Unix, for example, HP Unix, SGI Irix, Linux, Sun Solaris Unix, FreeBSD, and so on. For a long list, go to www.ugu.com. Note Apache is an open-source web server, one of the most common in the world. Developed by the Apache Software Foundation, it has been around since 1995. The Apache Software Foundation also provides support for the Jakarta projects, all written in Java, with Tomcat being the foundation’s implementation of the JavaServer and JSP specification.
With such a large variety of web server operating systems, the “write once, run anywhere” mantra becomes more than a marketing buzzword—it’s a necessity. Also the creators and owners of Java, Sun Microsystems implement the Java environment on Unix (Solaris source code is available), whereas the Microsoft Windows Java environment has to function on top of the “black box” of the windows code. Fortunately, virtually all Java implementations have smoothed out their inconsistencies, so Java is now a stable, enterprise-ready environment. You can see why a Java environment is the natural choice for a majority of web servers.
What Is a JSP Page? A JSP page is an HTML web page that has been enhanced by the addition of special tags and Java code, both of which are used by the web server and the JavaServer Engine to create a page for a client’s web browser. Note JavaServer Pages (JSP) is a server-side programming language. The raw Java/JSP code never reaches the client. Java can be used on the client side in the form of applets, or applications installed on the desktop. Warning
The closest client-side scripting language is probably JavaScript. But JavaScript is not Java!
The JavaServer Engine strips out the special tags and Java source code and uses the code to interpret and create the page that the web server sends out; no Java code is actually sent to the client. Thus, any web browser with or without Java installed can use a JSP application! The JSP page is actually compiled into a servlet on the Java-enabled web server; thus to serve out JSP pages, a web server must have a JavaServer Engine installed or provide this functionality. Later in this chapter, we’ll look at different JavaServer Engines and JSP development environments. Server-side Java was a late entry to the game; servlets only became possible with the release of Java 1.2. A servlet is a Java program that runs only on a Java-enabled web server servlet container. A servlet container is a JavaServer Engine that can host servlets and JSP pages. For example, Apache’s
THE GROWTH OF SERVER-SIDE JAVA AND JSP’S ROLE
Tomcat is a servlet container. A servlet is designed to run only on a web server inside a servlet container; you cannot run a servlet as a standalone application or in a browser window, but a browser can send requests and receive responses from a servlet. A servlet receives a request, processes some information, and returns a result. That may sound vague, but it has to be said that way because servlets have a certain quality of vague flexibility. For example, you could design an application so that a client could request information about a race horse. One servlet could then return the statistics, while another servlet could return a picture of the horse. Another servlet might call the database to record the popularity of the horse and check the client’s connection speed. If the client happens to have a small screen or a slow connection, another servlet could pass the information on to an image-formatting servlet, which would then return the final processed page. Servlets can be chained together so that they go far beyond the typical web paradigm of one page request returning one page view. HTTP servlets behave similarly to CGI programs: they accept raw input from a client’s browser, process the data, and return a result. The idea was that they could provide additional functionality at a crucial stage. For example, using regular HTML, a website can direct users to a selection of products, cache the selections (albeit somewhat awkwardly), send the user to an order submit page, process the final order by checking the parameters, call a database to log a charge against the customer’s account, and remove the item(s) from inventory. CGI programs were written in the C programming language, whereas servlets take advantage of Java’s structured exception handling. As you will see, the JSP environment has further improved the handling of errors. Beyond mimicking the behavior of CGI programs, Java servlets added Session and Servlet Context objects. We’ll look at these in depth in Chapter 2.
Why Use JSP? The following are some of the advantages associated with JSP: ◆ ◆ ◆ ◆ ◆
JSP encourages platform independence: conscientiously written code can be written once, run anywhere. JSP is the preferred Presentation layer for enterprise services. JSP provides stability by allowing developers to use and integrate established, thoroughly tested Java code. JSP can encourage a clean separation of the Data layer from the Presentation layer of an application. JSP’s seamless integration with the Java2 Enterprise Edition services encourages the development of extended architectures, not just a series of web pages linked together.
In addition to serving JSP pages, the JavaServer Engine provides functionality and memory for creating objects that persist across the user’s session state. Thus, a user can visit a page, begin an order, look at some unrelated pages, perhaps browse through similar products—with the JavaServer Engine patiently holding onto the user’s shopping cart selections—and then return to complete the order. All the behind-the-scenes caching of the user selections happens without extra code. Numerous time-savers and opportunities for code reuse make JSP popular for developers, especially compared with the options.
5
6
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
Learning JSP: How Hard Is This Going to Be? From our experience of observing and teaching people new to JSP, we have found that given enough enthusiasm and effort anyone can become proficient in JSP and web programming. Different backgrounds, however, present different challenges. Getting into JSP with a Background in HTML
Coming from an HTML background centers the developer on the user’s experience. HTML coders usually know what works for users, and usually they can give a fair estimate of what’s possible and how long it will take. The danger is that they might get hypnotized by flashy graphics instead of getting their application to talk to the database. The most difficult part for someone with heavy HTML experience is that Java is not JavaScript; although many features of the languages are similar, they are two different languages. The challenge depends on how much Java you want to learn. Just enough Java to create good JSP pages is within ready grasp; proficiency in the fine points of graphic user components, for example GUI applets that enhance a JSP, will take longer. Depending on your situation and needs, the learning curve may not be a great barrier; the more complex features of Java and JSP are getting easier to use all the time through pre-packaged JavaBeans, Java classes, and JSP tag libraries. We’ll look at these technologies in depth in the coming chapters. Getting into JSP with a Background in C/C++ or Java Application Programming
Sooner or later, every application programmer longs to put up a web page or even get a web page to run their program. This desire arises because the web is everywhere and because these days HTML documentation of source code is a standard feature of many tools. For example, javadoc, a program bundled with the Java Development Kit (JDK), produces hyperlinked HTML files from Java source code. Many other IDE vendors have followed suit, adding this functionality to generate HTML road maps in C, C++, and other languages. The most difficult part for application programmers is remembering and understanding the end user. This viewpoint is deceptively simple, and many engineers often quickly forget that a web application lives or dies by the user’s approval. In a way, it’s not surprising that they don’t put the user first because until recently university computer science courses often didn’t give due emphasis to designing for end users. Many companies deal with this apparent skills gap by including a graphic artist and sometimes a creative director on a project team. This approach is a good management technique for remedying imbalances; however, it’s far more efficient to anticipate the problems and deal with them at the source. The more you understand, the more you will be valued as a developer. Although there may be a practical limit on how much technical knowledge you want to acquire, interpersonal understanding—such as the insight into what users want in a web page form and how they want to be able to find help—will often play a more important role in projects and promotions than technical know-how. Many books can help you understand the sometimes inscrutable demands of users and managers. We recommend Designing Web Usability, by Jakob Nielsen (New Riders Publishing, 1999), for excellent insights and more than common sense, and The Inmates Are Running the Asylum, by Alan Cooper (Sams, 1999), for a detailed look at how to harmonize software design and user needs.
WEB PROGRAMMING LANGUAGES COMPARED
Web Programming Languages Compared As the web has grown, the demand for flexible ways to design it has only increased. Web programming languages have made difficult tasks easier and turned impossible ideas into attainable goals. In this section, we’ll look at some of these languages. We’ll point out their advantages and disadvantages and, as appropriate, discuss the advantage of using JSP instead of one of these languages.
Perl Perl (Practical Extraction and Report Language) handles the processing and formatting of text exceptionally well. It can be expanded by the use of modules of code and is supported by many operating systems. CGI (Common Gateway Interface) is the use of Perl in a web server environment. Perl can be resource expensive because there’s no built-in functionality for sharing application resources, for example, session tracking, database connection pooling, and so on. CGI/Perl has limited errorhandling capabilities. The Web was first programmed with CGI scripts, and Perl remains largely procedural, which is excellent for simple tasks but poses special problems for code reuse. Often Perl is difficult to learn because of its many idiosyncratic language constructions. The JSP advantage over Perl is that JSP provides special, customized error handling, which we’ll look at in detail in Chapters 4 and 8.
ASP (Active Server Pages) ASP is a scripting language similar to JSP that provides native support for documents created with Microsoft products, for example, an Excel spreadsheet. ASP is proprietary, however, and runs only on Windows web servers. Note Some software companies have/are developing ASP engines/interpreters for non-Windows platforms; however, developers must nevertheless be proficient in the proprietary Microsoft languages. VBScript, C#, and Microsoft’s ASP framework leave significant portions of the architecture components in limbo. ActiveX data objects, COM (Component Object Model) DLLs, and COM servers must be served up from a Windows Registry and a Service Control Manager (SCM).
Both ASP and IIS (Internet Information Services), Microsoft’s web server, rely on the COM/ COM+ enterprise application framework being hosted on Microsoft servers. This arrangement can limit the flexibility of an application as it places demands on a business’s hardware and software choices. The advantage of using JSP rather than ASP is that JSP is cross-platform ready, without any functionality being crippled. JSP’s backbone Java architecture allows supporting components to be distributed in source form or near equivalents, allowing greater user-ownership of the product and the potential for more thorough debugging (the source can be decompiled); whereas ActiveX and the COM/COM+ architecture models aim to produced discreet “black boxes” of software tied to a Windows machine.
7
8
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
ColdFusion ColdFusion is fairly unique among web application tools because it uses a tag-based scripting language. When you view the source files of an application created in ColdFusion, you see tag sets that behave much the same as HTML tags. Thus, ColdFusion has an edge in projects in which programmers and graphic designers collaborate. Programmers can build some fairly sophisticated web applications that nevertheless allow designers to find their way around the tag-based source code even if they aren’t familiar with programming. ColdFusion is also extensible, meaning that if you find a task it can’t handle, you can create a solution with another programming language such as Perl or C and then seamlessly integrate it with ColdFusion. ColdFusion’s tag-based language may also be its biggest drawback. Although the tags provide shortcuts to common programming tasks, they can also create unwieldy code that’s difficult for anyone but the original programmer to troubleshoot. Also, unlike many of the tools described here, ColdFusion Server is an application that must be purchased and installed in conjunction with your existing web server. Many web-hosting services support ColdFusion, but you can expect higher monthly rates.
PHP: Hypertext Preprocessor PHP is an open-source scripting language, and as such it has the potential to change faster; individuals can participate in the development and maturation of the language. PHP is a late entry in the arena of web server programming languages. It has an unusual scripting syntax, which is a mix of Perl, C++, and Java. Although PHP was originally designed for small sites, it’s now striving to grow and achieve speed and efficiency. Many web programmers select PHP because a number of free, open-source portal and bulletin board software modules are available. JSP has an advantage in that its underlying language is Java, one of the world’s most popular programming languages. PHP’s language is powerful, but many managers and companies may be discouraged from using PHP because it can be more difficult to find developers and support personnel to write and maintain the code.
JSP in Various Server Environments JSP can’t be run standalone for a couple of reasons, but for each reason JSP gains an advantage: ◆
JSP pages must be compiled before they are served. The JSP source files are changed from ASCII text into Java byte code, which speeds up their execution and allows the web server to cache them in memory.
Note The only disadvantage of the compiling and caching mechanism is that, in most cases, during debugging, a developer must stop the web server, manually delete the compiled pages, upload the new source files, and restart the web server. Otherwise, the old JSP pages will be served up, often even in the presence of newer source files! ◆
JSP pages run inside a servlet container that is usually part of a larger JavaServer Engine. That engine is usually part of a larger J2EE architecture. Because JSP pages must be hosted by a JavaServer Engine, they are always ready to integrate with other J2EE services as they come online.
JSP IN VARIOUS SERVER ENVIRONMENTS
What Is J2EE? J2EE (officially, Java 2 Platform, Enterprise Edition) is a set of standards that allows for a unified back end for business architecture, including the following services: ◆
Middleware: EJB (Enterprise JavaBeans) and JMS (Java Message Service)
◆
Data management: JDBC (Java Database Connectivity) and the extensions that some database vendors provide in their JDBC drivers
◆
Transactions: JTS (Java Transaction Service)
◆
Directory services: JNDI (Java Naming and Directory Interface)
◆
Presentation layer: servlets and JSP
The items in this list account for the information management needs of most businesses. Indeed, the scope of J2EE is so large that most people specialize in a particular area. Sections of the rest of this book will deal with two of the major services, EJB and JDBC.
Which Java Environment? Now that you need a JavaServer environment, which one is best? Well that depends. At most companies, the Java environment is decided for you by issues of cost, availability of support, and the experiences of other developers and managers. However, because you might be called on to give an educated evaluation, and because you might have to work with one or more of these systems, it’s important to learn their names and something about their features. Tomcat
Tomcat (see Figure 1.1) is the Java Servlet container implementation for the Java Servlet specification and the JavaServer Pages specification. It’s different from the other Java environments described here in that by itself it doesn’t provide all the features of a Sun-certified J2EE environment. Regardless, Tomcat has been and will continue to be the backbone of Java development. FIGURE 1.1 Tomcat JavaServer Engine at startup in a console window
9
10
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
Tomcat is free software from the Apache Software Foundation, which readily provides the source code and binaries (see www.apache.org and http://jakarta.apache.org). Tomcat and other Apache projects are maintained and developed by open-source developers, people contributing to the Apache software community by working in their spare time. These developers do not earn money for their work but share in the successes of their contributions. Apache is one of the leading web servers on the internet. An October 2001 survey discovered that 56 percent of the sites on the Internet were being served up by Apache. Jakarta is the group name for Java server software developed by the Apache Software Foundation. Their list of web server extensions continues to grow and includes valuable tools that enhance Java, notably the following: ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆
Ant 1.4.1, a tool for automating the building of applications; extremely helpful for compiling complex applications composed of numerous files Cactus 1.2, a framework for the automatic testing of server-side code ECS 1.4.1, a Java package and API (applications programming interface) for generating and formatting the elements for HTML 4, XML, and others James 1.2.1, the Java Apache Mail Enterprise Server Jetspeed 1.3a2, an open-source information portal JMeter 1.5, a pure Java desktop application for testing log4j 1.1.3, software that allows logging to be turned on at runtime ORO 2.0.4, a library that provides text-processing Java classes similar to Perl, AWK, and more Slide 1.0.16, WebDAV (WWW Distributed Authoring and Versioning) modules; for remote website maintenance and authoring Struts 1.0.1, a revolutionary application framework for providing clean Model-View-Controller designs Turbine 2.1, a secure servlet framework
Just as the Apache web server has revolutionized the Web, we expect the Jakarta subprojects to engender major, industry-wide changes. iPlanet/Netscape
Netscape merged with iPlanet, and both companies are owned by Sun Microsystems, the creators of Java. iPlanet provides development environments and enterprise application servers. iPlanet is an excellent choice when funding is available. Their products make extensive use of XML. WebLogic
WebLogic was one of the first companies to make a big name in the J2EE application server market. Even though it can be prohibitively expensive, it has remained popular with developers and businesses largely due to its reputation for providing a robust environment.
JSP IN VARIOUS SERVER ENVIRONMENTS
Web-Sphere
Web-Sphere is IBM’s J2EE system. IBM is a major Java player, and WebSphere has proven itself by supporting some extremely large sites, such as eBay. Oracle9i Application Server
With the release of its 9i application server, heavyweight competitor Oracle is offering J2EE support to augment its position as one of the premier enterprise database companies. Oracle is only continuing to expand its support of Java and XML, and the future looks very promising. JBoss
Sun and IBM have declared J2EE development an open-industry process. Both companies compete with their own proprietary (closed-source) J2EE application servers. An excellent open-source J2EE solution is emerging: JBoss. JBoss is a complete J2EE solution that provides an EJB container, JMS messaging, mail services, JTS services, security services, connectivity, and persistence. Additionally, JBoss has, unbelievably, several features that aren’t available in the other J2EE application servers. The only problem with JBoss is that it awaits Sun certification. As a result, the business rules of some companies will not yet allow them to support their enterprise architecture using it.
Fast-Brewing Java on the Client Side Compiling a small Java application from a command-line window is easy enough, but even talented programmers have difficulty guessing how a graphical layout will look. Running the application after every visible change is a horribly inefficient use of time. An IDE eases the pain of nontrivial development tasks by providing a visual interface for developers to navigate their projects, dragging and dropping components onto visual layout managers. Most IDEs provide all the features a developer needs to code, debug, test, package, and deploy standalone applications, web applications, libraries, and anything else a developer would want. Warning An IDE lets you work faster and potentially learn more; however, it’s important not to lose sight of what the IDE is doing and which commands it is running. Otherwise, your understanding might become superficial, your visualization skills might be impaired, and you might feel helpless if you are called on to debug your application with a minimum of tools, as in a server room without the comfortable, cute graphics of your favorite IDE.
Because developers spend so much time with IDEs, often looking at them with the same microscopic vision they train on obscure passages of code, it’s inevitable that annoying bugs will crop up and be noticed. Initially, Sun released Java as a language and encouraged other companies to create tools and development environments. Although all the IDEs contributed helpful features, many of them surreptitiously bundled in and encouraged the use of additional, semi-proprietary code, all to encourage loyalty to and dependency on the parent company. For example, one early IDE allowed users to build fairly complex applets by drag-and-drop and using interactive wizards. It all worked beautifully in the IDE, but when users tried to package and deploy the applet, they found that proprietary mouse-handler classes and a slew of other unnecessary class libraries had to be included. The applet usually became too large for an impatient user waiting with a modem. Many
11
12
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
of these horrible “planted” bugs should have been worked out by now, but a clear lesson remains: be aware of the possible hidden price of time-saving routines, and always check to see what your IDE is doing under the covers. Often in the working world, the choice of an IDE is moot because businesses standardize their development on a particular product. However, businesses do change their minds, and sometimes management listens to developers. Since so much of your time will probably be spent in front of an IDE, it’s important to watch for changes and new features that, given some effort to learn, might make your work easier. By all means, download some of the following, even just the trial versions, to keep yourself familiar with what is possible. Note Since the URLs for downloading sample IDEs often change, we’ll reference only the vendor. Search for the vendor’s site on the Web, and choose the appropriate IDE for your needs. JBuilder
JBuilder is a great IDE because it is flexible and gives users many choices. For example, the web server it uses can be upgraded to a newer version of Tomcat. By default, JBuilder uses Tomcat as its web server. Figure 1.2 shows the JBuilder IDE. FIGURE 1.2 The JBuilder IDE
Note You can easily run all the book’s sample project files on the CD-ROM under JBuilder, and almost all the illustrations in the book will use JBuilder. Of course, you can also run the projects and code on a standalone installation of Tomcat. We’ll show you how to package web applications for individual Tomcat deployments in Appendix A.
JSP IN VARIOUS SERVER ENVIRONMENTS
You can use the JBuilder IDE to preview basic HTML layout, as shown in Figure 1.3. However, JavaScript code doesn’t always work in the window, and server-side code won’t display properly since it requires a running Java environment to provide the dynamic content. FIGURE 1.3 The basic HTML layout of a JSP page displayed in JBuilder
The JBuilder IDE has some useful features. For example, each source file has integrated graphical source control, as shown in Figure 1.4. FIGURE 1.4 JBuilder Source Control
13
14
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
JBuilder also provides extensive debugging information, as shown in Figure 1.5. FIGURE 1.5 JBuilder debugging information
Notice the Query String parameter in Figure 1.5. If the page had HTML inputs inside a pair of tags, the inputs and their values would also be shown, as in Figure 1.6. Here, you can see that the JBuilder debug window shows everything the user submits and what happens to those values along the way. FIGURE 1.6 JBuilder debugging information in detail
JSP IN VARIOUS SERVER ENVIRONMENTS
JDeveloper
JDeveloper is a free IDE that Oracle released to promote the use of Java and Oracle. Oracle is a big supporter of Java, and in fact the Oracle software installers and the GUIs are written in Java. The JDeveloper IDE is similar to an older version of Borland’s JBuilder, but whatever its origins, the latest release encompasses all aspects of JavaServer programming, and the IDE is tailored with built-in functionality to interact with Oracle applications and databases. Also, the IDE comes with an impressive number of supporting libraries. Forte for Java
Forte is Sun’s late entry into the Java IDE arena. Sun bought Forte from a private company and released a version to the public. You can choose between using a single document interface (SDI) and a multiple document interface (MDI). Figure 1.7 shows the windows docked together and attached to the toolbar. FIGURE 1.7 The Forte IDE
Unlike Sun’s Forte for C++, Forte for Java is free. A Forte Internet edition, with many useful features for programming JavaServer code, is available for a considerable fee. The free version comes with many useful options found in more expensive IDEs. Figure 1.8 shows the Forte Object Browser, useful for finding method names inside packages.
15
16
CHAPTER 1
INTRODUCING JAVASERVER PAGES AND THE JSP ENVIRONMENT
FIGURE 1.8 The Forte IDE showing the Object Browser
The expanse of Forte is impressive; however, many users find it slow unless run on a computer with lots of memory, so your mileage may vary. Under similar stresses, JBuilder seems to fair better. VisualCafé
VisualCafé is another Java IDE. Over several releases, it has maintained a high-quality user interface with extensive assistance for developers. Unfortunately, its price has been prohibitively high. Visual J+/Visual J++/Visual J#.net
Visual J is Microsoft’s Java IDE. We mention it here cursorily because it still seems to persist, albeit in some sort of mangled form, and JSP developers are likely to run into it somewhere on an old machine. There is still great suspicion about what Microsoft is trying to do with Java. The Sun vs. Microsoft Java lawsuit, after years of litigation, was settled out of court with Microsoft paying somewhere in the neighborhood of 20 million dollars. Fortunately, you can now choose from many alternative IDEs. Other IDEs
The previous list is not exhaustive, and new, helpful additions will surely appear. If you ever find yourself frustrated with your current IDE, give one of the others a try, or surf around and see what’s new.
SUMMARY
What You Need to Get Started For the examples in this book, we’ll use Apache’s Tomcat. Tomcat has been chosen as Sun’s reference implementation for the latest JSP specification (1.2). Tomcat is also free and open source, so you can’t complain about the price, and if you want to know what’s really going on, you can browse its source. Better yet, if you have any spare time, you can contribute to the Tomcat project or to any of the other Jakarta projects. Note Apache is perhaps the most successful free software endeavor, with its web server dominating the World Wide Web. Its Java projects lead the industry in setting standards. Time spent with Apache software is an excellent investment.
To install Tomcat, you need about 34MB of disk space and an operating system that includes a Java 2 release (Windows, Linux, Solaris, Macintosh, and so on). It’s recommended that you also install the Java Development Kit (JDK) for your system so that you’ll have access to the additional tools, javadoc, the debugger, and so on.
Summary Java grew out of its initial appearance in cute applets to become the ideal solution for server-side web programming. Compared with other scripting and web programming languages, Java is as good or better. JSP can leverage the use of server-side objects and even embed Java code right into the script of the web page—and it will still run on any platform. JSP pages and servlets are inextricably linked. JSP pages make the Presentation layer more manageable, and servlets shore up the processing and facilitate lean, economical communication with other enterprise entities such as databases, messaging services, transaction services, and just about anything else related to the information needs of a business. Today, you can choose from several JavaServer environments, and more are becoming available every day. Price is no longer an issue, because open-source development has made Tomcat web server available free, and there’s even a free J2EE Java environment—JBoss. And with Forte from Sun, it’s possible to get a Java IDE for free.
17
This page intentionally left blank
Chapter 2
HTTP and Servlet Basics Before starting to program for the Web on the server side, most people know how to get around on the Web and use it. Most people are familiar with the Web and at some time or another have done the following: ◆ ◆ ◆
Typed a web address or clicked a link Used a form on a web page to submit an order or information Attached and e-mailed a file using a web-based e-mail client
These are all examples of using the Hypertext Transfer Protocol (HTTP) commands GET, POST, and PUT. In the first section of this chapter, we’ll look at these commands in detail and see how they relate to server-side programming. But first, while we’re on the subject of what’s familiar, let’s review the limitations of these commands, which you may already be familiar with: ◆ ◆
◆
A web search engine returns a list of sites, and you click an entry only to receive an error message “404 Request Not Found,” which indicates that the site isn’t available. You submit an order or a survey, and then using the browser’s Back button, you try to go back and double-check on the quantities to make sure you entered everything correctly, but the data you entered is gone. You try to upload a file to a web-based e-mail client, but after waiting a long time for the file to be attached, the web server informs you that the file is too large to attach.
Note Often HTTP is listed alongside another protocol, for example, HTTP TCP/IP. In this case, HTTP has been implemented over TCP/IP (Transport Control Protocol, Internet Protocol). TCP specifies the way data or HTTP requests and responses are packaged into packets and shipped around the web; IP specifies the address system, for example, http://192.168.1.1 or http://www.yahoo.com.
To understand these commands and limitations, you need to understand HTTP. An operation that is the result of a command is an HTTP request, and it originates from the client. By contrast, a
20
CHAPTER 2
HTTP AND SERVLET BASICS
web server provides an HTTP response to an HTTP request. This exchange is the standard means of communicating on the web. Featured in this chapter: ◆
How HTTP works Understanding HTTP requests and responses ◆ Programming servlets
◆
Behaviors and Limitations of HTTP HTTP is stateless protocol that relies on the immediate or nearly immediate processing of requests. Requests are sent immediately, and, ideally, they are processed without delay. However, delays happen. Sometimes web servers are overwhelmed by more requests than they can handle. Sometimes the web server and the client aren’t directly linked so that information must be routed through several intermediary servers and routers, each of which can add delays. In short, many things can cause a delay. HTTP has a built-in mechanism to allow some flexibility with the time it takes to deliver requests: timeouts. A timeout is the length of time a client waits for a request to be returned. Because of the immediate nature of HTTP, requests are not cached. For example, a search engine may have a listing for a website, but if you click the link and the site is down or otherwise unavailable, HTTP by itself returns an error message “404 Request Not Found.” Note A proxy can be used to cache pages, making them appear when the original web server is down. Often an organization uses a proxy to ease the strain on a network by holding copies of frequently accessed pages. However, a proxy can cache only static pages; dynamic pages require the interactivity of a live web server.
HTTP requests and responses are wholly independent. Each HTTP exchange exists in a vacuum. Web clients are not able to communicate to the web server if the packets get lost, there’s no confirmation of delivery, there’s no accounting to keep track of previous attempts to communicate, and they are not privy to the contents of previous exchanges. In addition, because HTTP is stateless, HTTP requests and responses do not retain any information passed if it doesn’t go through. For example, you might compose an e-mail message using a browser-based web e-mail system, and press the Send button. If the message (using POST) doesn’t go through, the browser displays an error page, and an attempt to return to the letter to resend displays a blank form with the contents wiped away—even though HTTP failed to submit the contents! This inability to retain contents seems like a terrible disadvantage, but users would demand this behavior if they stepped away from their e-mail browser and somebody tried to press the browser’s Back button and see or change what was written. Here’s another limitation example. You try to upload a file to a web-based e-mail client, but HTTP can’t tell if the information it’s trying to pass (the file being uploaded in a POST) is too large for a web server’s buffer or if it’s so large that it might time out with a slow connection. As a result of these constraints, you might be tempted to say that HTTP is not a “smart” protocol, but a choice of economics and perhaps of choosing the lesser of two evils. HTTP has provided great flexibility and allowed the Web to grow and support the internet and intranets for business. Users
THE HTTP REQUESTS
appreciate applications that guide them and help solve some of the problems that can appear because of HTTP’s stateless protocol, and you’ll see that JSP is well suited for this task.
The HTTP Requests HTTP works by requests and responses. In the simplest terms, a user makes a request by entering a website address, and the browser returns the page. That single transaction may actually consist of many small requests and responses, such as a request and a response for each image on the page. A response can also be an error message, perhaps indicating that the requested resource isn’t available or that the server is too busy to respond properly. A web server sends error messages because HTTP doesn’t have any built-in transaction mechanism. HTTP is stateless; that is, the Transmission protocol doesn’t remember anything from one request to the next. This is good because it makes the Web uniform: if multiple users request the same page, they all get the same page. However, because users often want their settings remembered and their browsing experience to be easier, web developers must look outside the capability of HTTP. Fortunately, doing so gives your JSP applications a chance to shine, as you’ll see in the coming chapters. If a user gets the impression that the Web remembers, most likely a Web application is doing its job to make the user’s life easier. Requests can take a number of forms. The following sections describe in detail the principal HTTP requests: GET, HEAD, POST, PUT, DELETE, TRACE, and OPTIONS.
The GET Request The GET request attempts to return the resource represented in a URL (Universal Resource Locator). When a user enters a simple URL such as http://www.yahoo.com, they are issuing a GET request. In web programming, the GET request also ferries what is referred to as the query string, a list of parameters attached to the URL after a question mark, represented in URL-encoded characters. For example, the following is a query string: http://localhost:8080/requestdump?Question=what+is+a+bird%3F
Here’s how a URL would look packed with multiple parameters: http://localhost:8080/requestdump?Question=what+is+a+bird%3F&Question2=what+is+ knowledge%3F
Seeing the HTTP Exchange Several times in this chapter we will look at the raw HTTP request response exchange. Fortunately it’s possible to do this in a very concrete manner using Telnet. Enter the following on a command line: telnet GET /index.html HTTP/1.0
Continued on next page
21
22
CHAPTER 2
HTTP AND SERVLET BASICS
Seeing the HTTP Exchange (continued) and then press Enter twice. The console window displays the HTML page. Since HTTP is stateless, the telnet connection closes immediately after receiving the data from the server. To view header information, enter the following: HEAD /index.html HTTP/1.0
and press Enter. This information can be invaluable in determining if the web server is up and running. Here’s a sample: HTTP/1.1 200 OK Date: Thu, 11 Apr 2002 22:15:11 GMT Server: Apache/1.3.12 (Unix) Last-Modified: Tue, 19 Mar 2002 23:59:02 GMT ETag: "dc762-dcc-3c96d0c6" Accept-Ranges: bytes Content-Length: 3532 Connection: close Content-Type: text/html Connection to host lost.
A lot of information is displayed here, including the server time, the last time the page requested was modified, the length of the page in bytes, the kind of web server delivering the page, and even the version of the web server! If you’re having trouble running any of the examples, at home or at work, be sure to verify that your web server is properly responding to basic HTTP transactions.
The HEAD Request The HEAD request is identical to GET except that the server is prohibited from sending a message-body in the response. The information contained in the HTTP header of a HEAD request is identical to the information sent in response to a GET request. You can use the HEAD request to obtain meta-information about the entity implied by the request without transferring the entity-body itself. You can also use the HEAD request to test hypertext links for validity, accessibility, and recent modification. In addition, some browsers send a HEAD request for a document and compare the information with a similarly named page in their cache to determine if the page has changed. A modification is indicated by a change in ContentLength, Content-MD5, ETag, or Last-Modified. Figure 2.1 shows HEAD information. Figure 2.1 The HEAD information from a connection to a web server
THE HTTP REQUESTS
Warning Many web servers implement HTTP 1.0 or implement the HEAD command incorrectly, returning the body of the document like a GET request. Note The W3C (World Wide Web Consortium) has an open-source Java web server, Jigsaw, that provides a reference implementation of HTTP 1.1. You can find recent documents and code at www.w3.org/Jigsaw/.
The POST Request The POST request pushes a form body to a web server to do the following: ◆ ◆
Post a message to a bulletin board, newsgroup, mailing list, or similar group of articles Provide a block of data, such as the result of submitting a form, to a data-handling process
The actual function performed by the POST request is determined by the server and usually depends on an application linked to the Request-URI. The posted entity is held in the body of the URI (Uniform Resource Identifier). Note The Request-URI is commonly known by the action parameter inside an HTML form tag. For example, in the action tag indicates an object that can process the values packaged inside the body of the POST. In the example, a relative URL points to a servlet. It’s called a URI instead of a URL because a URL by definition only points to a location, such as /index.html, which can’t by itself process the values contained in the POST. In large, the naming distinction merely emphasizes that special objects or programs must process a POST; a POST doesn’t persist beyond its initial destination.
For a long time, browsers implemented POST as a semi-secure way to handle data. For example, if you fill out an order form, POST it, and then click the Back button, the order form is blank, thereby eliminating the danger of accidentally submitting the same order twice. Although this probably delighted people in inventory and shipping-and-handling departments, it greatly frustrated end users. Many current browser implementations actually retain information that has already been posted or at least prompt the user that they are going to try to reload the form data that has already been submitted. The main difference between submitting a form using GET and POST is that GET shows form parameters appended to the query string, whereas POST passes form parameters along in the body of the request.
The PUT Request PUT was designed to place files on the web server. Because HTTP doesn’t provide built-in access and security features (those features are the responsibility of applications and administrators), PUT is not usually implemented directly. You can control the uploading of files by using a POST form, which sends a file as a MIME (Multipurpose Internet Mail Extension) encoding type multipart/formdata, and with specialized code and application programming on the server side.
The DELETE Request DELETE was designed to remove files from the web server. Like PUT, most often it is not implemented
because of security and administration concerns.
23
24
CHAPTER 2
HTTP AND SERVLET BASICS
The TRACE Request The TRACE request is used in debugging to send back the request message. It’s primarily helpful for diagnosing forwarding problems when the HTTP request must travel through a series of proxies. The average web developer will probably not find the TRACE functionality terribly useful. The TRACE message is supposed to be sent back as the body of a 200 (OK) response and not simply thrown as an error. TRACE has some useful features for debugging, namely the via header field and the max-forwards field. The value of the via header field acts as a trace of the request chain. Used in conjunction with the max-forwards header field, it allows the client to limit the length of the request chain, which can be useful for tracking down and testing a chain of proxies forwarding messages in an infinite loop. You can use the max-forwards request-header field to target a specific proxy in the request chain. When a proxy receives a request on an absolute URI for which request forwarding is permitted, the proxy must check for a max-forwards field. If the max-forwards field-value is zero (0), the proxy can’t forward the message and instead must respond with its own communication options. If the max-forwards field-value is an integer greater than zero, the proxy decrements the field-value when it forwards the request. If no max-forwards field is present in the original request, the proxy must not attach a max-forwards field when it forwards the request.
The OPTIONS Request The OPTIONS request asks for information about the communication options available on the request/response chain identified by the Request-URI. This request allows the client to determine the options and/or requirements associated with a resource or the capabilities of a server, without implying a resource action or initiating a resource retrieval. The OPTIONS method was largely designated to be a server-to-server query-and-response mechanism. If the OPTIONS request includes an entity-body (indicated by the presence of Content-Length or Transfer-Encoding), the media type must be indicated by a Content-Type field. To request and receive the OPTIONS method from a web server running on your local machine, follow these steps: 1. At the Windows command prompt, type telnet and press Enter to display the following prompt:
2. Specify the address for localhost, 127.0.0.1, and the port the web server is running on, usually
8080, inside an IDE as follows:
THE HTTP REQUESTS
3. Press Enter to connect. You’ll see the word “Connecting” with three dots after the machine
name, signifying that the program is waiting for more input. Although the cursor appears to be at the end of the line in the following graphic, it will jump to the top of the screen as soon as you type something. (This doesn’t always happen, but sometimes that’s just Windows. We haven’t observed this behavior in Linux.)
4. Enter OPTIONS / HTTP/1.0. Notice the input scrolling along the top of the document
in the following graphic.
5. Press Enter twice to clear the screen will clear and display the OPTIONS information:
The message “Connection to host lost” refers to the Telnet application’s expectation that a connection will be maintained in contrast to HTTP’s constraint that all connections are stateless and that each request is essentially disconnected from the others.
25
26
CHAPTER 2
HTTP AND SERVLET BASICS
Now that you’ve seen the basic transaction mechanism of the Web, wouldn’t it be nice to manipulate it and be able to write programs around it? That’s where servlets come in.
HTTP and Servlets Before JSP was introduced, developers could use only HTML pages and servlets for web programming and providing dynamic content. Although this was bad, it wasn’t the end of the world; after all, a JSP page is compiled into a servlet. But now that we have JSP, Java servlets are still valuable for providing a higher level of architectural abstraction and security. Let’s start by looking at what a servlet is and how it interacts with HTTP.
Servlet Basics A servlet is a Java class that wraps HTTP interactions. It does this by providing a framework in which developers can write Java code that handles each HTTP request (usually GET and POST, but it’s also possible to implement the others). The servlet classes are properly called a Java extension because they are not a central part of the Java language. Servlets are distributed and installed as an extra package, and this is evident in their class names, which begin with javax. instead of java.. Let’s take a brief look at these required classes: javax.servlet.Servlet Specifies the servlet interface, which is further distinguished into the javax.servlet.http.GenericServlet class. Defines an interface for a generic, protocol-independent servlet. Developers can customize the interaction and handling of data by overriding the service() method.
javax.servlet.http.GenericServlet
javax.servlet.http.HttpServlet Specifies the interface for an HTTP servlet; the most commonly used class. When a web server receives a request pointing to a servlet, it calls the servlet’s service method, which handles the request and accepts a response object that will be returned to the client. Regular HTTP servlets do not need to override the service method; instead, they can override the methods that service delegates to, namely, GET and POST. Here are the function prototypes for those methods: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
Before anything can be sent to the client, the JavaServer engine must know the format of the character set. To specify the format, you set the content type as follows: public void ServletResponse.setContentType (String strType)
Here is an example: response.setContentType(“text/html”);
HTTP AND SERVLETS
Note The default content type is ISO-8859-1 (Latin-1), suitable for Western European languages. Other languages are available.
Data is written via the PrintWriter. The prototype is: public PrintWriter ServletResponse.getWriter() throws IOException
Programmatically, you access the PrintWriter like this: PrintWriter out = response.getWriter();
Once you obtain the PrintWriter, you can construct the web page that the client will receive using statements, such as:
out.println
Out.println (“”); Out.println (“This servlet just says: \“Hi there\””); Out.println (“”);
Note In this example, the quotation marks are escaped so that they print inside the body of the quote.
Let’s looks at these basic principles in a simple servlet designed to showcase the HTTP request process and other web server variables that can be accessed inside a servlet.
HTTP Access and Variables Available to a Servlet RequestDump (see Listing 2.1) is a simple servlet designed to show the range of HTTP values available to a servlet. Let’s see what this simple servlet does, what the values are, and how they might be used. Note The Java code in this chapter is relatively simple and is designed for illustration purposes. The important thing to understand for the rest of the chapter is how web pages and HTTP interact with servlets. Nonetheless, if you are not comfortable writing servlets or if you lack Java skills, take a look at Appendix C, which is a Java primer. LISTING 2.1: REQUESTDUMP.JAVA package c2; import import import import
javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*;
/** * Title: Request Dump Servlet * Description: MasteringJSP * Copyright: Copyright (c) 2001 * Company:
27
28
CHAPTER 2
HTTP AND SERVLET BASICS
* @author Todd Cook * @version 1.0 */ public class RequestDump extends HttpServlet implements SingleThreadModel { private static final String CONTENT_TYPE = "text/html"; /**Initialize global variables*/ public void init() throws ServletException { } /**Process the HTTP Get request*/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println(""); out.println("RequestDump"); out.println(""); out.println("
The servlet has received a GET. This is the reply.
"); ////// DumpHTTPRequest(request, out); ////// out.println(""); } public void DumpHTTPRequest (HttpServletRequest request, PrintWriter out) { out.println("getServerName:"); out.println( request.getServerName()); out.println(""); out.println ("getServletContext().getServerInfo():"); out.println( getServletContext().getServerInfo()); out.println(""); out.println("getProtocol:"); out.println(request.getProtocol()); out.println(""); out.println("getServerPort:"); out.println(request.getServerPort()); out.println(""); out.println("getMethod:"); out.println(request.getMethod()); out.println(""); out.println("getPathInfo:");
HTTP AND SERVLETS
out.println(request.getPathInfo()); out.println(""); out.println("getPathTranslated:"); out.println(request.getPathTranslated()); out.println(""); out.println("getServletPath:"); out.println(request.getServletPath()); out.println(""); out.println("getQueryString:"); out.println(request.getQueryString()); out.println(""); out.println("getRemoteHost:"); out.println(request.getRemoteHost()); out.println(""); out.println("getRemoteAddr:"); out.println(request.getRemoteAddr()); out.println(""); out.println("getAuthType:";) out.println(request.getAuthType()); out.println(""); out.println("getRemoteUser:"); out.println(request.getRemoteUser()); out.println(""); out.println("getContentType:"); out.println(request.getContentType()); out.println(""); out.println("getContentLength:"); out.println(request.getContentLength()); out.println(""); out.println("getHeader(\"Accept\"):" ); out.println(request.getHeader("Accept")); out.println(""); out.println("getHeader(\"Accept-language\"):"); out.println(request.getHeader("Accept-language")); out.println(""); out.println("getHeader(\"Accept-charset\"):" ); out.println(request.getHeader("Accept-charset")); out.println(""); out.println("getHeader(\"User-Agent\"):" ); out.println(request.getHeader("User-Agent")); out.println(""); out.println("getHeader(\"Referer\"):" ); out.println(request.getHeader("Referer")); } /**Process the HTTP Post request*/ public void doPost(HttpServletRequest request, HttpServletResponse response)
29
30
CHAPTER 2
HTTP AND SERVLET BASICS
throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println(""); out.println("RequestDump"); out.println(""); out.println("
The servlet has received a POST. This is the reply.
"); /////// DumpHTTPRequest(request, out); ////// out.println(""); } /**Clean up resources*/ public void destroy() { } }
You’ll notice that in addition to implementing the HTTP servlet interface, Listing 2.1 implements the Single Thread Model interface. Under load, the web server builds a request queue and starts another instance of the servlet to ease the load. Now let’s see the servlet in action. First let’s look at the raw HTTP exchanges by starting the web server with the servlet and displaying a Telnet window to connect. Follow these steps: 1. Open a connection. (See the steps earlier in this chapter if you need instructions for doing this.) 2. Make a GET request to the servlet mapping. (See Appendix A for a description of servlet mapping.)
HTTP AND SERVLETS
3. Press Enter to dump the request.
You cannot test POST using the Telnet–web server connection, because no BODY is sent. Earlier in this chapter, you saw in Figure 2.1 that the Java debugger in JBuilder shows the body as null. Listing 2.2 shows the RequestDump.shtml HTML page. It sets up the forms and URLs for testing the RequestDump servlet. Figure 2.2 shows the RequestDump.shtml page. LISTING 2.2: REQUESTDUMP.SHTML RequestDump Request Dump Example
Click here to call the RequestDump servlet using a GET, without parameters
31
32
CHAPTER 2
HTTP AND SERVLET BASICS
Click here to call the RequestDump servlet using a GET, with parameters Or a GET request may be sent using a form
This is the alternate form for submitting a question to the servlet:
Click Submit to send the question in a GET request to the RequestDump servlet
Type in a question to send it using a POST:
Click Submit to post to the RequestDump servlet
Figure 2.2 The web page that sets up the testing of the RequestDump servlet
Clicking the first hyperlink sends a regular GET, as shown in Figure 2.3.
HTTP AND SERVLETS
Figure 2.3 The RequestDump servlet responding to a GET request
The second hyperlink has parameters hardcoded into its URL. The result is shown in Figure 2.4. Figure 2.4 Hard-coded parameters in a hyperlinked URL produce a GET request and a query string.
33
34
CHAPTER 2
HTTP AND SERVLET BASICS
You often prepare and send a GET request through a form, with the setup shown in Figure 2.5. Figure 2.5 A GET request set up with a form
And the result is shown in Figure 2.6. Figure 2.6 The result of the GET request sent from a form
HTTP AND SERVLETS
That’s right. There’s essentially no difference between a GET request sent from a form and a GET request sent from a hyperlink, except that the user can specify input through the form. You set up a POST with input, as shown in Figure 2.7. Figure 2.7 A POST request with input, ready for submission to the servlet
And the result is shown in Figure 2.8. Figure 2.8 The RequestDump servlet’s response to the posted form data
35
36
CHAPTER 2
HTTP AND SERVLET BASICS
Now that you’ve seen how HTTP parameters and variables can be accessed inside a servlet, and that a result can be returned to a client, let’s look further at some the features and constraints of this servlet. The servlet shows flexibility by sharing code with the function DumpHTTPRequest used in both the GET and POST handling. Why provide both? To GET or To POST Often developers find it easier to debug and generate quick proof-of-concept prototypes using the GET request because testing the submission can be modified simply by manually changing the URL’s query string. However, people often prefer release/production versions of a web application that has implemented the POST method simply because it makes the application appear more seamless, rather than flashing an ugly, long URL and query string.
Tip Always consider how your application might affect the psychological reactions of end users. For example, if you change the URL with a GET request, and the page doesn’t load, a user might be tempted to second-guess whether your application’s new URL is correct.
Configurable Servlet Programming The RequestDump servlet also shows the limitations of static compiled files: hard-coded HTML. The HTML tags aren’t so much the problem as the language they wrap. What if you want to use this servlet in a non–English-speaking country and accommodate the preferred language? Or what if you want to change the wording of the response message? The answers all involve the ability to configure the servlet. You have two primary solutions: ◆ ◆
Use a database to store the strings for all major display text messages Use a property file to store the string assignments
Either way, making variables for every text message output and reading and assigning variables is tedious work. In a later chapter, we’ll set up a database and code the connection. Property files are often used to provide a servlet with a simple, customizable configuration. Even databases that connect Java classes often rely on property files for their startup and initial configurations. The Pros and Cons of Database Usage in the Development Cycle Storing configuration variables in a database is often viewed as a feature that promotes the most flexible architecture. Although the judicious use of databases can bring sanity to the sometimes chaotic workflow of an application, it’s often a unifying feature that is implemented only after the basic structures of the application layout have been solidified. Continued on next page
CONFIGURABLE SERVLET PROGRAMMING
The Pros and Cons of Database Usage in the Development Cycle (continued) On the one hand, using a database increases the flexibility of configuration and growth and is often ideal for the long term, that is, for the life cycle of an application. On the other hand, using a database increases complexity and requires an extra step during development and prototyping. It potentially stretches the initial performance dependency of a servlet across a fallible bridge. For example, if the connection to the database lags, is the user going to be patient? We’ll dig into database implementation and configuration in Chapter 7.
Property Files A property is a text file that contains a grouping of name and value pairs. You access the values by using the java class java.util.ResourceBundle. Property files are regularly used in standalone Java applications, and they are a convenient way to avoid passing in long and cumbersome options as a command-line parameter. What’s more, since the initialization mechanism for reading a property file searches the CLASSPATH, property files can allow each class to be responsible for its proper instantiation. The PropertiesDemo.java program in Listing 2.3 shows the simple mechanism by which a Java program can access configuration data. LISTING 2.3: PROPERTIESDEMO.JAVA /** PropertiesDemo.java * Description: illustrates the dynamic configuration of variables **/ import java.util.*; public class PropertiesDemo { public static int iNumberOfQuestions = 0 ; public static void main(String[] args) { try { ResourceBundle rbInfo = ResourceBundle.getBundle("PropertiesDemo"); iNumberOfQuestions = Integer.parseInt( rbInfo.getString("NumberOfQuestions")); System.out.println("Number Of Questions: " + iNumberOfQuestions); System.out.println ("Coder's remark: " + rbInfo.getString("remark")); System.out.println ("Question1: " + rbInfo.getString("Question1"));
37
38
CHAPTER 2
HTTP AND SERVLET BASICS
System.out.println ("Question2: " + rbInfo.getString("Question2")); } catch (Exception e) { System.out.println (e.getMessage()); e.printStackTrace(); } } }
Lising 2.3 requires a properties file that contains the desired information. By convention, property files have the .properties suffix and are referenced by only their “first” names. The contents of the required file are shown in Listing 2.4. LISTING 2.4: PROPERTIESDEMO.PROPERTIES # PropertiesDemo.properties - for illustration purposes NumberOfQuestions=2 remark=What would the web be without dynamic programming? Question1=Who was the first person to say, "Hello World"? Question2=Why aren't more applications more configurable?
Figure 2.9 shows the output of this listing. Figure 2.9 A debugger window displays the output of the PropertiesDemo program
So far it looks pretty good, but what if your servlet is going to run in a non–English-speaking country? Is there a way you can give users a choice of property files? Yes, indeed, the creators of Java thought of that. To achieve this flexibility, the servlet must use property files with locale designations and with internationalization coding idioms. We’ll look at locales and the steps required to internationalize Java code in Chapter 12. In addition to setting display variables, property files can also toggle settings between the development and production environments. For example, you can use a property file to turn debugging on and off. A property file has the following characteristics: ◆
The first line is disregarded. Typically, it contains the title and perhaps a comment on the purpose of the file.
CONFIGURABLE SERVLET PROGRAMMING
◆ ◆ ◆
◆
Key names and values are paired with an equal sign. Key names must not contain spaces. Values are assigned as is. For example, strings with quotations can be printed as is, and unlike the regular Java code within a servlet, they don’t need to be escaped, for example, out.println(“”);. Locales are indicated in the filename using the following syntax: ResourceBundleName_ LocaleName.properties.
SalaryQuote Servlet To see how property file configuration works in practice, let’s look at a sample SalaryQuote servlet, shown in Listing 2.5. This servlet is also designed to show how calculations (correlating a person’s position to their salary) and the verification of a username and password can be done inside the private “packaged” area of a servlet. As long as the configuration file is secured, the information the servlet controls is safe from, say, a junior web developer browsing the source directories on the web server. However, there’s a lot more to security, and we’ll deal with security in Chapter 6. LISTING 2.5: SALARYQUOTE.JAVA package c2; import import import import
javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*;
/** * Title: SalaryQuote * Description: Demonstration servlet: properties * and servlet configuration * Copyright: Copyright (c) 2001 * Company: Sybex Mastering JSP * @author Todd Cook * @version 1.0 */ public class SalaryQuote extends HttpServlet implements SingleThreadModel { private static final String CONTENT_TYPE = "text/html"; private String strUserName = ""; private String strEmpPosition = ""; private String strPassphrase = ""; private String strAuthUsers = ""; private String strSalaryInfo =""; private String strMailToMessage =""; private boolean bDebug=true;
39
40
CHAPTER 2
HTTP AND SERVLET BASICS
/**Initialize global variables*/ public void init() throws ServletException { try { ResourceBundle rbInfo = ResourceBundle.getBundle("SalaryQuote"); if (rbInfo.getString("AuthUsers")!= null) { strAuthUsers = rbInfo.getString("AuthUsers"); } if (rbInfo.getString("DebugMode")!= null) { bDebug = true; } else { bDebug = false; } if (rbInfo.getString("MailToMessage")!= null) { strMailToMessage = rbInfo.getString("MailToMessage");} if (rbInfo.getString("SalaryInfo")!= null) { strSalaryInfo = rbInfo.getString("SalaryInfo"); } if (bDebug) { System.out.println("AuthUsers: " + strAuthUsers); System.out.println("MailToMessage: " + strMailToMessage); System.out.println("SalaryInfo: " + strSalaryInfo); } } catch (Exception e) { e.printStackTrace(); } } private boolean CheckUser () { String strTmp = "";
CONFIGURABLE SERVLET PROGRAMMING
int iPos = 0 ; int iPosComma = 0; int iPosPipe = 0; boolean bIsOkay = false; if (bDebug) { System.out.println("strUserName=" + strUserName); System.out.println("strPassphrase=" + strPassphrase); System.out.println("strAuthUsers=" + strAuthUsers); } try { iPos = strAuthUsers.indexOf(strUserName); if (iPos == -1) { bIsOkay = false; } iPosComma = strAuthUsers.indexOf(",", iPos); iPosPipe = strAuthUsers.indexOf("|", iPos); System.out.println(strAuthUsers.substring (iPosPipe + 1, iPosComma)); if (strPassphrase.equals (strAuthUsers.substring (iPosPipe + 1, iPosComma))) { bIsOkay = true; } if (bDebug) { System.out.println( "Authentication = "+bIsOkay);} } catch (Exception e) { e.printStackTrace(); } return bIsOkay; } private String PullSalaryInfo (String positionInfoRequest) { // This would be a great place for a database call, // since dealing with arrays of values from property // value assignments is error prone// and tedious to maintain. // Okay for a prototype int iPos = 0 ;
41
42
CHAPTER 2
HTTP AND SERVLET BASICS
int iPosSemiColon = 0; int iPosPipe = 0; try{ if (bDebug) { System.out.println("strEmpPosition" + strEmpPosition); System.out.println("strSalaryInfo" + strSalaryInfo); } iPos = strSalaryInfo.indexOf(strEmpPosition); if (iPos == -1) { return "Sorry no info found"; } iPosSemiColon = strSalaryInfo.indexOf(";", iPos); iPosPipe = strSalaryInfo.indexOf("|", iPos); String LineItem = "A(n)" + strSalaryInfo.substring (iPos, iPosPipe) + " makes " + strSalaryInfo.substring (iPosPipe +1, iPosSemiColon) + " a year " ; if (bDebug) { System.out.println("Info found: " + LineItem);} return ( LineItem ); } catch (Exception e) { e.printStackTrace(); } return ""; } /**Process the HTTP Get request*/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println(""); out.println("SalaryQuote"); out.println("");
CONFIGURABLE SERVLET PROGRAMMING
out.println("
The SalaryQuote servlet does not respond to GET requests.
"); out.println(""); } private void PullParams (HttpServletRequest request) { try { strUserName = request.getParameter("UserName"); strPassphrase = request.getParameter("Passphrase"); } catch(Exception e) { e.printStackTrace(); } try { strEmpPosition = request.getParameter("EmpPosition"); } catch(Exception e) { e.printStackTrace(); } } /**Process the HTTP Post request*/ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PullParams(request); response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println(""); out.println("SalaryQuote"); out.println(""); out.println("
"); if (CheckUser()) { //success out.println ( PullSalaryInfo (strEmpPosition )); } else { out.println(strMailToMessage);
43
44
CHAPTER 2
HTTP AND SERVLET BASICS
} out.println("
"); out.println(""); } /**Clean up resources*/ public void destroy() { } }
There are several important things to remark about this servlet. In getting the property values, each call to the ResourceBundle is tested to see if it’s null. If a property value doesn’t exist, the ResourceBundle returns a null. Of course, trying to use a null value as a string will throw an exception. It’s generally considered good practice to check all incoming values before assigning them to variables. When the servlet initializes, it checks the properties file to see if debug mode is turned on. If so, a global class variable debug is set and used to determine if information should be sent to the system’s output stream, which is usually a console window that invoked the application or started the web server. The SalaryQuote servlet is configured with the SalaryQuote.properties file, shown in Listing 2.6. The properties file holds many pieces of information that should be properly stored in a database, such as a list of users who can access the salary information and another listing of the salary information statistics. Databases are set up, used, and discussed extensively in Chapters 7 and 14. LISTING 2.6: SALARYQUOTE.PROPERTIES # SalaryQuote.properties AuthUsers=Joe Clerk|myPassword,Sue Payroll|herPassord SalaryInfo=Office Clerk|30,000;Payroll Clerk|40,000;Secretary|35000;Manager|60000;President|90000 MailToMessage=Sorry, there was a problem with authentication, please contact the system administrator at:
[email protected] DebugMode=true
The AuthUsers and SalaryInfo fields in Listing 2.5 contain customized data formats to represent the structures. The servlet searches for each of these variables and interprets them according to a hardcoded logic in the servlet. In the AuthUsers field, a pipe character separates the user’s name from their password, and a comma separates entries. In the SalaryInfo field, a pipe separates employee titles from their salary figures, and a semicolon separates the entries because commas are present in the dollar values of the salary figure. As you can see, this is a clumsy configuration setup even when documented and explained.
CONFIGURABLE SERVLET PROGRAMMING
Note In this chapter, we are using property files to configure servlets for illustration purposes only. We’ll discuss how to set up and interact with a database in Chapters 7 and 14.
The SalaryQuote.shtml page, shown in Listing 2.7, sets up the POST request with the appropriate information so that the SalaryQuote servlet can process and return the request. LISTING 2.7: SALARYQUOTE.SHTML SalaryQuote
Welcome to the Salary Quote inquiry tool
This is a restricted area, please authorized personnel only!
UserName
Passphrase
Employee Position Office Clerk Payroll Clerk Secretary Manager President
Click Submit to post your request to the SalaryQuote servlet
Click here to call Servlet: SalaryQuote
Now let’s see how the program acts. Figure 2.10 shows the setup and the correct inputs to get a response. Figure 2.11 shows the response.
45
46
CHAPTER 2
HTTP AND SERVLET BASICS
Figure 2.10 SalaryQuote.shtml with all the proper inputs ready for submission
Figure 2.11 The SalaryQuote servlet responds to a proper POST request.
The debug property parameter turns on the debug output. Figure 2.12 shows the JBuilder debug window. So far the implementation looks good and configurable, but the obscure method the servlet uses to interpret the properties file is error prone and difficult to use. Additionally, the servlet specifies to much of the Presentation layer, with the HTML hard-coded into the response. JSP came after servlets and was designed to add flexibility to the Presentation layer, which is ugly and inflexible here. If you visualize the deployment of this servlet, it’s easy to see how property files can be a powerful assistance. On a web server, the system administrator can protect the configuration file from read/ write access, and indeed, if any server connections must be changed, the system administrator can change those values, and it would be quite easy for the system administrator to change your configuration file—without ever touching your code! The developer need only provide some additional documentation on manipulating the values in the .properties configuration file. You’ve seen that asking servlets to do too much on the Presentation layer can result in inflexible responses and configuration difficulties. So why use them?
CONFIGURABLE SERVLET PROGRAMMING
Figure 2.12 Jbuilder’s debug window showing the debugging output after it has been turned on through the use of the properties file
The Advantages of Servlets Servlets allow a level of abstraction not possible with JSP pages. For example, a servlet can process a request, filter or authenticate it, and then pass it on to another servlet or to JSP. Servlets promote an architecture that is compiled and packaged, whereas JSP pages present a pliable presentation layer. Java servlets can be obfuscated so that the internal code cannot be easily reverse-engineered, whereas JSP code must be preserved as is and in human-readable form. In this chapter, we covered the basics of HTTP and servlet programming. In later chapters, I’ll discuss the advantages of servlets in more detail and describe some new, more advanced features. Here’s a quick peek.
What’s New in Servlet Specification 2.3? The new Servlet specification includes two additions: added facility for managing application life cycle events, and filtering. Application Life-Cycle Event Management
Imagine a large web application in which many connection points access a database. A properly constructed architecture should share the database connection, but how would it know when it was no longer needed? Life-cycle event management answers that question by providing the means for applications to notify the Servlet Context when they start listening. This takes place through adding EventListeners. You’ll learn more about this in Chapter 3.
47
48
CHAPTER 2
HTTP AND SERVLET BASICS
Filters
Filters are special servlets that are designed to reformat or process data coming in or going out to the client. Unlike JSPs, filters are designed for transparency; the user might never know that their content is being filtered. Here’s some examples of tasks suitable for a filter: ◆ ◆ ◆ ◆
File conversions (.doc to .html, .tif to .jpg) Data compression Image compression and conversion XML to HTML conversion
Let’s look at a scenario in which some of these filters might be used. A user logs into his account for a horse-racing site. He’s usually at home, but this time he’s logging in from a palm-sized computer from the racing track’s sideline. He visits an SSL-encrypted (Secure Sockets Layer) login (more on this in Chapter 6), where his username and password are sent to an authentication servlet that logs him in. During login, he specifies that he is using his palm-sized computer, connecting with low bandwidth. He checks his account and requests statistics on horses for the next race. A servlet gathers the information and passes it to an image-compression servlet. The servlet checks his session profile information and discovers he needs to see a smaller image than usual, and because of his low bandwidth, the image needs to be as lightweight as possible. The filter servlet then shrinks a copy of the image and compresses the file before sending it out. The user is not aware that his web content was filtered—he may only notice that it looks “different” on his palm-sized computer.
Summary HTTP exchanges are the basic currency of the Web. GET requests a URL, POST pushes the parameters in a form body, HEAD requests the information from a page without actually receiving the entire page, and OPTIONS requests the web server to report back what it can accept. The PUT and DELETE requests, although available, are largely unimplemented due to concerns for security and resource management that are usually handled elsewhere anyway. Servlets can access the HTTP request object directly and can implement specific handling for the HTTP requests. Servlets build a response line by line, and while this gives precise control over a response, it can be dangerous because it encourages the hard coding of the response format. This problem of an inflexible presentation layer is exactly what JSP was designed to fix. The main remedies are using property files to set parameters at servlet initialization time, and modifying the request and passing it to a JSP page. You can use property files to customize variable values for a servlet or a standalone application. You can also use property files to configure a servlet or an application for different languages. Although database storage is often ideal for mutable variables, even useful database connection classes often have to gather their initialization parameters from a property file. You can also increase servlet flexibility by modifying the request and passing it on to a JSP, which we will cover in the next chapter.
Chapter 3
JSP Processing In the previous chapter, you saw how to manipulate HTTP requests and responses, the basic currency of the Web, inside a Java servlet. In this chapter, we’ll look at the background processing involved with serving JSP pages and servlets. You’ll see how the JavaServer Engine uses reflection introspection to link a JSP page with other parts of a Java back-end enterprise system. The JavaServer Engine hands out session IDs to each browser, and the server maintains a variable namespace area for those session objects. You’ll see how these session IDs and objects behave, how you can manipulate them, and how they can be crucially important when creating a flexible web application. By understanding background processing, you can become a better developer, knowing when to use which tool where, how to get components working together, and where to look when things go wrong. Featured in this chapter: ◆
The elements of a JSP page ◆ Server processing of JSP pages ◆ Using JSP with other enterprise components
The Tag Elements of a JSP Page Without JSP tags, all you have is regular HTML. You use JSP tags to insert Java code into a web page to ease the task of displaying or processing data. Additionally, JSP tags can help structure the layout of the page by including sections from other HTML or JSP files. JSP tags can also guide the user, prompting them to take a required action such as logging in before changing an item. Let’s take a look at the formats of the JSP tags.
50
CHAPTER 3
JSP PROCESSING
JSP Tags JSP tags are of two primary types: scriptlet tags and JSP keyword tags. Scriptlet tags give you the freedom to use any kind of Java code. JSP keyword tags tap into the special language features provided by the JSP libraries. Scriptlet Tags
Any tag starting with , and any code in between, is a scriptlet tag. In other words, everything in a scriptlet tag stays on the server side, where it’s compiled for processing. A JavaServer page can be composed of several scriptlet tags, but for each page, all scriptlet tags are compiled together into one servlet. I’ll explain the compilation process soon, but first let’s finish our look at the JSP tags. The Format of Other JSP Tags
Other than scriptlet tags, JSP has adopted XML-styled tags whenever possible. Although XML is the tip of a future programming iceberg (we’ll deal more thoroughly with XML in Chapter 10), you only need to understand that all JSP tags must behave properly by closing themselves with a closing tag or by following the special syntax for a single unified tag. The following example shows an XML-compliant opening and a closing tag in HTML: Jump to index
And this example shows an opening and a closing tag in JSP:
The odd-looking tag in the center showcases the new shorthand, the special syntax for a single unified tag that is an abbreviation for the opening and closing tag. The abbreviation is a forward slash inserted before the closing angle bracket (>). You use this single tag syntax when two tags can’t contain a value, such as with the HTML tag, or when the value is defined inside the tag, as in the tag example given earlier. Therefore, this tag:
is equally as valid as:
The abbreviated version doesn’t provide the benefit of being able to sandwich a parameter as the first example does. Before we get into what happens with JSP processing, let’s take a look at its elements and anatomy. Because all the functionality of JSP is packaged into tags, JSP syntax could be seen as a “serverenabled” extension of HTML. And indeed JSP tags are XML compliant, just as the next recommended version of HTML, XHTML, is based on XML. Even for simple HTML programming tasks, JSP provides better HTML.
THE TAG ELEMENTS OF A JSP PAGE
Improved Commenting with JSP Commenting JSP code is a necessary step toward ensuring a well-designed and easily maintained application. Regular HTML and JavaScript are rarely commented—a bad habit. Comment JSP code thoroughly; unlike regular HTML comments, JSP comments will only be read by developers. Managers should rejoice, for JSP developers now have no excuse for skimping on rudimentary, “signpost” documentation in their code; correctly commented code is secure from public viewing. Let’s compare the two. The following is an example of a regular HTML comment:
Warning Because the first */ pair prematurely ends the comment, the JSP comment generates a compile error if the double forward slashes on the left are removed. It’s recommended that you stick to the double forward slashes comment style. They are the first thing the eye sees, so they are more difficult to miss.
A commented out line will not hide the end tag of a scriptlet even if it is on the same line:
51
52
CHAPTER 3
JSP PROCESSING
All you need is a space preceding the end tag.
If there is no space between the double forward slash and the closing scriptlet tag, the JavaServer Engine generates a compile error. JSP Directives
JSP directives comprise two groups of tags: the @ directives, which provide the JavaServer Engine with compilation instructions for building a JSP, and action tags such as , which provide runtime instructions for the handling of the page. The difference between the two will be demonstrated in the examples. The @ directives act as shortcuts, allowing you to reference libraries and build a JSP page out of other HTML pages or even other JSP pages. The action tags allow you to include HTML/JSP files at runtime or forward a user on to a URL constructed at runtime. Used properly, both tags help build robust and flexible applications. The import Directive
The @ import directives are fundamental cues that assist the JavaServer Engine in compiling a JSP page. They must appear at the top of the JSP page. The @ import directive can reference distinct Java classes, JavaBeans, and entire libraries. The following code snippet brings the java.util.Date class in as a reference.
This import tag is represented in pure Java source code as: import java.util.Date;
By using these declarations, you can write code that’s cleaner and easier to read. For example, you can write: Date myDate = new Date();
instead of: java.util.Date myDate = new java.util.Date();
Note The JSP import directive accomplishes the same thing as the import keyword used in Java source code in standalone applications and servlets; it references libraries and classes for the compilation process. (See Appendix C for more information.)
By default, the following are already imported into the compilation of a JSP page: java.lang.* javax.Servlet.* javax.Servlet.jsp.* javax.Servlet.http.*
THE TAG ELEMENTS OF A JSP PAGE
Note Unlike the regular Java language syntax, you can separate multiple import statements with commas. Although this format may look cute, many developers prefer to place multiple import statements on separate lines for the sake of clarity and consistency. Suit yourself. The import Language Tag
The @ import Language tag is so fundamental that it’s assumed, because Java is the default language for the code inside a JSP page.
Note Currently, Java is the only supported language; however, the JSP specification allows for possible future language extensions. The include Tag
JSP can use special include tags to build a larger page for an HTTP response by including several other pages, such as sandwiching its dynamic content between headers and footers. For a JSP page to “paste” in a header, it needs only reference the include tag in the appropriate place. By doing this, developers can build web pages that have a consistent look and feel, or at least consistent headers and footers.
You use the flush function to specify whether the buffer of the included resource is flushed before being included. The easiest way to identify the flush function is to visualize the JavaServer Engine demanding that it can’t build a response page until each component submits a complete contribution. Tip Pages built with the tag load the file specified at runtime, whereas files specified in the tag
The revision of the JSP specification 1.2 is supposed to remove the flush requirement from the tag. Thus far, though, I’ve seen the removal of the flush attribute cause errors several times, so perhaps the implementations don’t quite have it down yet. JSP specification 1.1 allows for the attachment of an optional value or values using a subservient tag, jsp:param, as in the following:
jsp:include
Note We described jsp:param as subservient, and that’s appropriate because it isn’t a valid tag unless it is sandwiched between other relevant JSP tags, such as a forward tag.
53
54
CHAPTER 3
JSP PROCESSING
The forward Tag
Often a web user is redirected to a page based on some conditional processing. For example, if a user doesn’t complete a survey, they may be directed to a particular page. You can redirect the user by using the forward tag like this:
With the release of JSP 1.1, developers have been allowed to attach parameters, such as in the following example:
These parameters function in the same way as values pushed to the web server using an HTTP POST. Let’s see how in an example. Listing 3.1 shows the setup code. LISTING 3.1: FORWARDSETUP.JSP ForwardSetup ForwardSetup Inquiry info: Click submit to test the forward action with your value Send a comment: Click submit to test the forward action with your value
THE TAG ELEMENTS OF A JSP PAGE
The ForwardSetup JSP allows a user to send either an inquiry or a comment to the forward test page. An inquiry or a comment is enclosed by its own tag, and inside each, a hidden text field designates which form is passing information about the type of submission. The form appears in Figure 3.1. Figure 3.1 The ForwardSetup JSP page in a browser, with text entered as an inquiry
The ForwardSetup page could just have easily had one text field and a check box or a radio button for the type, and it could have been a simple HTML page. The important thing in this example is what the receiving page, ForwardTest.jsp, does with the parameters. The ForwardTest page, shown in Listing 3.2, pulls the passed parameters and forwards the request in a tag. If the inquiry text block is passed in, the inquiry text is written into the URL. If the text block is passed in as a comment, the text is written into a parameter that is sandwiched between beginning and ending tags. LISTING 3.2: FORWARDTEST.JSP ForwardTest
55
56
CHAPTER 3
JSP PROCESSING
Forward Test There was a problem with your entry
The following comment, if inserted into Listing 3.2, may cause a difficult-to-solve runtime error: // The following construction should work above, // but it failed to parse correctly on some implementations //
Warning Many implementations of the JavaServer Engine have a problem with commented directives. To be on the safe side, remove unused directives and leave a note pointing to some offline documentation.
By design, the ForwardTest.jsp shouldn’t actually appear in the browser; the ForwardTest page merely processes requests and forwards them. Only in some kind of odd error condition would it actually display in the client’s browser. To see the results of a working example, we need to look at
THE TAG ELEMENTS OF A JSP PAGE
the destination pages. Forwarded inquiries are simply displayed on the InquiryProcessing page, as shown in Listing 3.3. LISTING 3.3: INQUIRYPROCESSING.JSP Inquiry Processing Inquiry Processing Inquiry was:
In Figure 3.1, the Inquiry area contains the text, “Add param to forward tag?” When the user clicks the Submit button, the ForwardTest.jsp page processes the request and forwards the information to the InquiryProcessing.jsp, as shown in Figure 3.2. Figure 3.2 Processing an Inquiry request by ForwardTest.jsp
Likewise, forwarded comments are simply displayed on the CommentProcessing JSP page, shown in Listing 3.4. LISTING 3.4: COMMENTPROCESSING.JSP CommentProcessing
57
58
CHAPTER 3
JSP PROCESSING
Comment Processing Comment was:
Figure 3.3 shows the setup for pushing a parameter to the comment page. Figure 3.3 The Comment field loaded for processing
Figure 3.4 shows the results of the ForwardTest.jsp processing the Comment field and forwarding it appropriately. Figure 3.4 The forwarded comment
Notice anything odd between Figures 3.2 and 3.4? The URL is still the same as the page that had the controlling logic tests and the JSP forward tags. That’s right. Even though the request was forwarded, it occurs within the shell of the larger page!
THE TAG ELEMENTS OF A JSP PAGE
Examining the code for ForwardTest.jsp reveals that the parameter was dynamically written in as an attached parameter in the forward, for example:
Yet, notice the lack of a query string with any of the posted parameters in the URL. Changing the forward tag by rewriting the query string can be more error prone. Some implementations complain when you visit the page with a forward tag modifying the query string like this:
which causes the JavaServer Engine to complain with this message: org.apache.jasper.JasperException: Forward: Invalid attribute, InquiryProcessing.jsp?forwardedInquiry at org.apache.jasper.compiler.JspUtil.checkAttributes (JspUtil.java:229) at org.apache.jasper.compiler.Parser$Forward.accept(Parser.java:333)
It looks as if the problem is related to the parsing. The workaround is creating the URL string and placing it in the JSP forward tag as a single item, as in: String tmp ="InquiryProcessing.jsp?forwardedInquiry=" + strRequest; %> …
The variable definition area appears near the top of the code. The function defined in it can be used to simplify the repetitive use of large HTML code constructions. In Chapter 15, you’ll see how this behavior can be factored out into custom tags. Listing 4.1 produces the following HTML: NOTE:
The static variable iTimesPageHasBeenViewed:
Later we’ll package this string into the handlers of a JavaBean.
Putting It All Together Let’s look at a short web application, Mastering Jsp Set User Preferences, to illustrate the elements we’ve talked about and to capture user preferences, customize the user’s interface, perform calculations, and handle errors gracefully. First, we use the tag to provide a common heading (see Listing 4.7). This heading is in raw HTML, so if graphic artists want to update the look and feel of the heading, they’ll never have to touch the JSP code. LISTING 4.7: HEADER.JSP
A header is a good place for: | Hyperlinked General Help | Links to Company Surveys |
Figure 4.2 shows the Mastering Jsp Set User Preferences page. Here the user enters their name and their e-mail address if they want to be contacted should an error occur on a page and they need help. The application could easily substitute this field for a temporary phone number; if the user is an employee navigating the site at another location, it might be more convenient for them to be contacted at a temporary office location. In a later chapter, I’ll show you how a JSP application can page a help desk person with the necessary contact, error, and debugging information. This basic user preferences page allows users to choose settings that will cascade throughout the application (see Listing 4.8). In the page in Figure 4.3, the user can choose text and background colors. These values and others can be linked to a login, perhaps with a temporary password
PUTTING IT ALL TOGETHER
e-mailed in a confirmation, and each time the user visits the site—from no matter where—their preferences are stored and retrieved as a profile. I’ll discuss profile storage and retrieval in Chapters 7 and 13. FIGURE 4.2 This page requires that you identify yourself before you begin setting preferences.
FIGURE 4.3 The effect of the customization as controlled by the JavaBean code
91
92
CHAPTER 4
USING SCRIPTING ELEMENTS
LISTING 4.8: MJSPUSERPREFERENCES.JSP Mastering Jsp User Preferences Mastering Jsp Set User Preferences Enter your name: Enter your email address: (If you'd like to be contacted should you encounter an error on a page) Set Background color: white black light blue blue green yellow orange Set Font color:
PUTTING IT ALL TOGETHER
white black blue green yellow orange Welcome A demonstration of error handling and the usefulness of storing client information on the server side Formating and working with numbers and dates Examples of scope Examples of Flow Control Examples of performance issues in scripting
The page first references a global error page should anything happen. It then invokes the MJspUserPreferencesBean, gathers the users information, and submits to itself and validates using the JavaBean functionality as described in Chapter 5. Note We’ll discuss JavaBeans in Chapter 5. It’s recommended that you revisit this chapter and examine the JavaBeans source code listed at the end of this section.
It then provides a number of hyperlinked choices, among them an error demo page (Figure 4.4), produced by the code in Listing 4.9.
93
94
CHAPTER 4
USING SCRIPTING ELEMENTS
FIGURE 4.4 The Error Demo page sets up the test.
LISTING 4.9: ERRORDEMO.JSP Error Demo Error Demo Welcome This page sets up an error condition that will be thrown from a bean.
PUTTING IT ALL TOGETHER
This error will show how the error page directive will handle the error. And it will also show how storing the client's information on the server side can be helpful. Click submit to test Jsp error handling
The Error Demo page posts to itself and invokes the ErrorTest JavaBean method setTestError (see Listing 4.10), which simply throws an error to illustrate how an exception is forwarded to the error page as defined in the @ page JSP attribute for each page (see Chapter 3). Figure 4.5 shows how the thrown error was handled. FIGURE 4.5 Displaying and hiding debug messages
95
96
CHAPTER 4
USING SCRIPTING ELEMENTS
LISTING 4.10: ERRORPAGE.JSP Error Page We're sorry, there was a problem processing your request, . Please go back and try again, try later, or email the helpdesk
The best error reporting approach might be to inform users politely that an error simply occurred, while presenting the debugging information concealed in HTML. The Java Exception messages can be wrapped in an HTML comment so that developers can see what happened if they view the browser's source.
The Java Engine generated this Stack Trace -->