Bài giảng JSTL in Action

pdf 111 trang huongle 8930
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng JSTL in Action", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfbai_giang_jstl_in_action.pdf

Nội dung text: Bài giảng JSTL in Action

  1. www.it-ebooks.info
  2. JSTL in Action www.it-ebooks.info
  3. www.it-ebooks.info
  4. JSTL in Action SHAWN BAYERN MANNING Greenwich (74° w. long.) www.it-ebooks.info
  5. For my future wife and kids, who, when I meet and conceive them, respectively, will likely be my love and my inspiration www.it-ebooks.info
  6. x CONTENTS Foundation: XML and JSP 15 2 2.1 Introduction to XML 16 A dose of tag terminology 17  The relevant rules of XML 21 2.2 Introduction to JSP 23 JSP tag syntax 24  Standard JSP tags 25 JSP tag libraries 29  Other JSP directives 32 JSP comments 33  How JSP organizes data 34 2.3 Summary 39 PART 2LEARNING JSTL 41 The expression language 43 3 3.1 Expressions and the tag 44 What expressions look like 45  Where expressions work 46 Default values in 46  Special characters and 47 3.2 Scoped variables and the expression language 48 Basic syntax to access scoped variables 48 Different types of scoped data 50 3.3 Request parameters and the expression language 55 HTML forms 55  A page that reads request parameters 62 3.4 More powerful expressions 63 Different ways to access properties 64  Accessing other data with the expression language 65  Comparisons 67  Boolean operations and parentheses 69  Multiple expressions 70 3.5 Saving data with 71 3.6 Deleting data with 74 3.7 Summary 75 www.it-ebooks.info
  7. CONTENTS xv Dynamic features for web sites 279 12 12.1 An online survey 280 What our survey looks like 281  Setting up the survey database 281  Adding survey questions to pages 284 How the survey works 285 12.2 A message board 291 What our message board looks like 291  Setting up the message database 293  Linking to appropriate message boards 294 How the message board works 295 12.3 Summary 300 Case study in building a web site 301 13 13.1 Managing the layout 303 A framework for channels 303  Modular channels 305 13.2 Adding dynamic content 309 Including RSS channels 309  Including other dynamic content 311 13.3 Registering users 313 Modifying the header 313  The registration form 314 Saving the registration 318  The user database 319 13.4 Authenticating users 320 Logging in users 320  Some notes about authentication 321 13.5 Personalizing the site 322 Filling in a form automatically 322  Displaying a chosen RSS feed 324 13.6 Summary 325 PART 4JSTL FOR PROGRAMMERS 327 Control and performance 329 14 14.1 Scripting elements and the JSTL rtexprvalue libraries 330 Warning against scripting expressions 331  JSTL’s dual libraries 332  Scripting variables and 333 14.2 Modifying properties with 334 www.it-ebooks.info
  8. xx PREFACE This book will show you how to make the most of JSTL. It begins without assuming you know anything more than HTML, and it gently introduces you to all the principles you’ll need to produce flexible, powerful web pages. The goal of this book isn’t to satisfy my own ego by showing you how subtle and tricky technology can be, but instead to equip you to handle any JSTL-related issue that arises when you produce real-world, dynamic web sites. If you read an example in this book and think, “I didn’t realize it could be so easy,” then JSTL has done its job—and so have I. www.it-ebooks.info
  9. ABOUT THIS BOOK xxv names (for HTML, XML, or JSTL tags), tag attributes, scoped-variable names, and other words that normally appear within code.  Tables for tags Just like HTML tags, JSTL tags have attributes that let you modify the tags’ behavior. For instance, in the tag , the text type= "currency" is an attribute. I’ve listed tag attributes in tables that have a consistent format. Here’s an example: tag attributes Attribute Description Required Default email Email address to send junk email to Yes None subject Subject of the junk-email message No "Long distance service for less." message Body of the junk-email message No Body This sample table shows a few things. First, tables for tag attributes have a “tag” icon to help you find them. Such tables have four columns describing the attribute name, a brief description of each attribute, information about whether the attribute must be specified for each use of the tag, and information about the default value of the attribute if you don’t specify a value. If the Default column contains None, the attribute has no default. If this column contains Body, the default value comes from the tag’s body. (See chapter 2 for more information about tags, attributes, and bodies. Note that is, of course, not a real JSTL tag—although given the number of applications that send out junk mail, there’s clearly a need for it; per- haps we’ll see it in JSTL 1.1.)  Highlighting I highlight sections of code samples whenever I feel like it, usually to draw your attention to a part of the code sample that has changed. Highlighting isn’t consis- tent; it’s there only when I think it will be useful.  Code annotations Some longer examples are annotated using bullets like this: i. These are often tied to paragraphs that follow and amplify the code.  Call-out boxes Occasionally, I draw your attention to a Note, Tip, or Warning using a noticeable box in the middle of the page. To be honest, I do this just because other books do it; fortunately, I use these boxes sparingly. www.it-ebooks.info
  10. Part 1 Background We l c o me t o JSTL in Action, a guide to everything you’ll need to know about JSTL. In the first part of this book, we explore what JSTL is and how it works. We start by discussing the simple ideas behind dynamic content on the Web. After that, we look at some of the differences between HTML and XML. This topic is important because JSTL uses an XML-like syntax, so you’ll need to be aware of its rules. Toward the end of part 1, we also discuss the basics of JavaServer Pages (JSP), the broader language that JSTL is based on. Part 1 takes for granted only a basic knowledge of HTML. This book is designed to be a gentle but complete introduction to JSTL, and it doesn’t assume you’re familiar with any other programming or web-design languages. Part 1 lays a foundation so that you have all the tools you need to jump in and begin design- ing dynamic web pages. www.it-ebooks.info
  11. www.it-ebooks.info
  12. Dynamic1 web sites This chapter covers  Ideas behind dynamic web content  What JSTL looks like  Requirements for running JSTL  JSTL’s role in web applications 3 www.it-ebooks.info
  13. The simple ideas behind dynamic web content 7 To conduct a mail merge and print a customized letter, you supply the informa- tion missing from this single master copy of the letter—perhaps at the prompting of your word processor, or as a preformatted, comma-separated text file. To be com- plete, each letter needs four pieces of information: NAME, DOLLARS, PRESENT, and APPENDAGE. Like the old Mad-Libs games, producing a customized letter simply involves filling in these placeholders. One set of legitimate values might be Jack, 20, tuna sandwich, finger Another might be Leonard, 1200, television, arm Yo u ’d use the mail merge in the first place because doing so is simpler than typing each letter manually—or even using a word processor to edit the letter yourself each time you need a new, customized copy. Believe it or not, template languages for the Web work almost exactly the same way. Starting with a web-development language is no harder than using mail merge. The major difference is that instead of printing simple text letters or docu- ments, the goal of a web-design language is usually to print HTML. For instance, here’s what our sample mail-merge letter might look like in JSTL: Nasty letter Dear : My records show that you owe me $ . I need this money now to buy myself a big . If I don’t get it, I will break your . NOTE In this example, and throughout the rest of this book, I use bold type to highlight JSTL tags that occur within HTML text. This formatting makes it easier to differentiate the dynamic parts of a page from its static, tem- plate text. www.it-ebooks.info
  14. 12 CHAPTER 1 Dynamic web sites Figure 1.4 Small applications can be designed entirely using JSTL pages. Web browsers load the pages directly, and the pages know how to find all the information that they need to print. design, the JSTL page does all the work. That is, it knows how to find all the data it needs to print, without any help from back-end Java code. In contrast with figure 1.4’s simple design, consider figure 1.5. The web browser makes a request for a web page, but this request is handled by a servlet, which is a web program written in the Java programming language. In order to handle this request, the servlet can interact with other Java code, as well as databases, directo- ries, XML files, messaging systems, and nearly anything else. Finally, once the serv- let has decided what it wants to display to the user, it forwards—that is, hands off— the request to a JSTL page, which decides how to print out the information. One key principle of this model is that each JSTL page is designed to do a differ- ent thing. For example, one JSTL page might be written to print a shopping cart to cell phones using WML. Another would be designed to present a registration page for new users in HTML. The pages themselves don’t decide what task to perform; they only decide what to display. The servlet takes care of all the behind-the-scenes action, which might include determining what kind of device the user’s using (cell phone versus web browser) and what the user is asking for (shopping cart or regis- tration page). Organizing an application as shown in figure 1.5 has a number of benefits. Doing so supports division of labor in your organization, much like traditional divi- sion of labor in a factory assembly line. If you work for a large organization, you probably have a number of different kinds of colleagues: programmers, web-page authors, graphics designers, database administrators, and so on. Separating the pieces of your application into different blocks—a servlet, plain Java code, a data- base, JSTL pages—means that all the people in your organization can focus on what they do best. This division of labor also makes a site more maintainable. Before template sys- tems, it was common to include HTML in the middle of conventional programs, like this: www.it-ebooks.info
  15. Introduction to XML 17 XML is an approach for using these tags to mark off information within a document. XML, unlike HTML, does not describe a particular set of tags ( , , and so forth) or relationships between such tags. Instead, it describes the rules for using tags in a document in the first place. To draw a loose analogy, XML is a general- purpose mechanism, like Arabic numerals—1, 2, 3, and so on. Receiving a group of Arabic numerals in isolation doesn’t tell you much; for example, seeing “79” on a blank page doesn’t convey any useful information without a context. However, you know that “79” is a valid string containing just Arabic numerals, and that “g”, “49E”, and “©” are not. Similarly, the tag in the previous code snippet doesn’t mean anything in isolation. In fact, neither does a tag like . This latter tag has a meaning when it appears in an HTML document, but alone, it is simply an arbitrary tag, just as “79” is an arbitrary string of digits. Nonetheless, it follows XML’s rules, so it is a well-formed, recognizable XML tag, whereas [am-I-an-XML-tag?] is not. In a moment, we’ll look more at XML’s rules. If you’ve browsed discussion groups online or exchanged email with enough peo- ple, you’ve probably seen informal uses of tags beyond HTML. For instance, I’ve often seen people mark off a particularly vibrant part of an email message with tags like and , or introduce a long, rambling section with a tag. This pseudo-HTML markup, insofar as it technically adds structure to a document, represents the essential goal of XML: tags are used to mark a document in ways that help people and programs identify the purpose of each part of that document. Jumping right in, we’ll first look at some of the jargon used to describe XML tags and their relationships. Then we’ll follow up with some syntactic rules of XML. 2.1.1 A dose of tag terminology When we talk about JSTL, it’s important to make sure we’re on the same page (so to speak). To ensure this, one of the less glamorous things we need to do is cover some XML terminology. We’ll also explain the terms and idioms that are used most com- monly by JSP and JSTL users. As you probably know from your experience with HTML, tags often come in pairs: one tag, which might look like , starts a block; and a corresponding tag, such as , ends it. Figure 2.1 shows an example of an XML element—a block of XML between, and including, corresponding start and end tags. The element begins with a start tag, optionally contains a body (some inner text, tags, or both), and wraps up with an end tag. www.it-ebooks.info
  16. 22 CHAPTER 2 Foundation: XML and JSP Table 2.1 Some relevant rules of XML syntax, with examples of violating and compliant markup (continued) Rule HTML example (violating rule) XHTML example (following rule) Empty elements must be closed A few straightforward rules Most of these rules are self-explanatory. When writing plain HTML, you can be somewhat sloppy without causing any problems. When constructing a list, you can start a list item with but neglect to end it with . You can mix uppercase and lowercase freely. And, you can leave off quotation marks in tag attributes (mod- ifiers within a tag) in most cases. You can still do all these things when you use JSTL, as long as you’re just trying to produce HTML pages and not strict XML pages. However, no matter how you use JSTL tags, you need to introduce them into your page following the rules in table 2.1. For instance, your document’s tags can be written as , and you don’t need to explicitly end all your HTML tags—but your JSTL tags must have their attributes quoted and must appear in the proper case. Empty tags must be closed The final rule in table 2.1 is one of the more confusing to HTML authors starting out with XML or JSTL. In well-formed XML, every tag that’s meant to be empty must be closed immediately, using either the longhand form shown earlier ( ) or the vastly more common shorthand ( ). Again, if you’re producing loose HTML with your JSTL pages, you don’t have to worry about your tags. But if you introduce an empty JSTL tag—for instance, —into your page, you need to close it or use the shorthand empty-tag syntax. TIP If you are trying to produce well-formed XHTML pages, instead of loosely structured HTML documents, you might run into a problem. Some older browsers aren’t smart enough to recognize empty tags like or . They expect the loose form of HTML, where the tag is not necessarily closed. In such cases, you can use the expanded form ( ). Often, to avoid this cumbersome syntax, you can simply insert a space between the ; many browsers (even the older ones) can handle this correctly. Thus, tags end up looking like or —note the spaces before the />. www.it-ebooks.info
  17. Introduction to JSP 27 Now, suppose b.jsp contains the following text: Welcome to b.jsp. Then a.jsp will output the following: Welcome to a.jsp. Now including b.jsp . . . Welcome to b.jsp. The contents of b.jsp have replaced the tag in page a.jsp. Note that, because the tag (as used here) does not contain a body, it is closed by placing a forward slash before the closing angle bracket. As we described earlier, JSP tags—which follow XML syntax—need to be closed in this fashion if they are empty. The tag can only include local files—files from the same JSP engine servicing the page in which appears. Either static or dynamic files can be included. That is, the tag can include a simple text file, another JSP page, or even a servlet or other arbitrary resource on the local server. WARNING If you are an experienced designer of web applications, you might have used the HTML tag. This tag allows you to specify a location that all tags like and will use as their base. That is, if you specify a new base with then a tag like will cause the browser to try to load not the local image.jpg file in the same directory as the web page. The tag, however, does not affect the way that JSP tags like operate. To a JSP engine, the tag is arbitrary HT- ML. has its effect because the browser interprets it and uses it to modify the way the rest of the page loads. But JSP engines do not interpret HTML tags; they simply pass them through to the browser. Therefore, al- though it makes sense to think of as finding files in a manner similar to and , the analogy is not perfect. always looks for files on the local server. A typical pattern is to use to include header and footer text in mul- tiple pages. For instance: Page contents www.it-ebooks.info
  18. 32 CHAPTER 2 Foundation: XML and JSP Table 2.3 Before you can use a tag library, you need to import it. You can use the following lines to import each JSTL library into your page. For each page, you only need to import the libraries you actually use, although there’s no harm in importing all of them. JSTL tag library directive Core XML Formatting Database In this book, I won’t always show the directive every time I give you a short example of a JSTL tag. However, you’ll need to include these directives if you plan to run the tag. (All source code available from the Manning web site includes the appropriate directives, as do this book’s longer examples.) 2.2.4 Other JSP directives In addition to , JSP has two other directives that are worth looking at quickly. As you just saw, directives are pseudo-tags that have special meaning to the container; they are not passed through to the browser but, instead, are processed by the JSP engine. This section is, by necessity, somewhat technical; you will not miss much if you skip it and come back to it later. The directive Earlier in this chapter, you saw how to include other pages using the tag. JSP also has a directive that lets you include other files: . It takes a file attribute corresponding to a relative path, similar to the tag. For instance, to include b.jsp from a.jsp, you could use a directive like Why have two mechanisms to include data? The difference between the two is somewhat subtle and technical, but it boils down to this: the direc- tive works by finding the target file and inserting it into your JSP page, just as if you had cut and pasted it using a text editor. By contrast, locates the tar- get page while your JSP page is executing. This difference in operation implies the following differences in behavior:  If a file included with changes, its changes will not be noticed until the page containing the directive also changes. Recall from chapter 1 that the JSP engine notices when files are changed and processes them automatically. However, the container doesn’t keep track of www.it-ebooks.info
  19. Introduction to JSP 37 Figure 2.8 Page scope lets one part of a page share data with another part. Request scope Earlier in this chapter, we looked at the and tags. These tags have something in common: they tie together multiple pages. To access web pages, a web browser makes a request for data from a web server. If this request hits a JSP page that uses a or tag, then multiple JSP pages can be used to service a single request. All of the pages that are used to respond to a single request have access to a common request scope. For instance, as suggested by figure 2.9, a page that uses can use the request scope to transfer data to or from the pages it includes. Request scope is use- ful if the target page needs to act differently depending on an event that occurred in the page that includes it. Or perhaps the target page wants to set a variable that the page using needs to access. Either way, request scope—which is broader than page scope—can be appropriate. Figure 2.9 Request scope lets pages linked by or communicate among themselves. Application scope In the world of server-side Java programming, the term web application has a spe- cific meaning. A web application is a collection of JSP pages and other resources, like servlets and HTML pages. Typically, a web application is located under a common directory on the web server, and it represents a cohesive unit of func- tionality. For instance, an entire online store or auction site is a good candidate for a web application. www.it-ebooks.info
  20. Part 2 Learning JSTL Now that you’ve seen the tip of the iceberg, it’s time to focus on the details and principles of JSTL. We’ve discussed what JSTL’s supposed to do; now you get to see how it works. Part 2 introduces and demonstrates nearly every JSTL tag. (We’ll leave two tags until later.) We start with the most fundamental ones: those that handle sim- ple decisions and loops in your pages. Then, we explore all the features JSTL has to offer, from databases to powerful XML support. Although part 2 is designed as a tutorial and reference, we do (when appro- priate) take a step back and look at useful examples of JSTL in action. For more in-depth examples, see part 3. www.it-ebooks.info
  21. www.it-ebooks.info
  22. The expression3 language This chapter covers  JSTL’s expression language syntax  Printing dynamic content  Storing and retrieving scoped variables  Producing and reading HTML forms 43 www.it-ebooks.info
  23. Expressions and the tag 47 times, instead of printing nothing, you want to print an error message, placeholder, or other default value. For cases like these, takes a parameter called default. If value’s expression fails for any reason, default runs instead. For instance, look at this tag: This tag works just like the first tag we presented; but if ${username} doesn’t produce a sensible value, then the tag simply prints out the static text Nobody. The tag can also accept a body, which you can use as another way of speci- fying a default value. Thus, the following tag is equivalent to the last one: Nothing This tag can be useful if your default value is too long to fit conveniently inside an attribute. Or, you can stick other JSTL tags in the body, and they’ll be used as the default if ${username} doesn’t produce a sensible value. 3.1.4 Special characters and You should know one more useful thing about . By default, it makes sure that any characters with special meaning to HTML or XML are escaped using the entity references we discussed briefly in chapter 2. This feature lets you use without worrying that your data will get in the way of the HTML or XML output you’re producing. Imagine that a scoped variable contains the text AT&T, or , or another string that has one or more characters with special meaning to XML. (The following char- acters are special to XML: &, , ', and ".) By default, if you print such a variable with , any special characters that it contains will be escaped as &, <, and so forth. This escaping causes HTML browsers to display the characters to the user instead of treating them as part of HTML or XML tags. For example, if the vari- able eye contains the text , then will output <o> where < stands in for . Thus, an HTML browser will display the text —the original value of ${eye}—to the user. If were instead to output unescaped, then the browser would see an unrecognized HTML tag, and the user wouldn’t see the information at all. www.it-ebooks.info
  24. 52 CHAPTER 3 The expression language matical way of expressing statements like, “If I took my wristwatch off, it must be on the nightstand. But it isn’t on the nightstand, so I must not have taken it off. Or maybe I’m just growing senile.”) A boolean variable has two possible values: true and false. These values can also be interpreted as “yes” and “no.” Whereas strings and numbers can take on virtually unlimited values, a boolean variable can store only these two values. This limitation makes boolean variables particularly useful for yes-or-no ques- tions. For example, the escapeXml attribute for that we discussed in section 3.1 is a boolean attribute: it needs a boolean variable. Our earlier example showed escapeXml being used as follows: In this case, escapeXml was given the static value false. But just as ’s value attribute can accept expressions, so can escapeXml. If the scoped variable status has a boolean value, you can write this: This tag will decide whether to escape special characters depending on the value of the scoped attribute status. In chapter 4, you’ll see how to set scoped boolean variables. If you print a boolean value using , it will be printed as "true" or "false", as appropriate. NOTE Java has two different boolean data types: boolean and Boolean. (Java is case-sensitive, so these represent different types.) For our purposes, they are nearly identical, so you don’t have to worry about the differences be- tween them. Collections When a scoped variable is a string, number, or boolean, it stores exactly one thing: a piece of text, a number, or a truth value. Sometimes, however, a single scoped variable can store an entire collection of objects. The most obvious example, in our mercenary world, is a shopping cart. An application might make a shopping-cart variable accessible as ${sessionScope.shoppingCart} Such a variable refers to an entire collection of objects, organized under a single name: shoppingCart. www.it-ebooks.info
  25. Request parameters and the expression language 57 Summer Fall Languages you can read: English Spanish French Ontological speculations: It should be easy to see how the individual tags in listing 3.1 line up with the various parts of the form shown in figure 3.4. Let’s look at each piece of the form in turn. The tag An HTML form begins with and ends with . Between these two tags come tags for the various form elements, such as , , and . We’ll look at these individual tags in a moment; for now, I want to draw your attention to the start tag for : This tag has two attributes, method and action. The action attribute is more impor- tant for us. It functions basically like href in or src in —that is, it lets you enter a link. For our purposes, this link will typically be a relative URL and point to a JSP file in the current directory. The action attribute means, “When the user sub- mits this form, what page should I load, and where should I send the input?” For example, the tag we just looked at causes a page named formHandler.jsp to run and receive the form’s input when the user submits the form. (You’ll see in a moment how the user submits a form.) The value of the method parameter doesn’t matter much for now, but you can think of it this way: by default, or if method="get", all of the form’s input will show up encoded into the URL. (You’ll see more about the way this data is structured in chapters 5 and 6.) By contrast, when method="post", this data is hidden from the casual observer and is instead sent to the target page using a different behind-the- www.it-ebooks.info
  26. 62 CHAPTER 3 The expression language tle. The entire block of text the user types into a comes back to your JSP page as a single parameter. For example, the entire box created by comes back as a single parameter: ${param.philosophy}. Submitting a form To add a submission button to a form, you add an tag with the attribute type="submit": This tag adds a button to the form (labeled with whatever’s inside the value attribute); when the user clicks it, the form is sent to the page named in the action attribute of the original tag. TIP Submission buttons created with can also have name attributes. That is, they can also create request parameters. For in- stance, a button like will set a request parameter ${param.choice} equal to the string Register. This functionality is particularly useful if you want your form to have multiple submission buttons, and you want to figure out which button the user clicked to submit the form. 3.3.2 A page that reads request parameters We ’ve spent quite a bit of time discussing HTML forms and individual request parameters. Let’s look, at last, at a dynamic page that reads some parameters. As an example, we’ll write a page called formHandler.jsp that handles the form in figure 3.4 (and listing 3.1). To get this page to work, simply add it to the same directory as the page that produced the form. Listing 3.2 shows an example of such a page. Listing 3.2 formHandler.jsp: a page that prints out the results of a form Wow, I know a lot about you Your name is . Your password (sssssh!) is ' '. You are . www.it-ebooks.info
  27. More powerful expressions 67 Table 3.5 JSTL expressions involving pageContext. These somewhat involved expressions are useful if you need detailed information about the current page’s environment. Normally, you won’t need to use such expressions, but they come in handy on occasion. (continued) Expression Description Sample value ${pageContext.request. Your page’s entire query string p1=value1&p2=value2 queryString} ${pageContext.request. The URL used to access your page requestURL} page.jsp ${pageContext.session. true if the session is new; false true new} otherwise ${pageContext.servlet- Information about your JSP container Apache Tomcat/5.0.0 Context.serverInfo} ${pageContext. For a page marked as an errorPage, "Something very, very exception.message} a description of the error that bad happened" occurred 3.4.3 Comparisons You can use the expression language to produce boolean values even when your inputs aren’t boolean. For instance, the expression ${2 == 2} results in true. Note the use of two equal signs (==) as a way of comparing two values. Many programming languages, including Java and JavaScript, use similar syntax, so it might look familiar. Table 3.6 lists the JSTL expression language’s comparison and equality operators. Table 3.6 JSTL supports these comparison and equality operators in expressions. You can use these operators to write expressions like ${2 == 2} or ${user.weight gt user.IQ}. Every comparison operator has a symbolic version (==) and a textual one (eq). Operator Description Sample expression Result == Equals ${5 == 5} true eq != Not equals ${5 != 5} false ne Greater than ${5 > 7} false gt = Greater than or equal to ${5 ge 6} false ge www.it-ebooks.info
  28. 72 CHAPTER 3 The expression language take the result of this attribute—which may, of course, contain expressions—and save it to the variable indicated by var and scope. For instance, consider the following tag: This tag stores the value 4 in a scoped variable named four. The scoped variable named four is given page scope. If you wanted to store it in the session, you’d instead write The tag can take any kind of JSTL expression in the value attribute; it can result in a string, number, boolean, collection, or anything else. Using the tag’s body If you write a tag without a value attribute, then will take what- ever appears in its body and save it to the scoped variable indicated by var and scope. It’s important to realize that if other tags appear within ’s body, these tags will be evaluated; like the browser itself, only sees their output. This process might seem unusual, and it’s the first time we’ve encountered a concept that will keep coming up in JSTL. JSP lets every tag have access to the out- put of its body. Normally, everything in your page simply gets printed to the browser; either it’s template text and gets printed directly, or it’s a tag and can pro- duce dynamic output (see figure 3.6). But when template text and tags appear inside another tag, the inner text and tags don’t get a chance to send their output directly to the browser. Instead, the parent tag collects the output from its body and then decides what to do with it. It can decide to send it on to the browser, to save it to a scope variable, or to ignore it completely; it’s the tag’s choice (see figure 3.7). In Figure 3.6 Normally, all template text and JSTL tags in your page get the opportunity to output directly to a web browser. The template text goes right through (as itself), and the JSTL tags (like ) have a chance to produce dynamic output that, by default, gets sent to a web browser. www.it-ebooks.info
  29. Controlling flow with 4conditions This chapter covers  Simple conditions  Mutually exclusive conditions  Nesting condition tags  Syntactic rules for JSTL conditions 77 www.it-ebooks.info
  30. 82 CHAPTER 4 Controlling flow with conditions 4.2.2 Using within HTML tags Because JSP doesn’t draw any distinction between plain text and HTML tags, you can use tags anywhere in your page—even in the middle of an HTML tag. For instance, consider this use of a tag: color="red" > This code prints the user’s name in red if the user is a doctor. The code checks the user.education property and, if it is equal to doctorate, outputs the following (ignoring white space) where name is the user’s name, as output by the tag: name If user.education is different from doctorate, we instead get name In the first case, the HTML tag explicitly sets the text color to red, whereas the latter case uses the default color. Recall from chapter 1 that the browser doesn’t care how an HTML markup tag was generated—whether it was template text, the output of a JSTL tag, or both. Thus, JSTL tags, like , can easily be used to produce HTML tags or parts of them. 4.2.3 Multiple tags When tags appear next to one another, they act independently: Error 1 has occurred. Error 2 has occurred. This example assumes that when certain errors have occurred, your page (or back- end Java code) has stored the value true in page-scoped boolean variables called error1, error2, and so on. (You’ll see how to create such variables in section 4.2.5.) www.it-ebooks.info
  31. Yes-or-no conditions with 87 Dr. then the page might appear inconsistent to the user. After a certain point in the page, the Dr. title will appear; but at the beginning, it won’t. This difference might not matter; but if consistency is important, we should record the value—whatever it happened to be at a particular point—and then use it for the rest of the page. The var attribute allows us to do this. Consider the following example: Saves variable A serious error has occurred. [ large page body ] Uses variable Since a serious error occurred, your data has not been saved. In this example, when the first tag is reached, the expression in its test attribute is evaluated, and the result is saved into a page-scoped variable called error1. From this point forward, even if the value of flags.errors.serious.error1 in the ses- sion scope changes, the local error1 variable will stay the same. Thus, even if the session-scoped flags.errors.serious.error1 flag changes for any reason, the user will be given a message at the bottom of the page that is consistent with the one displayed at the top. (Note also that in the second tag, we save some typing by using our own shorter variable name.) Although most tags have a body, JSTL’s don’t require them to. So, you can use to write a tag whose only purpose is to expose a scoped variable. For example, the following empty tag exposes a boolean variable named error1: This tag isn’t used to make a decision during execution of the page; later tags on the page, however, can use the error1 variable that this tag creates. www.it-ebooks.info
  32. 92 CHAPTER 4 Controlling flow with conditions Error 3 has occurred. Addition of Everything is fine. to display the default message The example now prints out a reassuring message—by way of the optional tag—if ${error1}, ${error2}, and ${error3} are all not true. Example 3 Let’s consider a slightly more involved example. In the first example in this chap- ter, we discussed a tag used to print the text Dr. if user.education indi- cated that the user had a doctorate. In that example, Dr. would either appear or it wouldn’t; there was no third choice. Instead of this simple yes-or-no choice, let’s look at an example that prints one of three choices—Dr., Ms., or Mr.—as appropri- ate. To do this, we have our tags check both a user.education property and another property, user.gender: Dr. Ms. Mr. We use two different properties of the user variable, but all our tests are grouped under a single tag. The result is that an appropriate title (Dr., Ms., or Mr.) is displayed in all cases. Note that the check for Dr. appears first because it transcends gender. If we checked for a particular gender first, we would miss all the members of that gender who were also doctors. Instead, we want to check gender only if the user is not a doctor. This example demonstrates that JSTL strictly adheres to the order of your tags. If the first tag succeeds, then the second (and remaining) tags won’t be evaluated; if the second succeeds, then the third (and remaining) tags won’t be evaluated; and so on. The tag does not accept a var attribute, but it can use boolean vari- ables exposed by earlier tags. www.it-ebooks.info
  33. General-purpose looping with 97 The basic function of is to consider every item in the collection specified by its items attribute. For each item in the collection, the body of the tag will be processed once, with the current item being exposed as a page-scoped variable whose name is specified by ’s var attribute. Because this variable takes a different value for each loop, the body of the tag can print different text each time it is evaluated. Let’s make this behavior concrete. Consider the following use of : This tag loops over every item in the medicalConditions property of the user variable. If this property contains a list of medical conditions, like gingi- vitis, myopia, and dehydration, then the example will print a string for each of these items. You can also include static template text inside a tag’s body, in which case it will appear unchanged for each loop that makes. For example: Sorry, you are afflicted with the following minor medical conditions: If ${user.medicalConditions} contains the three conditions I mentioned earlier, this fragment will output the following HTML (ignoring white space): Sorry, you are afflicted with the following minor medical conditions: gingivitis myopia dehydration The template text outside the tag is, of course, included only once. For instance, this example prints only one tag. But text within the 1 In case you encounter specific Java types when talking with Java programmers—or in case you’re a developer yourself—you might be interested to know the names of the data types accepts. They include arrays, Collection variables (including Lists and Sets), Maps, Iterators, and Enumerations. As you’ll see in section 5.2, it can also accept simple strings. www.it-ebooks.info
  34. 102 CHAPTER 5 Controlling flow with loops Both and accept three optional attributes in sup- port of subsetting, as shown in table 5.3. Table 5.3 Subsetting attributes for and Attribute Description Required Default begin Item to start the loop (inclusive; 0=first item, 1=sec- No 0 ond item). end Item to end the loop (inclusive; 0=first item; 1=sec- No Last item ond item). step Iteration will process every stepth element (1=every No 1 element, 2=every second element). JSTL assigns an index to every item in a collection; this index represents the item’s place in the overall collection. For each collection, the index begins with 0, which— interestingly enough—corresponds to the first item. Each successive element takes the next index number: the second element has an index of 1, the third element has an index of 2, and so on. The begin and end attributes accept numbers corresponding to these indexes. By default, and process the entire collection available to them; like dutiful cogs in a machine, they start at the beginning and finish at the end. The begin and end attributes override this default behavior by identifying par- ticular start and end indexes. The begin attribute directs the tag to start with the item at a particular index, and end causes iteration to end with a particular index. For example, begin="0" and end="4" together instruct that a or tag should begin with the first element and end with the fifth. Simi- larly, when a or tag is given the attributes begin="5" and end="9", only the indexes 5, 6, 7, 8, and 9 will be included (that is, the sixth through tenth elements). WARNING Be careful! Because 0 represents the first element, end="4" will cause iter- ation to proceed through the fifth element. Zero-based indexes can be con- fusing, but many programming languages adhere to them for consistency. If you have worked with JavaScript or Java before, you probably are famil- iar with zero-based indexes. (Zero-based indexes are not limited to pro- gramming languages. Not too far from where I live, a highway mile marker labeled 0 indicates the beginning of the highway. As a program- mer, it warms my heart.) www.it-ebooks.info
  35. Loop example: scrolling through results 107 The count property, on the other hand, starts with 1 and reflects the current loop’s position among the items for which runs its body. No matter what, count always increases by one for each loop. For any or tag, count will be 1 the first time the body is processed, 2 the second time, and so on. The first and last properties are boolean properties indicating whether the current loop is the tag’s first or last, respectively. (The first property is just a convenient way of checking to see whether count currently equals 1.) The count attribute’s behavior isn’t affected by the begin, end, or step attribute. Figure 5.2 shows the values of these properties for a sample iteration.2 Figure 5.2 Values of the varStatus variable’s properties during a sample iteration. The tag in this figure iterates three times, producing the letters a, c, and e. The boxes above each letter show the values of the varStatus variable for that letter’s loop. 5.4 Loop example: scrolling through results Earlier, we discussed how you can use the begin and end attributes to display only part of a collection, in cases where the collection is too big to fit reasonably on a single screen. Many applications, when they have too much information for a sin- gle page, let users pick the information to view. For instance, the user can decide whether to display results 0 through 19, 20 through 39, and so on. 2 The variable that varStatus creates has some other properties, but they are intended more for developers of custom tags than for page authors. If you’re a Java developer and are interested in these extra properties, see the LoopTagStatus interface in appendix B. www.it-ebooks.info
  36. 112 CHAPTER 5 Controlling flow with loops To pick out every second row, we use the expression ${status.count % 2 == 0}. Recall from chapter 3 that % in JSTL’s expression language is a remainder operator. Thus, status.count % 2 means, “Divide status.count by 2 and take the remain- der.” This remainder will be 0 only for the even rows. Thus, only these rows print in a smaller font in figure 5.4. Note that we use the same condition twice: once to open a tag, and once to close it with . Figure 5.4 Many web sites display alternating rows in different colors. Because colors don’t show up well in a black-and- white book, our example of handling alternate rows uses font size instead of color. Here, every second row prints using small text. www.it-ebooks.info
  37. Including text with the tag 117 Another important task you’ll need to handle when you write dynamic web pages is managing Uniform Resource Locators (URLs). You need to use URLs when you import content with , but URLs show up in other places as well. For example, every time your pages display hyperlinks (HTML tags) to other pages, they use URLs. In this chapter, we look at and other tags that help you manage and use URLs. We’ll also show how you can communicate with the pages you include, in order to customize their output. 6.1 Including text with the tag To retrieve content from a local JSP page or from another server, you can use the tag. Sometimes you’ll just want to print the information that you retrieve, but also lets you store the retrieved text in a scoped variable instead of printing it. Table 6.1 shows the tag’s attributes. Table 6.1 Basic tag attributes Attribute Description Required Default url URL to retrieve and import into the page Yes None context / followed by the name of a local web application No Current context var Name of the attribute to expose the String No None contents of the URL scope Scope of the attribute to expose the String No page contents of the URL The crucial attribute is url, which specifies the URL of the content to retrieve. The other attributes let you modify the way the tag handles its URL.1 Often, a page that uses is called a source page, and the page whose contents are included with is called a target page. 6.1.1 Absolute and relative URLs Yo u ’re probably familiar with the basics of URLs simply from browsing the Web. A URL, which is often called a web address by the sort of person who’s captivated by 1 The tag has a few advanced attributes that you’ll need only if you’re performing relatively sophisticated text imports. See chapter 14 for more information about advanced techniques. www.it-ebooks.info
  38. 122 CHAPTER 6 Importing text The context attribute names another web application on the same server as the page you’re writing. This name needs to start with a forward slash (/). For instance, consider the following tag: This tag imports the page /directory/target.jsp from the web application named “other” in the same JSP container as our source page. Thus, the URL that appears in the url attribute is treated as if it is relative to the root of this other web application (that is, the other context). Using expressions Of course, you’re not limited to using URLs that you type literally into the tag’s url attribute. The tag supports the full range of JSTL expressions. For instance, the target URL can come from an expression, as follows: This tag looks up the target attribute in the application scope, treats it as a URL, and retrieves information from this URL. The context attribute can also come from an expression: 6.1.3 Saving information for later By default, retrieves information from a URL and then immediately prints it to your page. This is exactly what does, and in most cases, it’s also what you want. However, suppose you don’t want to immediately print the data you retrieve. Sometimes, for instance, you want to import a page and then include its text multi- ple times in your page. (As an example, imagine a file that contains nothing but some HTML formatting to produce a stylized, horizontal line.) Or you might want to retrieve some text every time the user logs in, and then store this text in the user’s session scope for use during the user’s session. Saving data from lets you avoid having to retrieve the contents of a URL multiple times, which can sometimes take a long time and slow your pages. To save the result of instead of printing it out, you can use the var attribute. Specifying a var attribute to the tag causes the tag to not out- put anything. Instead, the tag will simply retrieve text and save it to a scoped vari- able. As with other JSTL tags, you can also use a scope attribute to set the scope of the variable you create. (As usual, when you use var and scope, you need to specify the name and scope manually; you can’t use expressions in these two attributes.) www.it-ebooks.info
  39. Including text with the tag 127 Figure 6.3 lets you communicate simple request parameters, which take the form name=value. Request parameters are flexible, but they can only consist of simple text strings, and they only support one-way communication (from the source page to the target). web site, you might appreciate the simplicity of and the fact that, when you use within , you can immediately see what data two pages share. If you want to understand two pages that use scoped variables, you may need to spend more time looking at the source code for both the source and the target. Figure 6.4 In contrast with request parameters, scoped variables—which can be accessed by both the source and target pages of a tag—can include arbitrarily structured data. They support two-way communication as well. However, they only work for target pages within your web application. 6.1.5 Import example: a customized header Let’s look at a concrete example of pages communicating with one another using . Many web applications need to standardize the appearance of a header throughout the application. We’ll throw in a twist, however: in our example, the header will display a customized title that the source page (the one using www.it-ebooks.info
  40. 132 CHAPTER 6 Importing text Figure 6.8 source.jsp sets a variable and then imports target.jsp, which reads the variable. Before target.jsp finishes, it sets its own variable, which source.jsp later reads. Figure 6.9 source.jsp displays output that looks like this when loaded by a web browser. 6.2 Redirecting with In some situations, your web pages need to act like seasoned bureaucrats and refer you elsewhere. Fortunately, web browsers tend to have more patience than most people do. Normally, when a browser sends a request for a web page, it receives back an HTML file, image, or other content in response. Sometimes, however, it gets redirected to another page. Essentially, the server says, “I don’t have what you want; go look here instead,” where here is a particular URL the browser needs to fol- low. The browser then loads this URL and displays its content—or perhaps it’s redi- rected to yet another URL. www.it-ebooks.info
  41. Summary 137 Here, the tag is embedded within the tag’s src attribute; it causes the URL to be transformed appropriately so that the user’s browser can understand it. You can use ’s context attribute to create a URL to a page in another web application in your JSP container. The tag is also useful if you want to save a URL (using the var and scope attributes) and use it multiple times in your application. 6.4 Summary In this chapter, we looked at tags that support text retrieval, redirection, and URL management. Key points to remember include the following:  works like , but it lets you retrieve data from absolute URLs, as well as pages from different web applications on the same JSP server. It also lets you save data instead of printing it out immediately.  If the source and target pages are in the same web application, then they can share variables in request, session, and application scope. Doing so allows two-way transmission of whatever data you’d like (including, of course, sim- ple strings).  lets you bounce the user to a new page, using either an abso- lute or relative URL.  Whenever you write out a relative URL to a page, you should use instead of printing the URL directly. Doing so makes sure sessions work even in browsers that don’t support cookies, and it also simplifies use of context- relative URLs (those that begin with /).  lets you pass simple text strings from the source page to the target page. It works with , , and . www.it-ebooks.info
  42. 142 CHAPTER 7 Selecting XML fragments Figure 7.1 The tree structure of a sample HTML document. When an element like occurs inside , you can think of it as a child of that element. 7.2 XPath’s basic syntax XPath operates on documents using the type of tree structure you just saw. As you probably know, trees are commonly seen on computers. On nearly all modern operating systems, for example, a disk is organized into directories (or folders), each of which can contain other directories. This kind of organization naturally arranges itself into a tree, and we often speak of child directories or subdirectories when we dis- cuss disks. XPath takes advantage of our familiarity with traditional filenames, applying a similar syntax to the tree representing an XML document. If you have three direc- tories on your disk—a, b, and c—and you are running Windows, you can refer to these directories as follows: c:\a\b\c Note how the backslash character (\) is used to separate the directory names. Unix systems use the regular slash (/) character in a similar capacity: /a/b/c XPath adopts this Unix convention, using the slash character to separate the name of one XML element from another. For example, in the tree from figure 7.1, the element could be described by the following path: /html/body/p/b This XPath expression matches the highlighted part of our sample document: Poem Poem www.it-ebooks.info
  43. XPath variables and JSTL 147 Therefore, //p is true if it is applied to a document that has at least one ele- ment, and it’s false if the document has no elements. NOTE XPath expressions are more flexible than I’ve shown here. For instance, they can also call functions that directly return numeric values, boolean values, and so on. XPath also provides general rules for converting be- tween numbers, booleans, and other types of data. Details about XPath data types are beyond the scope of this book because they’re not needed to use JSTL; see appendix D for references to more information. 7.3 XPath variables and JSTL Like many languages, XPath supports variables. Just as in JavaScript, Java, and other languages, XPath variables are evaluated and replaced with actual values, which might be different every time an XPath expression executes. JSTL depends on XPath variables in a somewhat novel way: it maps them to dynamic scopes that resemble JSTL’s expression language. Therefore, XPath vari- ables can refer to things that are similar to those the familiar expression language can refer to (see chapter 3). Broadly speaking, an XPath variable is simply a qualified name (see chapter 2) introduced with a dollar sign ($). That is, it’s a dollar sign followed by either a name without a colon, like stomach, or a name with a colon, like large:intestine. The XPath expressions we’ve presented until now haven’t used variables; they simply contained text, as in /a/b/c You can introduce a variable into this static XPath expression. This variable can have a different value each time an XPath expression is evaluated. Variables can refer to data from a variety of sources. For instance, the expression $pageScope:document/b/c/d contains the variable $pageScope:document. Recall from chapter 2 that in the name pageScope:document, pageScope is a namespace prefix, and document is a specific, local name. JSTL recognizes the namespace prefixes listed in table 7.1. These prefixes have the same behavior as the implicit objects described in chapter 3 for the general-purpose expression language. Furthermore, just as in JSTL’s language, the default behavior when searching for a variable (the behavior when no namespace prefix is specified) is to search first in the page scope, and then www.it-ebooks.info
  44. 152 CHAPTER 7 Selecting XML fragments 7.6 Summary In this chapter we explored XPath’s basic syntax, in order to let you use XPath with JSTL. Keep in mind the following points:  JSTL’s support for XML manipulation depends on XPath.  XPath (the XML Path Language) can be used to select parts of XML documents.  XPath treats XML documents as trees and accesses individual nodes in the document in a similar manner to the way you access files on a disk.  You can use XPath to filter documents based on node names, attribute values, and even the order in which nodes appear. But be careful if your documents use namespaces.  XPath includes many more features than we’ve discussed here. Appendix D lists resources that will help you learn XPath in more depth, if you want to do so. www.it-ebooks.info
  45. Accessing XML with and 157 //table we’d write $doc//table This expression tells JSTL to find the doc variable, and then find all tags within the document it represents. It’s easy to confuse a variable that points to a document with the root element of that document. For instance, consider the following tag: To refer to the inner element, you could write $orders/orders/order, but not $orders/order. The inner element is not a direct child of the docu- ment; it is a child of the element. 8.2.2 The tag The tag evaluates and prints out the string value of an XPath expression; the starting node is often retrieved from an XPath variable. (For more information about string values, see section 7.2.) The tag is one of the most basic ways of introducing an XPath expression into your JSP page. The tag takes the attributes listed in table 8.2. Table 8.2 tag attributes Attribute Description Required Default select XPath expression Yes None escapeXml Whether to print characters like & as & No true Let’s look at in action. Suppose our page contains the following tag: www.it-ebooks.info
  46. 162 CHAPTER 8 Working with XML fragments match any elements. If customerId equals 525, however, then the expression will match the two order records for Jim Heinz. So, if Jim Heinz is the current customer (the one whose number is stored in customerId), we’ll match two nodes. For Roberto, we won’t match any. Note that we’re not interested in what the nodes are. For example, we couldn’t care less if the order number is 20005. Because we simply want to differentiate customers who have placed orders from those who haven’t, the mere presence of ele- ments for Jim Heinz (and their absence for Roberto del Monte) is decisive. Recall XPath’s boolean conversion rules from section 7.2: an XPath expression that matches one or more nodes is true, and one that doesn’t match any nodes is false. Therefore, our sample XPath expression is true for Jim Heinz because he has placed orders, and it’s false for Roberto del Monte because he hasn’t. Jim will therefore receive the special message intended for repeat customers, and Roberto won’t. Problem solved! Storing a boolean result The tag, just like , lets you save the result of a condition to a boolean variable using the var and scope attributes. As before, this tag has a number of uses:  To avoid wasteful re-evaluation of a condition.  To “lock in” a condition if you’re afraid it will change.  To use the result of a condition in a or tag that appears later in the page. (We’ll look at in a moment.) 8.3.2 Compound conditions with Just as the core JSTL library provides , , and for complex, mutually exclusive conditionals, the XML library offers , , and for compound XML-based conditions. Their use is identical to the core library’s, except that each tag uses an XPath expres- sion. Table 8.5 shows the attribute for . (As with the core library, the other mutually exclusive conditional tags don’t take attributes.) Table 8.5 tag attribute Attribute Description Required Default select XPath expression to evaluate. If true, process the Yes None tag’s body; if false, ignore the body. As a simple example of , , and , consider the following small document, which you first saw in chapter 7: www.it-ebooks.info
  47. Control flow based on XML documents 167 color="#000000" color="#888888" > In this case, preferred customers are printed in a deep black (color="#000000"), and regular customers are printed in a lighter gray (color="#888888"). Ignoring white space, the example outputs the following HTML text: Jim Heinz Roberto del Monte Richard Hunt Note how we use XPath’s @ syntax to refer to attributes of the context node. Read the expression “@status=’preferred’” as “Does the current node’s status attribute equal preferred?” Nested iteration If a tag appears inside another , it inherits the outer tag’s context node. Consider the following sample document: www.it-ebooks.info
  48. 172 CHAPTER 8 Working with XML fragments The JSP page in listing 8.1 is an archetypal example of how to use XSLT from JSTL. First, a tag sets the xml variable with body content that appears directly in the page. (Of course, this inline content could easily be replaced with a tag to fetch a document from elsewhere). Next, another tag sets the xsl variable using a simple, typed-in stylesheet. (Again, this stylesheet could reside else- where, and the page could retrieve it using .) Finally, the applies the XSLT stylesheet to the XML document and outputs the result. The page therefore outputs the following, ignoring white space:3 This document uses unusual markup, which we want to replace with HTML . For information on how the XSLT stylesheet works, see the references listed in appendix D. 8.4.2 Using the var attribute If you specify a var attribute for , the document that results from the tag’s transformation is saved in a variable instead of being output to the page. This result can be useful in a number of situations. For instance, once you’ve stored the output of a transformation using var, the output can be used as input to another tag. Or, you can select portions from the resulting document using XPath and . For example, the final line of listing 8.1 is a simple tag that out- puts its result to the page: Suppose we replaced this tag with one that stores the document in a variable and uses it in an tag, as follows: If these two lines replace the final line in listing 8.1, the listing’s JSP page then out- puts simply HTML—the string value of the second tag in the resulting document. Instead of passing $doc2 to the tag, we could have passed it to another tag. Chaining XSLT transformations—applying them successively, using the output of one transformation as input to another—is a flexible technique 3 In this example, the XML declaration (beginning <?xml) is added by the XSLT processor that’s used behind the scenes to perform the transformation. www.it-ebooks.info
  49. An XML example: reading RSS files 177 This surprisingly short example is all we need to handle simple RSS files. We start by loading and parsing the RSS file from a URL specified by one of our request parameters, rssUrl. To pass the simpleRss.jsp page this parameter, we might use an HTML form like this: Enter the URL for an RSS feed: Once simpleRss.jsp has retrieved its RSS file over the Web, it loops over each tag in the RSS file and prints out its and children. We insert the contents of the item into an tag’s href attribute, and we print the headline ( ) as the body of the hyperlink. A sample result is shown in figure 8.5. (This example uses a news feed from CNet, which was available at the following URL at the time this chapter was written: news/rss/1,11176,,00.xml. See appendix D for more examples of RSS feeds.) Dealing with namespaces The simpleRss.jsp example is short and sweet, and it works for many RSS files, but it has a problem: it doesn’t work for newer types of RSS files that use XML namespaces. This limitation arises because, as you saw in chapter 7, XPath expressions like //item and link don’t match elements that use namespaces. To match these items in all RSS files, you need to use a slightly different syntax. Instead of writing //item to match all tags, we’ll need to use an XPath expression like this: //*[name()='item'] This expression matches all tags whose name is equal to item, regardless of the RSS document’s use of namespaces. Listing 8.3 shows a more general page that parses and prints out RSS documents. Listing 8.3 rss.jsp: converts an RSS channel (with namespaces) into a list of hyperlinks www.it-ebooks.info
  50. 182 CHAPTER 9 Database-driven pages When you need a user’s information to last for an entire session, you can store it in JSP’s session scope. However, some information needs to last longer than the ses- sion scope allows. For instance, you probably don’t want to make your visitors enter their prefer- ences each time they come to your site. Most users would prefer to enter their infor- mation once and have your site remember it. Some information—like a customer’s full name, address, and phone number—might not even have anything to do with the user’s session or web experience; you might simply need to gather this informa- tion for use offline, after the user has left, to process orders or conduct other busi- ness operations. To store data for long periods of time, you can use a software product called a relational database management system—abbreviated RDBMS but often, these days, described by the more general term database. Database packages include Oracle, Microsoft SQL Server, PostgreSQL, MySQL. Of course, simple files on disk can also store information for a long time. You might wonder why you should use a database when you can store data in straight- forward text files. The answer is that using databases is safer, and in many cases more convenient, than managing arbitrary files on a disk. Databases are designed to store structured information. When you write to files, you must devise a way to represent your data manually. For instance, you can separate names and phone numbers with commas, and then store each user’s record on a different line in the file. But this process is as error-prone as it is tedious, and it makes your file idiosyncratic. A missing comma might cause you to greet a user as “Dear Mr. 203-432-6687.” If other people or applications need to read your data, they must learn the format you personally devised and implemented. By contrast, databases provide standard interfaces to your data, and they help you organize it. Databases also help keep your data safe and consistent. A database can be set up to ensure that every entry for a customer comes with a phone number and birthdate, so you don’t accidentally end up with partial data. When databases guarantee the consistency—or integrity—of data, they let you focus on other considerations. You can set up a database once (or have a database administrator set one up) and then read and write data to it, confident in its ability to handle the data quickly and accu- rately. All the tags we introduce in this chapter come from JSTL’s sql tag library. (See chapter 2 for more information on JSTL’s various tag libraries.) To use any of the examples in this chapter, you’ll need to use a directive like the following at the top of your pages: www.it-ebooks.info
  51. Database connections with 187 To prepare connections to this database, we’d use the following tag: Because this tag doesn’t have a var or a scope attribute, it will replace the page’s default database. That is, any other database tags that appear later in the same page will use the database identified by this tag’s attributes. Sup- pose we add just a scope attribute, as follows: With this new attribute, the tag will set up a new default database for the user’s session. We could also specify scope="request" or scope= "application" if we wanted to set a default for the request or application scope. Setting a default is useful when your application has only—or primarily—one database to use. For instance, you can put an tag in a com- mon header file included with into your page. If such an tag has a scope="application" attribute, then it sets an application- wide default, and you may never have to think about again until you start working on a new application. When different default databases exist for the page, request, session, and appli- cation scopes, then JSTL’s database tags use page first, followed by request, session, or application. This sequence lets you set a default for a specific scope without destroying the defaults for more general scopes. For instance, you can use in a single page but rely on a session-scoped default database for other pages. If your application works with multiple databases, then instead of using to set a default connection, you might instead use it to expose a scoped variable that represents a database. You can do this by adding a var attribute: <sql:setDataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:." user="sa" www.it-ebooks.info
  52. 192 CHAPTER 9 Database-driven pages SELECT NAME, IQ FROM USERS WHERE IQ > 120 The SQL query in this tag produces a result with exactly two columns: NAME and IQ. The number of rows depends on the data itself—in this case, on the number of peo- ple in the USERS table who have IQs above 120. Table 9.3 shows a sample result for this SQL query. The user named Richard has an IQ of 132, Jonathan weighs in at a less-impressive 121, and so on. Table 9.3 A sample result from a database, with two columns and five rows NAME IQ Richard 132 Jonathan 121 Liz 140 Michael 162 Rachel 149 The job of is to retrieve a result—just like that in table 9.3—and expose it as a scoped variable. Such a scoped variable isn’t as simple as a string or number; instead, it’s divided into a number of properties. These properties let you access two things about a database result: I The data in the table I Information about the data (often called metadata) Figure 9.3 shows all the properties of the variable that each exposes. The first two, rows and rowsByIndex, are for accessing data. The remaining proper- ties—columnNames, rowCount, and limitedByMaxRows—just help describe the data. Accessing metadata Let’s begin by looking at the metadata. Suppose you’ve used an tag to create a variable called result. The simplest property of this result variable is rowCount. The expression ${result.rowCount} lets you retrieve the number of rows in the result. For instance, for table 9.3, rowCount would be 5, because five pairs of NAME and IQ values are listed. You can also use the result variable to retrieve the names of the columns in the result. The columnNames property is a list of column names. Recall from chapter 3 that you can access the items in an ordered list using square brackets ([]) and index www.it-ebooks.info
  53. Performing queries with 197 Figure 9.5 Sample output from printQuery.jsp, using the data shown in table 9.3. The generic printQuery.jsp page accepts any result from and formats it as a simple HTML table. 9.3.3 Limiting the size of a query’s result We use databases because they’re good at storing large amounts of data. If all appli- cations managed only a small amount of data, a general-purpose, relational data- base would probably be overkill. The size of databases, though, can lead to a problem: it becomes easy, with a simple query, to retrieve a set of results that is unmanageably large. For example, the documentation for PostgreSQL, a free high- quality database, says that some PostgreSQL installations have databases 60GB in size. (That’s more than 64 billion characters.) Imagine that your application has a large database, and you perform a query based on user input. You have a page that prints data for all customers who match the user’s keyword. Now, suppose the user enters an uninspired keyword like “Bob” that matches 50,000 rows. JSTL lets you prevent the query from going out of control by using two attributes of the tag: maxRows and startRow. The maxRows attribute The maxRows attribute is straightforward. When it appears in an tag, it ensures that no more than a specific number of rows will be stored by the scoped variable that stores. For example, the following tag might produce a very large result named customers: SELECT * FROM CUSTOMERS However, this tag will never store more than 20 rows in customers: SELECT * FROM CUSTOMERS www.it-ebooks.info
  54. 202 CHAPTER 9 Database-driven pages 9.5.1 Template queries One way to use queries like this is to customize them with simple JSP, just like you customize an HTML page. After all, JSP is great for adding dynamic content to oth- erwise static text. For example, we can use JSTL’s tag (see chapter 3) to fill in part of an SQL query: SELECT * FROM TABLE WHERE CUSTOMER_NUMBER= This is a simple way to use JSTL to modify a query. It effectively plugs the value of a scoped variable into an SQL statement. However, this technique is more problem- atic than it might seem at first. You’re not always working with numbers; sometimes you’ll use strings. In SQL, strings must be quoted with single quotes. So far, that doesn’t sound like a problem; we could just insert the quotes manually, like this: WHERE CUSTOMER_NAME=’ ’ However, if the customer’s name contains a quotation mark, like David O’Davies, the result will be the following unfortunate text: WHERE CUSTOMER_NAME='David O'Davies' Because escapes the quotation mark by default, it yields an incorrect value; SQL does not understand XML escaping. There’s even a security risk in building up queries manually. If you decide to get around ’s escaping problem by using the attribute escapeXml="false", a malicious user could purposely corrupt the query to retrieve private information or even alter your database. For example, suppose the user, instead of a name like David O’Davies, enters the following unexpected text: David’ OR CUSTOMER_NAME ’David’ Because every customer name is either equal or not equal to ’David’, this query will match every row in the table! Therefore, it’s not usually a good idea to use to build up an SQL statement yourself. 9.5.2 Safe, convenient parameters with JSTL lets you avoid these problems by using a special syntax borrowed from JDBC, the Java package that supports database connectivity. Using this syntax, you can www.it-ebooks.info
  55. Managing transactions with 207 five operations must be treated as a single unit. Operations that need to succeed or fail as a single unit are known as transactions. WARNING Although most well-engineered database systems support transactions, not every software product does. Before using the tags in this section, check with your software’s documentation or your database administrator to en- sure your database supports transactions. 9.6.1 The tag In JSTL, transactions let you treat a series of and tags as part of a unified whole. All query and update tags within a transaction succeed or fail together; there is no middle ground. If the end of a transaction doesn’t complete successfully, the beginning is stricken from the record: the database pretends it never happened. This sort of pretending is formally called rolling back, and it involves restoring the database’s state to a prior one—specifically, to the way things were before the first in the transaction executed. JSTL supports transactions with a tag called . This tag acts as a parent tag for and tags. Each tag Figure 9.8 The tag protects its and children. It does so by ensuring that these children succeed or fail as a unit. If any of the individual steps under an fails, the database will be rolled back to a prior state, as if the transaction had never begun. www.it-ebooks.info
  56. 212 CHAPTER 9 Database-driven pages number. We can create a suitable table, which we’ll call counter, using the follow- ing SQL command: create table counter ( counter integer ) NOTE You’ll need to type this command into your database’s text interface. The instructions for doing so vary from database to database, so you’ll need to check with your database’s manual or administrator to determine how to send it commands manually. (My hsqldb tutorial at Manning Publication’s web site describes the procedure for hsqldb. See appendix D for its URL.) If you have trouble sending commands to your database manually, you can enter the command into an tag and run the tag manu- ally by loading its page. This technique is somewhat clumsy, but it’s a de- cent alternative. For instance, the following tag will create the counter table in the default database: create table counter ( counter integer ) The counter table has a single column, also called counter, which stores an integer. Our table will contain a single row, and this row’s value for the counter column will represent the current tally of web-page hits. Before we use the counter, we’ll need to create this row manually. To do so, we can run the following SQL command: insert into counter(counter) values(0) This line initializes our database and sets the counter’s starting value to 0. Now that we’ve set up the counter table, we’re ready to look at a page that uses it. Listing 9.2 shows such a page.4 Listing 9.2 counter.jsp: a simple hit counter 4 Remember, this chapter’s examples, including listing 9.2, assume you have a default database set up. If you don’t, you’ll need to use the tag and the dataSource attribute for . See section 9.2. www.it-ebooks.info
  57. Printing numbers with 217 will output 500000.01 The tag prints the number in a simple, default form. Integers, for instance, are presented as a sequence of digits. Floating-point numbers are displayed similarly, but with a decimal point (.) separating some digits from the other digits. This simple format might be okay for many of your pages, but if a page prints out a lot of num- bers, or if presenting numbers is a page’s main job, then you’ll probably want more control over how numbers are printed. That’s what is for. 10.1.1 Basic usage of In its simplest form, you can use the just like . For example, we can write This usage is similar to : the tag has an attribute, value, that points to the number we want to print out. However, even in this simple form, the tag does something more interesting than : it prints the number using its best guess about what format the user wants to see. Web browsers can con- vey information about their locale—essentially, their location and preferred formats for numbers, dates, and other data. The tag can automatically sense this locale and customize its output. So, if ${netWorth} equals 500000.01, the simple we just presented will output the following values for these countries: Country Sample numeric format United States 500,000.01 France 500 000,01 Germany 500.000,01 Switzerland 500'000.01 As this table shows, the format is different for the United States, France, Germany, and (as you might know if you have a Swiss bank account) Switzerland. TIP If you’re using Windows and Internet Explorer, you can experiment with different locales by going to the Start menu and choosing Settings, then Control Panel, and finally Regional Options. From there, the General tab lets you pick your locale. (These instructions may vary slightly if you use www.it-ebooks.info
  58. 222 CHAPTER 10 Formatting and internationalization WARNING By default, the currencyCode attribute works only on JDK 1.4 and later versions. Check with your system administrator if you’re not sure what version of the JDK your JSP container runs on. If you use the currency- Code attribute on a system that has an older version of Java, the code you use will be printed as a currency symbol. I wouldn’t recommend this ap- proach; use the currencySymbol attribute instead. A separate attribute, currencySymbol, lets you set a specific currency symbol to use. For instance, you might write currencySymbol="$" to indicate the dollar. 10.1.5 Grouping digits together or not By default, arranges digits into groups that are appropriate for the browser’s locale. For example, as you saw earlier, the number 500000.01 is printed as 500,000.01 in English. This formatting is used because of the locale’s customary rules: groups of three digits are separated by a comma (,). In Switzer- land, the style uses groups of three digits separated by an apostrophe (’). You can use the groupingUsed attribute to explicitly shut off this grouping, which will cause the number to be printed without any group separator. Figure 10.1 shows an example. Figure 10.1 By default, the tag arranges numbers into groups of digits, using a locale-specific group separator. You can shut off this behavior with the groupingUsed attribute. The following two tags are equivalent because groupingUsed="true" is the default: For the English locale, these tags both print 500,000.01 www.it-ebooks.info
  59. Printing dates with 227 For more information on how patterns work, you can read the Javadoc page for the DecimalFormat class, which (for the version of Java that was current at the time this chapter was written) should be available at api/java/text/DecimalFormat.html. 10.2 Printing dates with Just as JSTL provides support for formatting numbers with , it gives you to help print out dates and times. Table 10.4 lists its attributes. Table 10.4 tag attributes Attribute Description Required Default value Date to print Yes None type Whether to print dates, times, or both No date dateStyle Preformatted style to use for the date No default timeStyle Preformatted style to use for the time No default timeZone Time zone to use when formatting the date No See section 10.5 pattern Explicit formatting pattern to use No None var Variable to expose the formatted date (as a string) No None scope Scope in which to expose the formatted date No page 10.2.1 Differences from Besides the obvious difference that is for printing dates and is for printing numbers, a few syntactic differences exist between the two tags. First, always takes a value attribute; this attribute is required. In addition, it cannot accept data from its body. The value attribute for must point to a date variable; it can’t simply point to a string that represents a date, like "Jan 1, 2001". There’s no good, unambiguous way for to accept and interpret strings as dates. That job is given to another JSTL tag, , which we’ll encoun- ter later. You can get real date variables a few ways. You might retrieve one from a data- base or receive one from back-end Java code. Or, you might use the tag we just mentioned, which we’ll describe in section 10.4, to produce a date variable. You can also produce a date using an advanced tag called . We ’ll leave this tag’s inner workings as magic for now; we’ll mention it again in www.it-ebooks.info
  60. 232 CHAPTER 10 Formatting and internationalization Tag Output 10.3 Reading numbers with So far in this chapter, we’ve only discussed outputting data—formatting dates and numbers and then (usually) printing them or (less frequently) saving them to scoped variables. JSTL has two tags that help you handle input: to help you read numbers, and to help you read dates. In many cases, you don’t need these tags. As you saw in chapter 4, JSTL lets you treat simple numbers as strings, and vice versa. For example, if the request parame- ter named boundary equals the number 50 because that’s what the user entered in an HTML form, we can say and the tag will know to stop its iteration after the fifty-first element. The tag is specifically for cases in which you need to parse— or interpret—more complicated numbers. If the user enters 50,000 (including the comma), or if you read values that contain commas or spaces from an XML file or database, you can’t treat these values as numbers; you need to parse them first. Table 10.7 lists the attributes that accepts. Table 10.7 tag attributes Attribute Description Required Default value The string to parse into a number No Body type How to parse the number (number, currency, or No number percent) www.it-ebooks.info
  61. Reading dates with 237 would work for the English locale, but would lead to an error because it lacks a comma. This behavior makes the default case almost useless for processing input from users, because it’s usually inappropri- ate to force users to be so specific in the values they enter. However, this use of is appropriate in a few situations: I It’s useful if you know you’re getting data that was printed with . I You can also use this simple form of if you’re generating a string based on individual fields of user input—for instance, a pull-down menu for month, followed by another one for date, and so on. See chapter 11 for an example of this technique. If given a var attribute, stores a scoped variable that holds a date and time (the time is always midnight in this simple case). Otherwise, it prints the date in a somewhat ugly, unlocalized format: Sat Aug 24 00:00:00 EDT 2002 You therefore almost always want to use a var attribute with (except, perhaps, if you’re just testing your page). 10.4.2 Changing how parses dates The tag comes with four attributes that let you change how it parses dates. The first is simple: you can use the type attribute to let the tag parse times as well as dates. Just as with , the type attribute has three possible values: date, time, and both; date is the default. If you specify type= "time", then tries to read and parse a time in the locale’s default representation (for example, "07:45:02 PM"). For type="both", the tag expects a default date/time combination, like Aug 24, 2002 08:52:00 PM The type attribute is somewhat limited when used alone. It can be useful when used in conjunction with two more powerful attributes, timeStyle and dateStyle. They let the tag accept the sorts of values shown in table 10.5, earlier in this chapter. www.it-ebooks.info
  62. 242 CHAPTER 10 Formatting and internationalization Figure 10.3 When the tag surrounds one or more or tags, the time zone from automatically applies to each of these child tags. 10.6 Overriding locales with Throughout this chapter, I’ve mentioned that tags use the user’s web browser’s pre- ferred locale by default. But JSTL page authors and back-end Java programmers can also influence the locale used for the and tags. Doing so can be useful if you want to give users a choice of locale instead of letting the browser automatically speak for them. Just as with time zones, back-end programmers have control over what locales are used; they can explicitly choose to override the browser’s locale. See chapter 14 for information (geared to programmers) about how to do this. JSTL also lets you control the locale using a tag: . Table 10.11 lists this tag’s attributes. Table 10.11 tag attributes Attribute Description Required Default value Name of a locale to use (see section 10.6.1) Yes None variant Specific variety of the chosen local to use (see No None section 10.6.1) scope Scope for which to override the locale No page As table 10.11 shows, value is always required. Using value, you can specify the name of a locale. This locale will become the new default for the scope identified by the scope attribute—or for the current page by default, if you don’t specify a scope attribute. (The variant attribute is beyond the scope of this book.) www.it-ebooks.info
  63. Internationalizing text messages 247 10.7.2 Loading a bundle family with and If no back-end Java code manages message bundles for your pages, or if you want to override the bundle, you can use the and tags. Table 10.15 lists the attributes for . Table 10.15 tag attributes Attribute Description Required Default basename Name of the resource-bundle family to use Yes None prefix String to prepend to each key (for long key names) No None Table 10.16 lists the attributes for . Table 10.16 tag attributes Attribute Description Required Default basename Name of the resource-bundle family to use Yes None var Variable to expose the bundle No None scope Scope in which to expose the bundle No page The difference between and is the same as the dif- ference between and . The tags with set in their names change the defaults for an entire scope, whereas the tags without set apply only to their child tags. JSTL’s two bundle-related tags let you describe a group of related bundles using the basename attribute. You’ll know the base name of a bundle if you’ve internation- alized an application yourself; if you’re using someone else’s bundle, then whoever internationalized the application should tell you the base name. The tag changes the bundle for all the tags in its body. For instance: When you use the tag like this, you can give it a prefix attribute. This attribute is a string that is added before every key in each tag www.it-ebooks.info
  64. Part 3 JSTL in action So far, we’ve looked at what JSTL is and how it works. You’ve seen a few exam- ples of JSTL in action, but now we’ll examine more closely how to handle practi- cal tasks using JSTL. In chapter 11, we’ll show how you can use JSTL to address some common but small-scale needs. In the chapters after that, we’ll discuss more in-depth examples of web development with JSTL. A minor warning is in order. In some cases, you won’t be using JSTL as a stand-alone technology. You might use it with Jakarta Struts, for example, or with tag libraries developed specifically for your site. We can’t cover all the technolo- gies that JSTL might interact with in this book; therefore, although most of the material in part 3 is core, nuts-and-bolts stuff that you can use immediately, some of the examples push JSTL to its limits. This is intentional; I think the best way to learn a technology is by trying to use it creatively. So don’t be surprised if some of the examples use JSTL for tasks that you might otherwise solve with a custom, local library or with Struts. The examples here aren’t designed to demonstrate principles of web-application architecture; books like Web Development with Java- Server Pages1 already address that topic quite well. Instead, my goal is to show you as many uses of JSTL as you could possibly want to see. My hope is that these “stretches” will serve as a good reference as your knowledge of JSTL progresses. You just might find that JSTL can handle more than you’d expect! 1 Duane Fields, Mark Kolb, and Shawn Bayern, 2nd ed. (Manning Publications, 2001). www.it-ebooks.info