JETZT ONLINE BESTELLEN
Add to Cart
JavaServer Pages

Third Edition Dezember 2003
ISBN 978-0-596-00563-4
764 Seiten
EUR37.00

Weitere Informationen zu diesem Buch

Inhaltsverzeichnis | Kolophon |


Inhaltsverzeichnis

	
Chapter 1: Introducing JavaServer Pages
Inhaltsvorschau
The Java 2 Enterprise Edition (J2EE) has taken the once-chaotic task of building an Internet presence and transformed it to the point where developers can use Java to efficiently create multitier, server-side applications. Today, the Java Enterprise APIs have expanded to encompass a number of areas: RMI and CORBA for remote object handling, JDBC for database interaction, JNDI for accessing naming and directory services, Enterprise JavaBeans for creating reusable business components, Java Messaging Service (JMS) for message-oriented middleware, JAXP for XML processing, JAXR, JAX-RPC and SAAJ for web services, Java Transaction API (JTA) for performing atomic transactions, and much more. In addition, J2EE also supports servlets, an extremely popular Java substitute for CGI scripts. The combination of these technologies allows programmers to create distributed business solutions for a variety of tasks.
In late 1999, Sun Microsystems added a new element to the collection of Enterprise Java tools: JavaServer Pages (JSP). JavaServer Pages are built on top of Java servlets and designed to increase the efficiency in which programmers, and even nonprogrammers, can create web content. This book is primarily about JavaServer Pages, covering the latest version of this technology, JSP 2.0, as well as the related JSP Standard Tag Library (JSTL) Version 1.1. It also covers other J2EE technologies, such as servlets and JDBC, with focus on how to combine them with JSP in the most efficient way.
Put succinctly, JavaServer Pages is a technology for developing web pages that include dynamic content. Unlike a plain HTML page, which contains static content that always remains the same, a JSP page can change its content based on any number of variable items, including the identity of the user, the user's browser type, information provided by the user, and selections made by the user. As you'll see later in the book, this functionality is key to web applications such as online shopping and employee directories, as well as for personalized and internationalized content.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
What Is JavaServer Pages?
Inhaltsvorschau
Put succinctly, JavaServer Pages is a technology for developing web pages that include dynamic content. Unlike a plain HTML page, which contains static content that always remains the same, a JSP page can change its content based on any number of variable items, including the identity of the user, the user's browser type, information provided by the user, and selections made by the user. As you'll see later in the book, this functionality is key to web applications such as online shopping and employee directories, as well as for personalized and internationalized content.
A JSP page contains standard markup language elements, such as HTML tags, just like a regular web page. However, a JSP page also contains special JSP elements that allow the server to insert dynamic content in the page. JSP elements can be used for a variety of purposes, such as retrieving information from a database or registering user preferences. When a user asks for a JSP page, the server executes the JSP elements, merges the results with the static parts of the page, and sends the dynamically composed page back to the browser, as illustrated in Figure 1-1.
Figure 1-1: Generating dynamic content with JSP elements
JSP defines a number of standard elements that are useful for any web application, such as accessing JavaBeans components, passing control between pages and sharing information between requests, pages, and users. Developers can also extend the JSP syntax by implementing application-specific elements that perform tasks such as accessing databases and Enterprise JavaBeans, sending email, and generating HTML to present application-specific data. One such set of commonly needed custom elements is defined by a specification related to the JSP specification: the JSP Standard Tag Library (JSTL) specification. The combination of standard elements and custom elements allows for the creation of powerful web applications.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Why Use JSP?
Inhaltsvorschau
In the early days of the Web, the Common Gateway Interface (CGI) was the only tool for developing dynamic web content. However, CGI is not an efficient solution. For every request that comes in, the web server has to create a new operating-system process, load an interpreter and a script, execute the script, and then tear it all down again. This is very taxing for the server and doesn't scale well when the amount of traffic increases.
Numerous CGI alternatives and enhancements, such as FastCGI, mod_perl from Apache, NSAPI from Netscape, ISAPI from Microsoft, and Java servlets from Sun Microsystems, have been created over the years. While these solutions offer better performance and scalability, all these technologies suffer from a common problem: they generate web pages by embedding HTML directly in programming language code. This pushes the creation of dynamic web pages exclusively into the realm of programmers. JavaServer Pages, however, changes all that.
JSP tackles the problem from the other direction. Instead of embedding HTML in programming code, JSP lets you embed special active elements into HTML pages. These elements look similar to HTML elements, but behind the scenes they are actually componentized Java programs that the server executes when a user requests the page. Here's a simple JSP page that illustrates this:

                  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <body bgcolor="white">

  

  <jsp:useBean id="clock" class="java.util.Date" />

                  <c:choose>

                  <c:when test="${clock.hours < 12}">

      <h1>Good morning!</h1>

    </c:when>

                  <c:when test="${clock.hours < 18}">

      <h1>Good day!</h1>

    </c:when>

                  <c:otherwise>

      <h1>Good evening!</h1>

    </c:otherwise>

                  </c:choose>

  Welcome to our site, open 24 hours a day.

  </body>

</html>
This page inserts a different message to the user based on the time of day: "Good morning!" if the local time is before 12 P.M., "Good day!" if between 12 P.M. and 6 P.M., and "Good evening!" otherwise. When a user asks for this page, the JSP-enabled web server executes the logic represented by the highlighted JSP elements and creates an HTML page that is sent back to the user's browser. For example, if the current time is 8:53 P.M., the resulting page sent from the server to the browser looks like this:
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
What You Need to Get Started
Inhaltsvorschau
Before we begin, let's quickly run through what you need to run the examples and develop your own applications. You really only need three things:
  • A PC or workstation, with a connection to the Internet so you can download the software you need
  • A Java 2 compatible-Java Software Development Kit (Java 2 SDK)
  • A JSP 2.0-enabled web server, such as Apache Tomcat from the Jakarta Project
The Apache Tomcat server is the reference implementation for JSP. All the examples in the book were tested on Tomcat. In Chapter 4, I'll show you how to download, install, and configure the Tomcat server as well as the examples described in this book.
In addition, there are a variety of other tools and servers that support JSP, from both open source projects and commercial companies. Close to 30 different server products support JSP to date, and roughly 10 IDEs and authoring tools with varying degrees of JSP support are listed on Sun's JSP web site (http://java.sun.com/products/jsp/). You may want to evaluate some of these products when you're ready to start developing your application, but all you really need to work with the examples in this book is a regular text editor, such as Notepad, vi, or Emacs, and of course the Tomcat server.
So let's get going and take a closer look at what JSP has to offer. You'll need a solid ground to stand on though, so in the next chapter we will start with the foundations on which JSP is built: HTTP and Java servlets.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 2: HTTP and Servlet Basics
Inhaltsvorschau
Let's start off this chapter by defining the term web application. We've all seen regular client-side applications, but what exactly is a web application? Loosely, it can be defined as an application running on a server a user accesses through a thin, general-purpose client. Today, the most common client is a web browser on a PC or workstation, but other kinds of clients are rapidly joining the party, such as wireless PDAs, cell phones, and other specialized devices.
The lofty goal here is to access all the information and services you need from any type of device that happens to be in front of you. This means that the same simple client program must be able to talk to many different server applications, and the applications must be able to work with many different types of clients. To satisfy this need, the protocol of how a client and a server talk to each other must be defined in detail. That's exactly what the HyperText Transport Protocol (HTTP) is for.
The communication model defined by HTTP forms the foundation for all web application design. A basic understanding of HTTP is key to developing applications that fit within the constraints of the protocol, no matter which server-side technology you use. In this chapter, we look at the most important details of HTTP you need to be aware of as a web application developer.
One other item: this book is about using JSP as the server-side technology, so that's what we'll focus on. As you saw in Chapter 1, JSP is based on the Java servlet technology. Both technologies share a lot of terminology and concepts, so knowing a bit about servlets will help you even when you develop pure JSP applications. To really understand and use the full power of JSP, you need to know a fair bit about servlets. Hence, we look at servlet fundamentals in the last section of this chapter.
HTTP and all extended protocols based on HTTP are based on a very simple communications model. Here's how it works: a client, typically a web browser, sends a
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
The HTTP Request/Response Model
Inhaltsvorschau
HTTP and all extended protocols based on HTTP are based on a very simple communications model. Here's how it works: a client, typically a web browser, sends a request for a resource to a server, and the server sends back a response corresponding to the resource (or a response with an error message if it can't process the request for some reason). A resource can be a number of things, such as a simple HTML file returned verbatim to the browser or a program that generates the response dynamically. This request/response model is illustrated in Figure 2-1.
Figure 2-1: HTTP request/response with two resources
This simple model implies three important facts you need to be aware of:
  • HTTP is a stateless protocol. This means that the server doesn't keep any information about the client after it sends its response, and therefore it can't recognize that multiple requests from the same client may be related.
  • Web applications can't easily provide the kind of immediate feedback typically found in standalone GUI applications such as word processors or traditional client/server applications. Every interaction between the client and the server requires a request/response exchange. Performing a request/response exchange when a user selects an item in a list box or fills out a form element is usually too taxing on the bandwidth available to most Internet users.
  • There's nothing in the protocol that tells the server how a request is made; consequently, the server can't distinguish between various methods of triggering the request on the client. For example, HTTP doesn't allow a web server to differentiate between an explicit request caused by clicking a link or submitting a form and an implicit request caused by resizing the browser window or using the browser's
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Servlets
Inhaltsvorschau
The JSP specification is based on the Java servlet specification. In fact, JSP pages are often combined with servlets in the same application. In this section, we take a brief look at what a servlet is, and then discuss the concepts shared by servlets and JSP pages. In Chapter 3, we'll take a closer look at how JSP pages are actually turned into servlets automatically.
If you're already familiar with servlets, this is old news. You can safely skip the rest of this chapter.
In simple terms, a servlet is a piece of code that adds new functionality to a server (typically a web server), just like CGI and proprietary server extensions such as NSAPI and ISAPI. But compared to other technologies, servlets have a number of advantages:
Platform and vendor independence
All the major web servers and application servers support servlets, so a servlet-based solution doesn't tie you to one specific vendor. Also, servlets are written in the Java programming language, so they can be used on any operating system with a Java runtime environment.
Integration
Servlets are developed in Java and can therefore take advantage of all other Java technologies, such as JDBC for database access, JNDI for directory access, RMI for remote resource access, etc. Starting with Version 2.2, the servlet specification is part of the Java 2 Enterprise Edition (J2EE), making servlets an important ingredient of any large-scale enterprise application, with formalized relationships to other server-side technologies such as Enterprise JavaBeans.
Efficiency
Servlets execute in a process that is running until the servlet-based application is shut down. Each servlet request is executed as a separate thread in this permanent process. This is far more efficient that the CGI model, where a new process is created for each request. First of all (and most obvious), a servlet doesn't have the overhead of creating the process and loading the CGI script and possibly its interpreter. But another timesaver is that servlets can also access resources that remain loaded in the process memory between requests, such as database connections and persistent state.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 3: JSP Overview
Inhaltsvorschau
JSP is the latest Java technology for web application development and is based on the servlet technology introduced in the previous chapter. While servlets are great in many ways, they are generally reserved for programmers. In this chapter, we look at the problems that JSP technology solves, the anatomy of a JSP page, the relationship between servlets and JSP, and how the server processes a JSP page.
In any web application, a program on the server processes requests and generates responses. In a simple one-page application, such as an online bulletin board, you don't need to be overly concerned about the design of this piece of code; all logic can be lumped together in a single program. However, when the application grows into something bigger (spanning multiple pages, using external resources such as databases, with more options and support for more types of clients), it's a different story. The way your site is designed is critical to how well it can be adapted to new requirements and continue to evolve. The good news is that JSP technology can be used as an important part in all kinds of web applications, from the simplest to the most complex. Therefore, this chapter also introduces the primary concepts in the design model recommended for web applications and the different roles played by JSP and other Java technologies in this model.
In many Java servlet-based applications, processing the request and generating the response are both handled by a single servlet class. Example 3-1 shows how a servlet class often looks.
Example 3-1. A typical servlet class
public class OrderServlet extends HttpServlet {

    public void doGet((HttpServletRequest request, 

        HttpServletResponse response)

        throws ServletException, IOException  {

  

        response.setContentType("text/html");

        PrintWriter out = response.getWriter(  );

        

        if (isOrderInfoValid(request)) {

            saveOrderInfo(request);

            out.println("<html>");

            out.println("  <head>");

            out.println("    <title>Order Confirmation</title>");

            out.println("  </head>");

            out.println("  <body>");

            out.println("    <h1>Order Confirmation</h1>");

            renderOrderInfo(request);

            out.println("  </body>");

            out.println("</html>");

       }

 ...
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
The Problem with Servlets
Inhaltsvorschau
In many Java servlet-based applications, processing the request and generating the response are both handled by a single servlet class. Example 3-1 shows how a servlet class often looks.
Example 3-1. A typical servlet class
public class OrderServlet extends HttpServlet {

    public void doGet((HttpServletRequest request, 

        HttpServletResponse response)

        throws ServletException, IOException  {

  

        response.setContentType("text/html");

        PrintWriter out = response.getWriter(  );

        

        if (isOrderInfoValid(request)) {

            saveOrderInfo(request);

            out.println("<html>");

            out.println("  <head>");

            out.println("    <title>Order Confirmation</title>");

            out.println("  </head>");

            out.println("  <body>");

            out.println("    <h1>Order Confirmation</h1>");

            renderOrderInfo(request);

            out.println("  </body>");

            out.println("</html>");

       }

 ...
If you're not a programmer, don't worry about all the details in this code. The point is that the servlet contains request processing and business logic (implemented by methods such as isOrderInfoValid() and saveOrderInfo( )), and also generates the response HTML code, embedded directly in the servlet code using println( ) calls. A more structured servlet application isolates different pieces of the processing in various reusable utility classes and may also use a separate class library for generating the actual HTML elements in the response. Even so, the pure servlet-based approach still has a few problems:
  • Thorough Java programming knowledge is needed to develop and maintain all aspects of the application, since the processing code and the HTML elements are lumped together.
  • Changing the look and feel of the application, or adding support for a new type of client (such as a WML client), requires the servlet code to be updated and recompiled.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
The Anatomy of a JSP Page
Inhaltsvorschau
A JSP page is simply a regular web page with JSP elements for generating the parts that differ for each request, as shown in Figure 3-2.
Figure 3-2: Template text and JSP elements
Everything in the page that isn't a JSP element is called template text. Template text can be any text: HTML, WML, XML, or even plain text. Since HTML is by far the most common web page language in use today, most of the descriptions and examples in this book use HTML, but keep in mind that JSP has no dependency on HTML; it can be used with any markup language. Template text is always passed straight through to the browser.
When a JSP page request is processed, the template text and dynamic content generated by the JSP elements are merged, and the result is sent as the response to the browser.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
JSP Processing
Inhaltsvorschau
Just as a web server needs a servlet container to provide an interface to servlets, the server needs a JSP container to process JSP pages. The JSP container is responsible for intercepting requests for JSP pages. To process all JSP elements in the page, the container first turns the JSP page into a servlet (known as the JSP page implementation class). The conversion is pretty straightforward; all template text is converted to println( ) statements similar to the ones in the handcoded servlet shown in Example 3-1, and all JSP elements are converted to Java code that implements the corresponding dynamic behavior. The container then compiles the servlet class.
Converting the JSP page to a servlet and compiling the servlet form the translation phase. The JSP container initiates the translation phase for a page automatically when it receives the first request for the page. Since the translation phase takes a bit of time, the first user to request a JSP page notices a slight delay. The translation phase can also be initiated explicitly; this is referred to as precompilation of a JSP page. Precompiling a JSP page is a way to avoid hitting the first user with this delay. It is discussed in more detail in Chapter 17.
The JSP container is also responsible for invoking the JSP page implementation class (the generated servlet) to process each request and generate the response. This is called the request processing phase. The two phases are illustrated in Figure 3-3.
Figure 3-3: JSP page translation and processing phases
As long as the JSP page remains unchanged, any subsequent request goes straight to the request processing phase (i.e., the container simply executes the class file). When the JSP page is modified, it goes through the translation phase again before entering the request processing phase.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
JSP Application Design with MVC
Inhaltsvorschau
JSP technology can play a part in everything from the simplest web application, such as an online phone list or an employee vacation planner, to complex enterprise applications, such as a human resource application or a sophisticated online shopping site. How large a part JSP plays differs in each case, of course. In this section, I introduce a design model called Model-View-Controller (MVC), suitable for both simple and complex applications.
MVC was first described by Xerox in a number of papers published in the late 1980s. The key point of using MVC is to separate logic into three distinct units: the Model, the View, and the Controller. In a server application, we commonly classify the parts of the application as business logic, presentation, and request processing. Business logic is the term used for the manipulation of an application's data, such as customer, product, and order information. Presentation refers to how the application data is displayed to the user, for example, position, font, and size. And finally, request processing is what ties the business logic and presentation parts together. In MVC terms, the Model corresponds to business logic and data, the View to the presentation, and the Controller to the request processing.
Why use this design with JSP? The answer lies primarily in the first two elements. Remember that an application data structure and logic (the Model) is typically the most stable part of an application, while the presentation of that data (the View) changes fairly often. Just look at all the face-lifts many web sites go through to keep up with the latest fashion in web design. Yet, the data they present remains the same. Another common example of why presentation should be separated from the business logic is that you may want to present the data in different languages or present different subsets of the data to internal and external users. Access to the data through new types of devices, such as cell phones and personal digital assistants (PDAs), is the latest trend. Each client type requires its own presentation format. It should come as no surprise, then, that separating business logic from the presentation makes it easier to evolve an application as the requirements change; new presentation interfaces can be developed without touching the business logic.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 4: Setting Up the JSP Environment
Inhaltsvorschau
This book contains plenty of examples to illustrate all the JSP features. All examples were developed and tested with the JSP reference implementation, known as the Apache Tomcat server, which is developed by the Apache Jakarta project. In this chapter you will learn how to install the Tomcat server and add a web application containing all the examples used in this book. You can, of course, use any web server that supports JSP 2.0, but Tomcat is a good server for development and test purposes. You can learn more about the Jakarta project and Tomcat, as well as how you can participate in the development, at the Jakarta web site: http://jakarta.apache.org/.
Tomcat 5 is a pure Java web server with support for the Servlet 2.4 and JSP 2.0 specifications. In order to use it, you must first install a Java runtime environment. If you don't already have one, you can download a Java runtime for Windows, Linux, and Solaris at http://java.sun.com/j2se/.
I recommend that you download and install the Java 2 SDK (a.k.a. JDK), as opposed to the slimmed-down Runtime Environment (JRE) distribution. The reason is that JSP requires a Java compiler, included in the SDK but not in the JRE.
Another alternative is to use the JRE plus the Jikes compiler from IBM (http://www10.software.ibm.com/developerworks/opensource/jikes/). Tomcat can be configured to use Jikes instead of the javac compiler available in the Java 2 SDK from Sun; read the Tomcat documentation if you would like to try this. To make things simple, though, I suggest installing the Java 2 SDK from Sun. The examples were developed and tested with Java 2 SDK, Standard Edition, v1.4.2. I suggest that you use the latest version of the SDK available for your platform.
If you need an SDK for a platform other than Windows, Linux, or Solaris, there's a partial list of ports made by other companies at: http://java.sun.com/cgi-bin/java-ports.cgi.
Also check your operating-system vendor's web site. Most operating-system vendors have their own SDK implementation available for free.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Installing the Java Software Development Kit
Inhaltsvorschau
Tomcat 5 is a pure Java web server with support for the Servlet 2.4 and JSP 2.0 specifications. In order to use it, you must first install a Java runtime environment. If you don't already have one, you can download a Java runtime for Windows, Linux, and Solaris at http://java.sun.com/j2se/.
I recommend that you download and install the Java 2 SDK (a.k.a. JDK), as opposed to the slimmed-down Runtime Environment (JRE) distribution. The reason is that JSP requires a Java compiler, included in the SDK but not in the JRE.
Another alternative is to use the JRE plus the Jikes compiler from IBM (http://www10.software.ibm.com/developerworks/opensource/jikes/). Tomcat can be configured to use Jikes instead of the javac compiler available in the Java 2 SDK from Sun; read the Tomcat documentation if you would like to try this. To make things simple, though, I suggest installing the Java 2 SDK from Sun. The examples were developed and tested with Java 2 SDK, Standard Edition, v1.4.2. I suggest that you use the latest version of the SDK available for your platform.
If you need an SDK for a platform other than Windows, Linux, or Solaris, there's a partial list of ports made by other companies at: http://java.sun.com/cgi-bin/java-ports.cgi.
Also check your operating-system vendor's web site. Most operating-system vendors have their own SDK implementation available for free.
Installation of the SDK varies per platform but is typically easy to do. Just follow the instructions on the web site where you download the SDK.
Before you install and run Tomcat, make sure that the JAVA_HOME environment variable is set to the installation directory of your Java environment and that the Java bin directory is included in the PATH environment variable. On a Windows system, you can see if an environment variable is set by typing the following command in a Command Prompt window:
C:\> echo %JAVA_HOME%

C:\jdk1.4.2
If JAVA_HOME isn't set, you can set it and include the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Installing the Tomcat Server
Inhaltsvorschau
Tomcat supports many features and configuration options. In this section, I only describe the basics that you must know to get Tomcat up and running. If you plan to use Tomcat extensively for development or as a production server, refer to Tomcat: The Definitive Guide by Jason Brittain and Ian Darwin (O'Reilly).
You can download the Tomcat server in binary format or as source code that you compile yourself. If you're primarily interested in learning about JSP, I recommend that you use the binary download for running the examples in this book and to develop your own applications. If you're a Java programmer and are interested in seeing how Tomcat is implemented, feel free to download the source as well and take a look at the internals.
The binary distribution is available at http://jakarta.apache.org/site/binindex.cgi.
On this page you find three types of builds: release builds, milestone builds, and nightly builds. Release builds are stable releases that have been tested extensively and verified to comply with the servlet and JSP specifications. Milestone builds are created as intermediary steps towards a release build. They often contain new features that aren't yet fully tested but are generally known to work. A nightly build, however, may be very unstable. It's actually a snapshot of the latest source code and may have been tested only by the person who made the latest change. You should use a nightly build only if you're involved in the development of Tomcat.
I recommend that you download the latest release build. All examples in this book were developed and tested using the 5.0.12 version, but any release later than 5.0.12 should work fine as well. When you click on the link for the latest release build and select the bin directory, you see a list of archive files in different formats, similar to Figure 4-1.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Testing Tomcat
Inhaltsvorschau
The Tomcat installation directory contains a number of subdirectories. All of them are described in the README.txt file, but the most important ones are:
bin
Scripts for starting and stopping the Tomcat server.
conf
Tomcat configuration files.
webapps
Default l ocation for web applications served by Tomcat.
Two more subdirectories under the Tomcat home directory are created the first time you start the server:
logs
Server log files. If something doesn't work as expected, look in the files in this directory for clues as to what's wrong.
work
A directory for temporary files created by the JSP container and other files. This directory is where the servlets generated from JSP pages are stored.
To test the server, run the startup script as described in the platform-specific sections, and (assuming you're running Tomcat on the same machine as the browser and that you're using the default 8080 port for Tomcat) open a browser and enter this URL in the Location/Address field: http://localhost:8080/.
The Tomcat main page is shown in the browser, as in Figure 4-2, and you can now run all servlet and JSP examples bundled with Tomcat to ensure everything works.
Figure 4-2: The Tomcat main page
If you're trying this on a machine that sits behind a proxy, for instance on a corporate network, and instead of Tomcat's main page you see an error message about not being able to connect to
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Installing the Book Examples
Inhaltsvorschau
All JSP pages, HTML pages, Java source code, and class files for the examples can be downloaded from the O'Reilly site http://www.oreilly.com/catalog/jserverpages3/.
They can also be downloaded from the book web site that I maintain: http://www.TheJSPBook.com/.
On this site you find a Download page where you can download the file, called jspbook3.zip. Save the file on your hard drive, for instance in C:\JSPBook on a Windows platform, and unpack it:
C:\JSPBook> jar xvf jspbook3.zip

            
You can use the same command on a Unix platform.
Two new directories are created: ora and src. The first directory contains all examples described in this book, and the second contains the Java source files for the JavaBeans, custom actions, servlets, and utility classes used in the examples.
The examples directory structure complies with the standard Java web application format described in Chapter 2. You can therefore configure any JSP 2.0-compliant web container to run the examples.
If you like to use a container other than Tomcat, be sure to read the documentation for that container for instructions on how to install a web application.
To install the example application for Tomcat, simply copy the web application directory structure (the ora directory) to Tomcat's default directory for applications, called webapps. On a Windows platform, you can copy/paste the directory structure with the Windows Explorer tool, or use this command in a Command Prompt window:
C:\JSPBook> xcopy /s /i ora %CATALINA_HOME%\webapps\ora

            
On a Unix platform it looks like this:
[hans@gefion jspbook] cp -R ora $CATALINA_HOME/webapps

            
Recall from Chapter 2 that each web application in a server is associated with a unique URI prefix (the context path). When you install an application in Tomcat's webapps directory, the subdirectory name is assigned automatically as the URI prefix for the application (that is,
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Example Web Application Overview
Inhaltsvorschau
The examples for this book are packaged as a standard Java web application, as described in Chapter 2. All servers compliant with the JSP 2.0 specification support this file structure, so you can use the example application as a guideline when you create your own web applications. How a web application is installed isn't defined by the specification, however, so it varies between servers. With Tomcat, you simply copy the file structure to the special webapps directory and restart the server. To modify the configuration information for an application, you need to edit the application's WEB-INF/web.xml file using a text editor. Other servers may offer special deployment tools that copy the files where they belong and let you configure the application using a special tool or through web-based forms.
If you look in the ora web application directory, you see that it contains an index.html file and a number of directories corresponding to chapters in this book. These directories contain all the example JSP and HTML pages.
There's also a WEB-INF directory with a web.xml file, a lib directory, and a classes directory. We will look at this in much more detail later, starting in Chapter 5, but here's a quick review:
  • The web.xml file contains configuration information for the example application in the format defined by the servlet and JSP specifications. It's too early to look at the contents of this file now; we will return to parts of it when needed.
  • The lib and classes directories are standard directories, also defined by the servlet specification. A very common question asked by people new to servlets and JSP (prior to the standard web application format) was, "Where do I store my class files so that the server can find them?" The answer, unfortunately, differed depending on which implementation was used. With the standard web application format, it's easy to answer this question: if the classes are packaged in a JAR file, store the JAR file in the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 5: Generating Dynamic Content
Inhaltsvorschau
JSP is all about generating dynamic content: content that differs based on user input, time of day, the state of an external system, or any other runtime conditions. JSP provides you with lots of tools for generating this content. In this book, you will learn about them all—standard actions, custom actions, the JSP Standard Tag Library, JavaBeans, the Expression Language and scripting elements. Before going into all of that, however, let's start with a simple example to get a better feel for how the basic JSP elements work.
Recall from Chapter 3 that a JSP page is just a regular HTML page with a few special elements. A JSP page should have the file extension .jsp, which tells the server that the page needs to be processed by the JSP container. Without this clue, the server is unable to distinguish a JSP page from any other type of file and sends it unprocessed to the browser.
When working with JSP pages, you just need a regular text editor such as Notepad on Windows or Emacs on Unix. There are a number of tools that may make it easier for you, such as syntax-aware editors that color-code JSP and HTML elements. Some Interactive Development Environments (IDE) even include a small web container that allows you to easily execute and debug the pages during development. There are also several webpage authoring tools—the type of tools often used when developing regular HTML pages—that support JSP to some degree. You can browse through a fairly extensive list of tools like this at my web site: http://www.TheJSPBook.com/. I recommend that you do not use them initially, though; it's easier to learn how JSP works if you see the raw page elements before you use tools that hide them.
The first example JSP page, named easy.jsp, is shown in Example 5-1.
Example 5-1. JSP page showing a dynamically calculated sum (easy.jsp)

                  <%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Creating a JSP Page
Inhaltsvorschau
Recall from Chapter 3 that a JSP page is just a regular HTML page with a few special elements. A JSP page should have the file extension .jsp, which tells the server that the page needs to be processed by the JSP container. Without this clue, the server is unable to distinguish a JSP page from any other type of file and sends it unprocessed to the browser.
When working with JSP pages, you just need a regular text editor such as Notepad on Windows or Emacs on Unix. There are a number of tools that may make it easier for you, such as syntax-aware editors that color-code JSP and HTML elements. Some Interactive Development Environments (IDE) even include a small web container that allows you to easily execute and debug the pages during development. There are also several webpage authoring tools—the type of tools often used when developing regular HTML pages—that support JSP to some degree. You can browse through a fairly extensive list of tools like this at my web site: http://www.TheJSPBook.com/. I recommend that you do not use them initially, though; it's easier to learn how JSP works if you see the raw page elements before you use tools that hide them.
The first example JSP page, named easy.jsp, is shown in Example 5-1.
Example 5-1. JSP page showing a dynamically calculated sum (easy.jsp)

                  <%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

    <title>JSP is Easy</title>

  </head>

  <body bgcolor="white">

  

    <h1>JSP is as easy as ...</h1>

  

    <%-- Calculate the sum of 1 + 2 + 3 dynamically --%>

    1 + 2 + 3 = <c:out value="${1 + 2 + 3}" />

  

  </body>

</html>
The easy.jsp page displays static HTML plus the sum of 1, 2, and 3, calculated at runtime and dynamically added to the response. We'll look at all the different pieces soon, but first you may want to run the example to see how it works.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Installing a JSP Page
Inhaltsvorschau
A complete web application may consist of several different resources: JSP pages, servlets, applets, static HTML pages, custom tag libraries, and other Java class files. Until very recently, an application with all these components had to be installed and configured in different ways for different servers, making it hard for web application developers to provide easy-to-use installation instructions and tools.
Starting with the Servlet 2.2 specification, there's a standard, portable way to package all web application resources, along with a deployment descriptor. The deployment descriptor is a file named web.xml, containing information about security requirements, how all the resources fit together, and other facts about the application. The deployment descriptor and all the other web application files are placed in a Web Application Archive (WAR) file, arranged in a well-defined hierarchy. A WAR file has a .war file extension and can be created with the Java jar command or a ZIP utility program, such as WinZip (the same file format is used for both JAR and ZIP files).
Having a standardized web application format lets container vendors develop installation and configuration tools that make it easy to install an application. During installation, the container is free to unpack the contents of the WAR file and store it for runtime use in any way it sees fit, but the application developer needs to deal with only one delivery format.
Even though a container is required to know how to deal only with applications packaged as a WAR file, most (if not all) containers also let you store your application files directly in a filesystem using the same file structure as is defined for the WAR file. During development, it's more convenient to work with the files in a regular filesystem structure instead of creating an updated WAR file every time you make a change. In Tomcat, for instance, any subdirectory under the webapps directory is assumed to be a web application, using the standard web application file structure.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Running a JSP Page
Inhaltsvorschau
Assuming you have installed all book examples as described in Chapter 4, first start the Tomcat server and load the book examples main page by typing the URL http://localhost:8080/ora/index.html in the browser address field. Note how the /ora part of the URL matches the Tomcat webapps subdirectory name for the example application. This part of the URL is called the application's context path; every web application has a unique context path, assigned one way or another when you install the application. Tomcat uses the subdirectory name as the context path by default, but other containers may prompt you for a path in an installation tool or use other conventions. When you make a request for a web application resource (an HTML or JSP page, or a servlet), the first part of the URL (after the hostname and port number) must be the context path, so the container knows which application should handle the request.
There's one exception to this rule; one application per container may be installed as the default, or root, application. For Tomcat, this application is stored in the webapps/ROOT directory, by default. Requests for resources in the default application don't start with a context path (or more accurately, have an empty string as their context path). For instance, the http://localhost:8080/index.html URL is used to request a page in the default application.
You can run Example 5-1 by clicking the "JSP is Easy" link from the book examples main page, shown in Figure 5-1. You should see a result like the one shown in Figure 5-2.
Figure 5-1: JSP book examples main page
Figure 5-2: The "JSP is Easy" example output
The page shown in Example 5-1 contains both regular HTML elements and JSP elements. If you use the View Source function in your browser, you notice that none of the JSP elements are visible in the page source. That's because the server processes the JSP elements when the page is requested, and only the resulting output is sent to the browser. The HTML elements, on the other hand, are sent to the browser as is, defining the layout of the page. To see the unprocessed JSP page in a separate window, you can click on the source link for the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using JSP Directive Elements
Inhaltsvorschau
Let's look at each piece of Example 5-1 in detail. The first two lines are JSP directive elements. Directive elements specify attributes of the page itself, such as the type of content produced by the page, page-buffering requirements, declaration of other resources used by the page, and how possible runtime errors should be handled. Hence, a directive doesn't directly affect the content of the response sent to the browser, but it tells the container how it should handle the page. There are three different directives that you can use in a JSP page: page, include, and taglib. In this chapter, we're using the page and the taglib directives. The include directive is described in Chapter 17.
JSP pages typically starts with a page directive that specifies the content type for the page:
<%@ page contentType="text/html" %>
A JSP directive element starts with a directive-start identifier (<%@ ), followed by the directive name (page in this case), directive attributes, and ends with %>. A directive contains one or more attribute name/value pairs (e.g., contentType="text/html"). Note that JSP element and attribute names are case-sensitive, and in most cases, the same is true for attribute values. All attribute values must also be enclosed in single or double quotes.
The page directive has many possible attributes. In Example 5-1, only the contentType attribute is used. It specifies the MIME-type for the content the page produces. The most common values are text/html for HTML content and text/plain for preformatted, plain text. But you can also specify other types, such as text/xml for browsers that support XML or text/vnd.wap.wml for devices such as cell phones and PDAs that have built-in WML browsers. The container sends the content type information to the browser as a response header called Content-Type, so the browser knows how to interpret and render the response body. If you omit the contentType attribute, the container sets the header to
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Template Text
Inhaltsvorschau
Besides JSP elements, notice that the easy.jsp page contains mostly regular HTML, highlighted in Example 5-2.
Example 5-2. JSP page template text
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

    <title>JSP is Easy</title>

  </head>

  <body bgcolor="white">

    <h1>JSP is as easy as ...</h1>

    <%-- Calculate the sum of 1 + 2 + 3 dynamically --%>

    1 + 2 + 3 = <c:out value="${1 + 2 + 3}" />

  </body>

</html>

               
In JSP parlance, this is called template text. Everything that's not a JSP element (i.e., not a directive, action or scripting element) is template text. Template text is sent to the browser as is. This means you can use JSP to generate any type of text-based output, such as XML, WML, or even plain text. The JSP container doesn't care what the template text represents.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using JSP Action Elements
Inhaltsvorschau
Besides the fixed template text, the easy.jsp page also produces dynamic content. It has very simple dynamic content—the sum of 1, 2 and 3 calculated at runtime—but step back a moment and think about the type of dynamic content you see on the Web every day. Common examples might be a list of web sites matching a search criterion on a search engine site, the content of a shopping cart on an e-commerce site, a personalized news page, or messages in a bulletin board. The actual data for the dynamic content can come from many types of sources, for instance from a database, an XML document, or data accumulated in memory based on previous requests. The dynamic data needs to be combined with regular HTML elements into a page with the right layout, navigation bars, the company logo, and so forth, before it's sent to the browser. When using JSP, the regular HTML is the template text described earlier, and the dynamic data is inserted at the appropriate place in the template text using a JSP action element.
A JSP action is executed when a JSP page is requested (this is called the request processing phase, as you may recall from Chapter 3). In other words, JSP action elements represent dynamic actions that take place at runtime, as opposed to JSP directives that are used only during the translation phase (when the JSP page is turned into Java servlet code). An action can add text to the response, as in the example used in this chapter, but it can also do other things such as write to a file on the server, send an email, or retrieve data from a database that is later added to the response by other actions. Example 5-3 shows the easy.jsp page again, this time with the JSP action element highlighted.
Example 5-3. JSP action elements
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

    <title>JSP is Easy</title>

  </head>

  <body bgcolor="white">

  

    <h1>JSP is as easy as ...</h1>

  

    <%-- Calculate the sum of 1 + 2 + 3 dynamically --%>

    1 + 2 + 3 = 
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 6: Using JavaBeans Components in JSP Pages
Inhaltsvorschau
The JavaBeans specification defines a set of programming conventions for Java classes that are used as pluggable components. In layman's terms, tools that have no inside information about a class can use it if it's developed according to these conventions. For instance, a generic GUI builder tool can support any widgets developed as JavaBeans components. A JavaBeans component, or just a bean for short, is often used in JSP as the container for the dynamic content to be displayed by a web page. It typically represents something specific, such as a person, a product, or a shopping order. When JSP is combined with servlets, the bean can be created and initialized with data by the servlet and passed to a JSP page that simply adds the bean's data to the response. But even in a pure JSP application, a bean is a useful tool, for instance for capturing and validating user input.
A programmer must develop the bean, but someone who doesn't have any programming experience can then use it in a JSP page. JSP defines a number of standard actions for working with beans, and the JSP Expression Language accepts beans as variables in expressions. In this chapter, we take a closer look at what a bean is and how it can produce dynamic content in a page. We'll return to beans in Chapter 8 to see how they can be used for input validation.
As I said earlier, a bean is simply a Java class that follows certain coding conventions, so it can be used by tools as a component in a larger application. It can be instantiated and made available to the JSP page in a couple of ways. In an application that uses a servlet as a frontend for all business logic, the bean is typically created by the business logic code and sent to the JSP page to include its contents in the response. I describe this approach in detail in Chapter 19 and Chapter 20. The bean can also be created directly by a JSP page. This is the approach used in this chapter.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
What Is a Bean?
Inhaltsvorschau
As I said earlier, a bean is simply a Java class that follows certain coding conventions, so it can be used by tools as a component in a larger application. It can be instantiated and made available to the JSP page in a couple of ways. In an application that uses a servlet as a frontend for all business logic, the bean is typically created by the business logic code and sent to the JSP page to include its contents in the response. I describe this approach in detail in Chapter 19 and Chapter 20. The bean can also be created directly by a JSP page. This is the approach used in this chapter.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Declaring a Bean in a JSP Page
Inhaltsvorschau
Example 6-1 shows a JSP page that uses the bean described in Table 6-1 to display a cartoon strip.
Example 6-1. A page using a bean (cartoon.jsp)
<html>

  <head>

    <title>A dose of Dilbert</title>

  </head>

  <body bgcolor="white">

    <h1>A dose of Dilbert</h1>

  

    <jsp:useBean id="cartoon" 

      class="com.ora.jsp.beans.motd.CartoonBean" />

    <img src="images/<jsp:getProperty name="cartoon" 

      property="fileName" />">

  

  </body>

</html>
Before you use a bean in a page, you must tell the JSP container the type of bean it is and associate it with a name; in other words, you must declare the bean. The first JSP action in Example 6-1, <jsp:useBean>, is used for this purpose:
<jsp:useBean id="cartoon" class="com.ora.jsp.beans.motd.CartoonBean" />
The <jsp:useBean> action is one of the JSP standard actions (identified by the jsp prefix). The action creates an instance of the bean class specified by the class attribute and associates it with the name specified by the id attribute. The name must be unique in the page and be a valid Java variable name; it must start with a letter and can't contain special characters such as dots, plus signs, etc.
Other attributes you can specify for the <jsp:useBean> action are scope, type, and beanName. Chapter 10 explores how the scope attribute is used. The others are rarely used, but Appendix Acontains descriptions of how you can use them if you wish.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Reading Bean Properties
Inhaltsvorschau
A bean's data is represented by its properties. The CartoonBean used in Example 6-1 has only one property, named fileName, but other beans may have many different properties. The fileName property's value is the name of an image file that contains a cartoon. There are two ways to insert a bean property value in a JSP page. Let's look at them one at a time.
Once you have created a bean and given it a name using the <jsp:useBean> action, you can get the bean's property values with another JSP standard action, named <jsp:getProperty> . This action obtains the current value of a bean property and inserts it directly into the response body.
To include the current fileName property value in the page, simply use this tag:
<jsp:getProperty name="cartoon" property="fileName" />
The name attribute, set to cartoon, refers to the specific bean instance declared by the <jsp:useBean> action. The <jsp:getProperty> action locates this bean and asks it for the value of the property specified by the property attribute. In Example 6-1, the property value is used as the src attribute value for an HTML <img> element. The result is the page shown in Figure 6-1. The way this bean is implemented, the fileName property value changes every time you access the property; when you reload the page, a different cartoon strip is shown.
Figure 6-1: A JSP page with a dynamically inserted image file (Dilbert © UFS. Reprinted by Permission)
One thing in Example 6-1 may look a bit strange: an element (<jsp:getProperty>) is used as the value of another element's attribute (the <img> tag's src attribute). While this isn't valid HTML syntax, it is valid JSP syntax. Remember that everything that's not recognized as a JSP element is treated as template text. The container doesn't even try to interpret what the template text means, so it doesn't recognize it as invalid HTML. As far as the JSP container is concerned, the code in Example 6-1 is as valid as:
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Setting Bean Properties
Inhaltsvorschau
If a bean property is writable (write-only or read/write access), there are two actions you can use to set the value: <jsp:setProperty> or <c:set>.
One way to set a bean property value is using the standard action: <jsp:setProperty> . Table 6-2 shows a bean that is similar to the CartoonBean used in the previous example, but it also has a writable property named category.
Table 6-2: Properties for com.ora.jsp.beans.motd.MixedMessageBean
Property name
Java type
Access
Description
category
String
Write
The message category, either thoughts or quotes
message
String
Read
The current message in the selected category
Instead of image files, the MixedMessageBean has a property that contains a funny message (funny to me at least—I hope you agree). The bean maintains messages of different types, and the write-only category property is used to select the type you want. Example 6-3 shows how you can use this feature.
Example 6-3. A page setting a bean property (message.jsp)
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 7: Using Custom Tag Libraries and the JSP Standard Tag Library
Inhaltsvorschau
So far we've covered the JSP basics—the primary parts of a page and installation and execution of a page—and how to use beans to dynamically add content to a page. Before we start working on real applications, let's turn to another fundamental JSP feature: custom tag libraries.
Custom tag libraries are, in my opinion, what make JSP so powerful. They make it possible for page authors to embed pretty much any logic in a page using familiar, HTML-like elements. In this chapter, we take a close look at what a custom tag library is, how to install and use it, and what the JSP Standard Tag Library (JSTL) brings to the table.
The JSP standard actions, such as the <jsp:useBean> and <jsp:getProperty> actions used in Chapter 6, are HTML-like elements for commonly needed functions in a JSP page: creating beans, accessing bean properties, and invoking other JSP pages. But there's a lot more you want to do that isn't covered by the standard actions.
To extend the set of action elements a page author can use in the same familiar way, new actions can be developed, either by a programmer as Java classes or by a page author as tag files (a special kind of JSP file). In either case, these actions are called custom actions. A custom action can do pretty much anything: it has access to all information about the request, it can add content to the response body as well as set response headers, and it can use any Java API to access external resources such as databases, LDAP servers, or mail servers. The way the JSP container interacts with a custom action also makes it possible for a custom action to conditionally process its body and to abort the processing of the rest of the page. Custom actions can be created for application-specific functions to make it easier for page authors to develop the JSP pages. Some typical examples are shown later in this book.
A custom action is inserted into a page using an HTML-like (actually XML) element. The attribute values, and sometimes the body, you provide tell the action what to do and the data to use. In fact, you have already used a custom action; the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
What Is a Custom Tag Library?
Inhaltsvorschau
The JSP standard actions, such as the <jsp:useBean> and <jsp:getProperty> actions used in Chapter 6, are HTML-like elements for commonly needed functions in a JSP page: creating beans, accessing bean properties, and invoking other JSP pages. But there's a lot more you want to do that isn't covered by the standard actions.
To extend the set of action elements a page author can use in the same familiar way, new actions can be developed, either by a programmer as Java classes or by a page author as tag files (a special kind of JSP file). In either case, these actions are called custom actions. A custom action can do pretty much anything: it has access to all information about the request, it can add content to the response body as well as set response headers, and it can use any Java API to access external resources such as databases, LDAP servers, or mail servers. The way the JSP container interacts with a custom action also makes it possible for a custom action to conditionally process its body and to abort the processing of the rest of the page. Custom actions can be created for application-specific functions to make it easier for page authors to develop the JSP pages. Some typical examples are shown later in this book.
A custom action is inserted into a page using an HTML-like (actually XML) element. The attribute values, and sometimes the body, you provide tell the action what to do and the data to use. In fact, you have already used a custom action; the <c:out> action used in Chapter 5 and Chapter 6. It's part of the JSTL core library, and the JSTL libraries are implemented based on the same mechanisms as an application-specific custom tag library.
Behind the scenes, a custom action is implemented either as a Java class or as a tag file. The name of the class or the tag file and other information the container needs to invoke it are specified in a file called a Tag Library Descriptor (TLD). A custom
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Installing a Custom Tag Library
Inhaltsvorschau
Installing a custom tag library is very easy: just place the JAR file for the library in the WEB-INF/lib directory for the web application. If you look in the WEB-INF/lib directory for the book examples application, you see a JAR file named orataglib_3_0.jar; that's the custom tag library for all custom actions implemented as Java classes used in this book.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Declaring a Custom Tag Library
Inhaltsvorschau
As you know by now, a JSP page contains a mixture of JSP elements and template text, in which the template text can be HTML or XML elements. The JSP container needs to figure out which is which. It's easy for it to recognize the standard JSP elements (because they all use the jsp namespace prefix), but it needs some help to find the elements that represent custom actions. That's where the tag library declaration comes into play.
Example 7-1 shows a page that uses a custom action from a custom tag library.
Example 7-1. Custom tag library declaration (message.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="ora" uri="orataglib" %>

<html>

  <head>

    <title>Messages of the Day</title>

  </head>

  <body bgcolor="white">

    <h1>Messages of the Day</h1>

    <h2>Deep Thoughts - by Jack Handey</h2>

    <i>

      <ora:motd category="thoughts" />

    </i>

  

    <h2>Quotes From the Famous and the Unknown</h2>

    <i>

      <ora:motd category="quotes" />

    </i>

  </body>

</html>
This page displays messages from the same collections as the examples in Chapter 6. The second directive in Example 7-1 is a taglib directive, which is used to declare a custom tag library. Now, let's see what this really means. In order for the JSP container to use actions from a tag library, it must be able to do two things: recognize that an element represents a custom action from a specific library, and find the Java class or tag file that implements the custom action logic.
The first requirement—figuring out which library an action belongs to—is satisfied by the taglib directive's prefix attribute; all elements in the page that use the specified prefix belong to this custom tag library. A custom tag library defines a default prefix, used in the library's documentation and possibly by page-authoring tools that insert custom action elements in a page. You can, however, use any prefix you like except jsp, jspx, java, javax, servlet
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Actions from a Tag Library
Inhaltsvorschau
The custom action described in Table 7-1 does exactly the same thing as the second bean used in Chapter 6: it adds a message from a specified category to a page.
Table 7-1: Attributes for <ora:motd>
Attribute name
Java type
Dynamic value accepted
Description
category
String
Yes
Mandatory. The message category, either thoughts or quotes.
This custom action has one mandatory attribute named category, used to select the type of message you want. Let's get back to the "Java type" and "Dynamic value accepted" columns at the end of this chapter.
Example 7-2 shows the message.jsp page again, now with the custom action elements highlighted.
Example 7-2. Custom action elements (message.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="ora" uri="orataglib" %>

  

<html>

  <head>

    <title>Messages of the Day</title>

  </head>

  <body bgcolor="white">

    <h1>Messages of the Day</h1>

    <h2>Deep Thoughts - by Jack Handey</h2>

    <i>

      <ora:motd category="thoughts" />

    </i>

  

    <h2>Quotes From the Famous and the Unknown</h2>

    <i>

      <ora:motd category="quotes" />

    </i>

  </body>

</html>
First note how the <ora:motd> element name prefix matches the prefix assigned to the custom tag library by the taglib directive. The syntax for a custom action element is the same as for standard actions: an opening tag, possibly with attributes, a body, and a closing tag; or just one tag ending with
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 8: Processing Input and Output
Inhaltsvorschau
User input is a necessity in modern web pages. Most dynamic web sites generate pages based on user input submitted through an HTML form. Unfortunately, users seldom enter information in exactly the format you need, so before you can use such input, you need to validate it to make sure it's usable.
And it's not only the input format that's important. Web browsers are also picky about the format of the HTML you send them. For instance, when you generate an HTML form with values taken from a database, a name such as O'Reilly can cause problems. The single quote character after the O can fool the browser into believing it's at the end of the string, so you end up with just an O in your form.
In this chapter, we look at how you can use either JSTL actions or beans to access and validate user input. We also look at how special characters in the output must be treated so they don't confuse the browser.
The HTML specification defines a set of elements for presenting a form with fields in which the user can enter text or select among predefined choices. I'm sure you have encountered these countless times—to tell a vendor about yourself when downloading demo software, to specify what you're looking for on a search engine site, or to select the toppings when you order a pizza online. But you may not be familiar with what's going on behind the scene when you fill out the form and click Submit. Example 8-1 shows an HTML page that contains the most commonly used HTML form elements.
Example 8-1. HTML form elements
<html>

  <head>

    <title>User Info Entry Form</title>

  </head>

  <body bgcolor="white">

    <form action="process.jsp" method="post">

      <table>

        <tr>

          <td>Name:</td>

          <td>

            <input type="text" name="userName">

          </td>

        </tr>

        <tr>

          <td>Birth Date:</td>

          <td>

            <input type="text" name="birthDate">

          </td>

          <td>(Use format yyyy-mm-dd)</td>

        </tr>

        <tr>

          <td>Email Address:</td>

          <td>

            
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Reading Request Parameter Values
Inhaltsvorschau
The HTML specification defines a set of elements for presenting a form with fields in which the user can enter text or select among predefined choices. I'm sure you have encountered these countless times—to tell a vendor about yourself when downloading demo software, to specify what you're looking for on a search engine site, or to select the toppings when you order a pizza online. But you may not be familiar with what's going on behind the scene when you fill out the form and click Submit. Example 8-1 shows an HTML page that contains the most commonly used HTML form elements.
Example 8-1. HTML form elements
<html>

  <head>

    <title>User Info Entry Form</title>

  </head>

  <body bgcolor="white">

    <form action="process.jsp" method="post">

      <table>

        <tr>

          <td>Name:</td>

          <td>

            <input type="text" name="userName">

          </td>

        </tr>

        <tr>

          <td>Birth Date:</td>

          <td>

            <input type="text" name="birthDate">

          </td>

          <td>(Use format yyyy-mm-dd)</td>

        </tr>

        <tr>

          <td>Email Address:</td>

          <td>

            <input type="text" name="emailAddr">

          </td>

          <td>(Use format name@company.com)</td>

        </tr>

        <tr>

          <td>Gender:</td>

          <td>

            <input type="radio" name="gender" value="m" checked>Male<br>

            <input type="radio" name="gender" value="f">Female

          </td>

        </tr>

        <tr>

          <td>Lucky number:</td>

          <td>

            <input type="text" name="luckyNumber">

          </td>

          <td>(A number between 1 and 100)</td>

        </tr>

        <tr>

          <td>Favorite Foods:</td>

          <td>

            <input type="checkbox" name="food" value="z">Pizza<br>

            <input type="checkbox" name="food" value="p">Pasta<br>

            <input type="checkbox" name="food" value="c">Chinese

          </td>

        </tr>

        <tr>

          <td colspan=2>

            <input type="submit" value="Send Data">
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Validating User Input
Inhaltsvorschau
You should never trust your users, at least not when it comes to entering information in the format you need. Often, you need to make sure the input is valid before you continue to process a request. A date, for instance, can be written in many different formats. If you've traveled to the United States, and you're not a U.S. citizen, you probably have had to fill out both an I-94 and a customs declaration form to be admitted by an immigration officer. You may have noticed that on one of the forms you need to write your birth date as yy/mm/dd and on the other as mm/dd/yy. I always get it wrong.
The entry form used in the examples in this chapter has a number of fields that must be validated: a name must be entered, the birth date must be a valid date, the email address must at least look like a real email address (it's basically impossible to verify that it is in fact real), the gender must be one of m (male) or f (female), the lucky number must be a number between 1 and 100, and if any food favorites are selected, each must be one of z (pizza), p (pasta), or c (Chinese).
Simple input can be validated using the standard JSTL actions, but for more complex validation rules, a bean is a good choice. We will look at both approaches next. If you use JSP combined with servlets, the input validation is typically done by the servlet and the JSP pages are invoked only if the input turns out to be okay. This approach is described in Chapter 19.
Besides adding validation, let's make the input form example a bit more realistic. Instead of just echoing the entered values at the end of the page, we use them to set the initial values of the form fields. This makes it easier for the user to correct the mistakes. For each invalid value, an error message is also inserted above the incorrect field.
I use a number of JSTL actions that we have not discussed so far and a few tricks to implement these changes. To make all the new stuff easier to digest, we look at the new page in pieces. Example 8-5 shows the top part of the form with the validation and initialization of the Name field.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Formatting HTML Output
Inhaltsvorschau
If you enter a value containing double quotes in the Name field in the validate_jstl.jsp or the validate_bean.jsp page, such as Prince, "the artist", submit the form and look at the HTML code generated by the JSP page using your browser's View Source function, you see something like this:
<tr>

  <td>Name:</td>

  <td>

    <input type="text" name="userName"

      value="Prince, &#034;the artist&#034;">

  </td>

</tr>
Note that the quotes have been replaced with &#034;. What's going on here? This is the <c:out> action's doing, and it's a very good thing. In the JSP file, double quotes enclose the value of the <input> element's value attribute. If the value itself includes a double quote, the browser gets confused and interprets the first double quote in the value as the end of the value. To prevent this type of problem, the <c:out> action converts all problematic characters to their so-called HTML character-entity equivalents. It converts single quotes, double quotes, less-than signs, greater-than signs, and ampersands to the HTML character entities &#039;, &#034;, &lt;, &gt;, and &amp;, respectively. The browser handles the converted values without problem.
Besides taking care of the problem with quotes in a dynamic value, this type of character conversion also offers some protection against what's called a cross site scripting attack. What this means is that a malicious user submits input that causes problems when it's displayed by the browser. If the special characters aren't converted, entering <script>window.close( )</script> in the Name field for Example 8-2, for instance, causes the window to disappear. When text like this is added to the response as is, a browser with JavaScript enabled executes the script, with the effect that the browser window is closed. In this example, the malicious user harms only herself, but a more serious scenario is a site where a user can submit text that's then displayed to all other site visitors. A user submitting a partial HTML element can be equally annoying, for instance
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 9: Error Handling and Debugging
Inhaltsvorschau
When you develop any application that's more than a trivial example, errors are inevitable. A JSP-based application is no exception. There are many types of errors you will deal with. Simple syntax errors in the JSP pages are almost a given during the development phase. And even after you have fixed all the syntax errors, you may still have to figure out why the application doesn't work as you intended because of design mistakes. The application must also be designed to deal with problems that can occur when it's deployed for production use. Users can enter invalid values and try to use the application in ways you never imagined. External systems, such as databases, can fail or become unavailable due to network problems.
Since a web application is the face of the company, making sure it behaves well, even when the users misbehave and the world around it falls apart, is extremely important for a positive customer perception. Proper design and testing is the only way to accomplish this goal.
In this chapter, we look at the types of problems you can expect during development, as well as those common in a production system. You'll see how to track down JSP syntax and design errors, and to deal with runtime problems in a graceful manner.
The first type of error you will encounter is the one you, or your coworkers, create by simple typos—in other words, syntax errors. The JSP container needs every JSP element to be written exactly as it's defined in the specification in order to process the JSP page. When it finds something that's not right, it tells you. How easy it is to understand what it tells you depends on the type of error, the JSP container implementation, and sometimes, on how fluent you are in computer gibberish.
All container implementations report syntax errors, but details such as the wording of the messages, how much information the message contains, and where the message is written, differ between them. In this chapter, I show examples only of the messages produced by Tomcat.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Dealing with Syntax Errors
Inhaltsvorschau
The first type of error you will encounter is the one you, or your coworkers, create by simple typos—in other words, syntax errors. The JSP container needs every JSP element to be written exactly as it's defined in the specification in order to process the JSP page. When it finds something that's not right, it tells you. How easy it is to understand what it tells you depends on the type of error, the JSP container implementation, and sometimes, on how fluent you are in computer gibberish.
All container implementations report syntax errors, but details such as the wording of the messages, how much information the message contains, and where the message is written, differ between them. In this chapter, I show examples only of the messages produced by Tomcat.
Let's first look at how Tomcat reports some typical syntax errors in JSP directives and action elements. Example 9-1 shows a version of the easy.jsp page from Chapter 5 with a syntax error.
Example 9-1. Improperly terminated directive (error1.jsp)

                     <%@ page contentType="text/html" >

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

  <head>

    <title>JSP is Easy</title>

  </head>

  <body bgcolor="white">

  

    <h1>JSP is as easy as ...</h1>

  

    1 + 2 + 3 = <c:out value="${1 + 2 + 3}" />

  

  </body>

</html>
The syntax error here is that the page directive on the first line isn't closed properly with %>; the percent sign is missing. Figure 9-1 shows what Tomcat has to say about it.
Figure 9-1: Error message about an unterminated JSP directive
Tomcat reports the error by sending an error message to the browser. This is the default behavior for Tomcat, but it's not mandated by the JSP specification. The specification requires only that a response with the HTTP status code for a severe error (500) is returned, but how a JSP container reports the details is vendor-specific. For instance, the error message can be written to a file instead of the browser. If you use a container other than Tomcat, check the container documentation to see how it reports these types of errors.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Debugging a JSP Application
Inhaltsvorschau
After you have fixed all syntax errors, pat yourself on the back and enjoy the moment. If the application is more than a trivial example, however, this moment will probably be short-lived: you will likely find that one or more things still don't work as you expected. Logic errors, such as not taking care of all possible input combinations, can easily slip into an application during development. Finding and correcting this type of problem is called debugging.
For applications developed in compiled languages such as Java, C, or C++, a tool called a debugger is often used in this phase. It lets you step through the program line by line or run the program until it reaches a break point that you have defined, and lets you inspect the values of all variables in the program. With careful analysis of the program flow in runtime, you can discover why it works the way it does and not the way you want it to. There are debuggers for JSP as well, such as IBM's Visual Age for Java. Such products let you debug a JSP page exactly the same way as a program written in a more traditional programming language.
But a real debugger is often overkill for JSP pages. If your pages are so complex that you feel the need for a debugger, you may want to move code from the pages into JavaBeans or custom actions instead. These components can then be debugged with a standard Java debugger, which can be found in most Java Interactive Development Environments (IDEs). To debug JSP pages, another time tested debugging approach is usually sufficient: simply adding code to print variable values to the screen.
Let's look at how you can use this approach to find an error in an incorrect version of the input validation page from Chapter 8, shown in Example 9-9.
Example 9-9. Logical error (error9.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="ora" uri="orataglib" %>

  

<html>

  <head>

    <title>User Info Entry Form</title>

  </head>

  <body bgcolor="white">

  

    <form action="error9.jsp" method="post">

      <input type="hidden" name="submitted" value="true">

      <table>

        
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Dealing with Runtime Errors
Inhaltsvorschau
Eventually, your application will work the way you want. But things can still go wrong due to problems with external systems your application depends on, such as a database. And even though you have tested and debugged your application, there may be runtime conditions you didn't anticipate.
Well-behaved components, such as beans and JSP actions, deal with expected error conditions in a graceful manner. For instance, the UserInfo bean used in Chapter 8 has a valid attribute that is false unless all properties are set to valid values. Your JSP page can then test the property value and present the user with an appropriate message. The JSTL actions also act gracefully in most situations, for instance the <c:forEach> action simply does nothing if the items attribute value is null.
Some problems are impossible for the component to handle gracefully, however, and the user needs to be told about the problem instead. The standard way Java does this is to throw an exception. Beans, JSP actions, and the EL processor, can throw exceptions when something goes really bad. By default, the JSP container catches the exception and displays its message and stack trace in the browser, similar to what's shown in Figure 9-1. But that's hardly the type of error message you want the application users to see. Besides, the exception messages may reveal information that can be sensitive from a security point of view, such as file paths and SQL statements. You can present a much more user-friendly, and secure, response by telling the JSP container to use a customized error page instead.
Example 9-11 shows a JSP page with a page directive that defines an error page.
Example 9-11. Page with an error page definition (calc.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ page errorPage="errorpage.jsp?debug=log" %>

<html>

  <head>

    <title>Calculator</title>

  </head>

  <body bgcolor="white">

  

    <jsp:useBean id="calc" class="com.ora.jsp.beans.calc.CalcBean">

      <jsp:setProperty name="calc" property="*" />

    </jsp:useBean>

  

    <%-- Calculate the new numbers and state info --%>

    <c:set var="currentNumber" value="${calc.currentNumber}" />

  

    <form action="calc.jsp" method="post">

      <table border=1>

        <tr>

          <td colspan="4" align="right">

            <c:choose>

              <c:when test="${currentNumber == ''}">

                &nbsp;

              </c:when>

              <c:otherwise>

                <c:out value="${currentNumber}" />

              </c:otherwise>

            </c:choose>

            <input type="hidden" name="currentNumber" 

              value="${currentNumber}">

            <input type="hidden" name="previousNumber"

              value="${calc.previousNumber}">

            <input type="hidden" name="currentOperation"

              value="${calc.currentOperation}">

            <input type="hidden" name="reset"

              value="${calc.reset}">

          </td>

        </tr>

        <tr>

          <td><input type="submit" name="digit" value=" 7 "></td>

          <td><input type="submit" name="digit" value=" 8 "></td>

          <td><input type="submit" name="digit" value=" 9 "></td>

          <td><input type="submit" name="oper" value="  /  "></td>

        </tr>

        <tr>

          <td><input type="submit" name="digit" value=" 4 "></td>

          <td><input type="submit" name="digit" value=" 5 "></td>

          <td><input type="submit" name="digit" value=" 6 "></td>

          <td><input type="submit" name="oper" value="  *  "></td>

        </tr>

        <tr>

          <td><input type="submit" name="digit" value=" 1 "></td>

          <td><input type="submit" name="digit" value=" 2 "></td>

          <td><input type="submit" name="digit" value=" 3 "></td>

          <td><input type="submit" name="oper" value="  -  "></td>

        </tr>

        <tr>

          <td><input type="submit" name="digit" value=" 0 "></td>

          <td>&nbsp;</td>

          <td><input type="submit" name="dot" value="  .  "></td>

          <td><input type="submit" name="oper" value="  +  "></td>

        </tr>

        <tr>

          <td>&nbsp;</td>

          <td>&nbsp;</td>

          <td><input type="submit" name="clear" value=" C "></td>

          <td><input type="submit" name="oper" value="  =  "></td>

      </table>

    </form>

  

  </body>

</html>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 10: Sharing Data Between JSP Pages, Requests, and Users
Inhaltsvorschau
Any real application consists of more than a single page, and multiple pages often need access to the same information and server-side resources. When multiple pages process the same request (e.g., one page that retrieves the data the user asked for and another that displays it), there must be a way to pass data from one page to another. In an application in which the user is asked to provide information in multiple steps, such as an online shopping application, there must be a way to collect the information received with each request and get access to the complete set when the user is ready. Other information and resources need to be shared among multiple pages, requests, and all users. Examples are information about currently logged-in users, database connection pool objects, and cache objects to avoid frequent database lookups.
In this chapter you will learn how scopes in JSP provide access to this type of shared data. You will also see how using multiple pages to process a request leads to an application that's easier to maintain and expand, and learn about a JSP action that lets you pass control between the different pages.
As discussed in Chapter 3, one of the most fundamental features of JSP technology is that it allows for separation of request processing, business logic and presentation, using what's known as the Model-View-Controller (MVC) model. As you may recall, the roles of Model, View, and Controller can be assigned to different types of server-side components. In this part of the book, JSP pages are used for both the Controller and View roles, and the Model role is played by either a bean or a JSP page. This isn't necessarily the best approach, but it lets us focus on JSP features instead of getting into Java programming. If you're a programmer and interested in other role assignments, you may want to take a peek at Chapter 18 and Chapter 19. These chapters describe other alternatives and focus on using a servlet as the Controller.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Passing Control and Data Between Pages
Inhaltsvorschau
As discussed in Chapter 3, one of the most fundamental features of JSP technology is that it allows for separation of request processing, business logic and presentation, using what's known as the Model-View-Controller (MVC) model. As you may recall, the roles of Model, View, and Controller can be assigned to different types of server-side components. In this part of the book, JSP pages are used for both the Controller and View roles, and the Model role is played by either a bean or a JSP page. This isn't necessarily the best approach, but it lets us focus on JSP features instead of getting into Java programming. If you're a programmer and interested in other role assignments, you may want to take a peek at Chapter 18 and Chapter 19. These chapters describe other alternatives and focus on using a servlet as the Controller.
In this section we look at how to separate the different aspects in a pure JSP application, using a modified version of the User Info example from Chapter 8 as a concrete example. In this application, the business logic piece is trivial. However, it sets the stage for a more advanced application example in the next section and the remaining chapters in this part of the book; all of them use the pattern introduced here.
The different aspects of the User Info example can be categorized like this:
  • Display the form for user input (presentation)
  • Validate the input (request processing and business logic)
  • Display the result of the validation (presentation)
A separate JSP page is used for each aspect in the modified version. The restructured application contains the three JSP pages shown in Figure 10-1.
Figure 10-1: User Info application pages
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Sharing Session and Application Data
Inhaltsvorschau
The request scope makes data available to multiple pages processing the same request. But in many cases, data must be shared over multiple requests.
Imagine a travel agency application. It's important to remember the dates and destination entered to book the flight so that the customer doesn't have to reenter the information when it's time to make hotel and rental car reservations. This type of information, available only to requests from the same user, can be shared through the session scope.
Some information is needed by multiple pages independent of who the current user is. JSP supports access to this type of shared information through the application scope. Information saved in the application scope by one page can later be accessed by another page, even if the two pages were requested by different users. Examples of information typically shared through the application scope are information about currently logged-in users and cache objects that avoid unnecessary database queries for data that is the same for all users.
Figure 10-4 shows how the server provides access to the two scopes for different clients.
Figure 10-4: Session and application scopes
The upcoming examples in this chapter will help you to use the session and application scopes.
Keeping track of which requests come from the same user isn't as easy as it may look. As described in Chapter 2, HTTP is a stateless, request-response protocol. This means that the browser sends a request for a web resource, and the web server processes the request and returns a response. The server then forgets this transaction ever happened. So when the same browser sends a new request; the web server has no idea that this request is related to the previous one. This is fine as long as you're dealing with static files, but it's a problem in an interactive web application.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Online Shopping
Inhaltsvorschau
Now let's look at a more useful example; an online shopping site. Besides showing you examples on how the session and application scopes can be used effectively in a larger application, this example also introduces other useful tools, such as JSTL actions for number formatting and redirection, and EL syntax for getting collection values based on keys determined at runtime.
The application consists of three pages. The main page lists all available products. Each product is linked to a product description page, where the product can be added to the shopping cart. A product is added to the shopping cart by a request processing page. The main page with the product list is then displayed again, but with the current contents of the shopping cart as well, as shown in Figure 10-7.
Figure 10-7: The product list and the contents of the shopping cart
Two beans are used to keep track of the products: the com.ora.jsp.beans.shopping.CatalogBean contains all available products, and the com.ora.jsp.beans.shopping.CartBean represents one user's shopping cart. Each product in the catalog is represented by a ProductBean. Table 10-5, Table 10-6, and Table 10-7 show all the properties for the beans.
Table 10-5: Properties for com.ora.jsp.beans.shopping.CatalogBean
Property name
Java type
Access
Description
productList
com.ora.jsp.beans.shopping.ProductBean[]
Read
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Memory Usage Considerations
Inhaltsvorschau
You should be aware that all objects you save in the application and session scopes take up memory in the server process. It's easy to calculate how much memory is used for the application scope because you have full control over the number of objects you place there. But the total number of objects in the session scope depends on the number of concurrent sessions, so in addition to the size of each object, you also need to know how many concurrent users you have and how long a session lasts. Let's look at an example.
The CartBean used in this chapter is small. It stores only references to ProductBean instances, not copies of the beans. An object reference in Java is 8 bytes, so with three products in the cart we need 24 bytes. The java.util.Vector object used to hold the references adds some overhead, say 32 bytes. All in all, we need 56 bytes per shopping cart bean with three products.
If this is a site with a modest amount of customers, you may have 10 users shopping per hour. The default timeout for a session is 30 minutes, so let's say that at any given moment, you have 10 active users and another 10 sessions that aren't active but have not timed out yet. This gives a total of 20 sessions times 56 bytes per session, a total of 1,120 bytes. In other words, roughly 1 KB—nothing to worry about.
Now let's say your site becomes extremely popular, with 2,000 customers per hour. Using the same method to calculate the number of concurrent sessions as before, you will have 4,000 sessions at 56 bytes; that's a total of roughly 220 KB—still nothing to worry about. However, if you store larger objects in each session, say the result of a database search with an average size of 10 KB, it corresponds to roughly 40 MB for 4,000 sessions. A lot more but still not extreme, at least not for a site intended to handle this amount of traffic. However, it should become apparent that with that many users, you have to be a bit careful with how you use the session scope.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 11: Developing Custom Tag Libraries as Tag Files
Inhaltsvorschau
Starting with the 2.0 version of the JSP specification, custom tag library actions can be implemented in two ways: as Java classes or as regular text files containing JSP elements. In prior versions, custom actions could only be implemented as Java classes, putting them out of the reach of nonprogrammers. Another problem with the Java implementation of custom actions is that you're forced to printout HTML code with println( ) calls to produce complex content—the very problem JSP was supposed to solve.
In this chapter I show you how to develop custom actions as plain text files and package them as tag libraries that can be used in JSP pages.
A tag file is a text file that contains JSP elements implementing the functionality of a custom action. You must use a .tag filename extension to identify this type of file to the web container. All JSP elements that you can use in a JSP file can also be used in a tag file, with exception to the page directive (a tag file is not a page). There are also a few JSP directives that are only allowed in a tag file, as you will see shortly. Apart from that, creating a tag file is no different than creating a JSP page. Once created and installed, a tag file is used the same as the custom actions implemented in Java that you've seen in previous chapters.
Example 11-1 shows a very simple tag file.
Example 11-1. Simple tag file (copyright.tag)

                  <%@ tag body-content="empty" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



<jsp:useBean id="now" scope="application" class="java.util.Date" />

Copyright &copy; ${now.year + 1900} My Company
This tag file inserts a copyright statement with the current year in the calling page. The first line is a tag directive. You may use attributes of this directive to specify a description, icon, or an example that a page-authoring tool can show the designer. Other attributes let you specify whether EL expressions should be processed, as well as various information related to scripting code, i.e., the same type of information as you specify with the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Creating and Using a Tag File
Inhaltsvorschau
A tag file is a text file that contains JSP elements implementing the functionality of a custom action. You must use a .tag filename extension to identify this type of file to the web container. All JSP elements that you can use in a JSP file can also be used in a tag file, with exception to the page directive (a tag file is not a page). There are also a few JSP directives that are only allowed in a tag file, as you will see shortly. Apart from that, creating a tag file is no different than creating a JSP page. Once created and installed, a tag file is used the same as the custom actions implemented in Java that you've seen in previous chapters.
Example 11-1 shows a very simple tag file.
Example 11-1. Simple tag file (copyright.tag)

                  <%@ tag body-content="empty" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



<jsp:useBean id="now" scope="application" class="java.util.Date" />

Copyright &copy; ${now.year + 1900} My Company
This tag file inserts a copyright statement with the current year in the calling page. The first line is a tag directive. You may use attributes of this directive to specify a description, icon, or an example that a page-authoring tool can show the designer. Other attributes let you specify whether EL expressions should be processed, as well as various information related to scripting code, i.e., the same type of information as you specify with the page directive in JSP pages. All of these attributes are described in Appendix A.
In most cases, tag file authors only care about the attribute used in Example 11-1: body-content . This attribute defines how the custom action element's body should be handled, and that it must have one of these values: empty, scriptless (the default), or tagdependent. If it's empty (as in Example 11-1), trying to use a body for the custom action element results in a syntax error. The scriptless value means that the body can contain any JSP elements except the type of scripting elements described in Chapter 16. In other words, template text, EL expressions, standard actions, and custom actions are all allowed. As you will see later, the tag file can ask the container to process the actions in a scriptless body when and how often as it wants through the use of standard action named
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Accessing Attribute Values
Inhaltsvorschau
The tag file in Example 11-1 is too simple to illustrate all that you can do with tag files. For instance, most real-world tag files are controlled through attribute values set by the page author. You may recall from Chapter 7 that the <ora:motd> custom action has a category attribute for selecting the message category that messages should be picked from. Example 11-2 shows how a tag file implementation of the <ora:motd> action declares, accesses, and uses this attribute value.
Example 11-2. Using attributes in a tag file (motd.tag)
<%@ tag body-content="empty" %>

<%@ attribute name="category" required="true" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



<jsp:useBean id="mmb" class="com.ora.jsp.beans.motd.MixedMessageBean" />

<c:set target="${mmb}" property="category" value="${category}" />

${mmb.message}
Each attribute must be declared with an attribute directive in a tag file. In Example 11-2, the category attribute is declared using an attribute directive with the name attribute set to category. The required attribute is set to true, meaning that the page author must specify a value for the category attribute; the container complains if the attribute is missing. The default value for required is false, so you can leave it out for attributes that are optional.
Another attribute of the attribute directive, not used in Example 11-2, is rtexprvalue . A value of true means that the author can specify the value either as a static string or as a request-time attribute value , such as an EL expression; false means the value must be a static string. The default value is true, so you only need to use this attribute if you absolutely require a static value.
The value the page author assigns to an attribute shows up as a page scope variable in the tag file, with the same name as the attribute. This makes it easy to use it in an EL expression. In Example 11-2, a <c:set> action sets the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Processing the Action Body
Inhaltsvorschau
So far, the tag files we've looked at ignore (or actually forbid) the body of the custom action element used to invoke them, but the body is often an important part of the equation. One example is a conditional custom action, such as a variation of the <c:if> JSTL action. It needs to process the body if the condition is true. Another example is a custom action that transforms the body in some way or simply uses it as input.
Let's develop a custom action that transforms its body content. It first converts all characters that have special meaning in HTML and XML to the corresponding character entity codes (e.g., < to &lt;), and then converts special proprietary codes into HTML elements. A custom action like this can be used to process user input in an online forum to protect it against cross-site scripting attacks while still allowing for limited formatting of the messages. Here's how you can use this custom action in a JSP page:
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="my" tagdir="/WEB-INF/tags/mytags" %>



<%-- Create test data --%>

<c:set var="message">

  This is just a lot of text that the browser will format to

  fit the browser window. Attempts to <blink> add HTML elements

  are dealt with by conversion to character entities.

  [code]

  This part I want the browser to leave alone, so that

  all my indentations are left intact:



    public class Foo {

      public String getBar(  ) {

        return bar;

      }

    }

  [/code]

  And then some regular text again.

</c:set>

<html>

  <head>

    <title>Online Forum</title>

  </head>

  <body bgcolor="white">

    <h1>Online Forum</h1>

    Here's a formatted message:

    <p>

      <my:htmlFormat>

               ${message}

               </my:htmlFormat>

    </p>

  </body>

</html>
This page first saves test data containing text, an HTML element, and the proprietary formatting codes in a variable named message. In a real application, the text would likely come from a database or some other external source. It then processes the text with the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Processing Fragment Attributes
Inhaltsvorschau
Processing the custom action body is easy and powerful as you can see, but wait, there's more! The custom action body is actually just a special case of what's called a JSP fragment in the JSP specification. A JSP fragment is an executable representation of a set of dynamic elements (actions and EL expressions), optionally mixed with template text. When the tag file invokes the fragment, all the dynamic elements in the fragment are executed. Since the elements have access to the current values of all scoped variables, the result typically differs from invocation to invocation, and the tag file can invoke it any number of times (e.g., once or none for a conditional action or multiple times for an iteration action).
In Example 11-4, the <jsp:doBody> action invokes the special fragment representing a custom action element body, but named fragments can also be provided as custom action attributes and be invoked by the tag file. Such fragments are invoked with the <jsp:invoke> action, described in Table 11-2.
Table 11-2: Attributes for <jsp:invoke>
Attribute name
Java type
Dynamic value accepted
Description
fragment
String
No
Mandatory. The name of the fragment to invoke.
var
String
No
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Exposing Data to the Calling Page Through Variables
Inhaltsvorschau
Attributes provide input to a custom action, but sometimes you also need to give the page that contains the custom action access to data produced by the custom action. For instance, the <my:forEvenAndOdd> action is not all that useful unless the page can access the current iteration value in the fragments for even and odd rows. To handle this requirement, data can be passed from a custom action to the caller by exposing it through declared variables.
Example 11-6 shows a version of the tag file from Example 11-5 that's been extended to expose the current iteration value as a variable named current. All differences between the examples are highlighted.
Example 11-6. Exporting data through variables (forEvenAndOdd2.tag)
<%@ tag body-content="empty" %>

<%@ attribute name="items" rtexprvalue="true" required="true" %>

<%@ attribute name="even" fragment="true" required="true" %>

<%@ attribute name="odd" fragment="true" required="true" %>

<%@ variable name-given="current" variable-class="java.lang.Object"

  scope="NESTED" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



<c:forEach items="${items}" varStatus="status" var="current">

  <c:choose>

    <c:when test="${status.count % 2 == 0}">

      <jsp:invoke fragment="even" />

    </c:when>

    <c:otherwise>

      <jsp:invoke fragment="odd" />

    </c:otherwise>

  </c:choose>

</c:forEach>
The variable directive declares the variable. The name-given attribute specifies its name and the variable-class attribute its type. (Here I use the most generic class possible, java.lang.Object, because the collection to iterate over can contain elements of any type.)
The scope attribute accepts one of three values: AT_BEGIN, AT_END, or NESTED. It controls where the caller sees the variable. Despite its name, it has nothing to do with the scopes we've talked about earlier (page, request, session, and application), so visibility would have been a better name for this attribute. If it's set to
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Aborting the Page Processing
Inhaltsvorschau
In Chapter 9, I described how using the <jsp:forward> action or the JSTL <c:redirect> action shifts processing from the current page to the page specified by the page attribute, effectively aborting processing of the current page. Custom actions implemented as Java classes can cause the same thing to happen.
There's no directive or similar mechanism that a tag file can use to explicitly abort processing, but using <jsp:forward>, <c:redirect>, or a custom action that aborts page processing in a tag file has the same effect; both the tag file processing and the processing of the page that invokes the tag file stop after it aborts the processing. You can use this feature to, for instance, develop a smart forwarding action that decides which page to forward to based on runtime conditions, such as the time of the day, the current user, or the type of browser accessing the page.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Packaging Tag Files for Easy Reuse
Inhaltsvorschau
All examples in this chapter use a taglib directive with a tagdir attribute to specify the directory that contains the tag files. While this is handy for custom actions implemented as tag files in an application you control, it's not as easy as one would want for deployment and use of the tag library in third-party applications. As you may recall from Chapter 7, it's very easy to deploy a tag library packaged as a JAR file; just put the JAR file in the WEB-INF/lib directory and use the default URI as the uri attribute value in the taglib directive.
You can do the same with a tag library developed as tag files, but in this case you must also create a Tag Library Descriptor (TLD) and include it in the JAR file. I described the purpose of the TLD briefly in Chapter 7, but let's take a closer look at it here. Example 11-8 shows the TLD for a tag library with some of the tag files we've developed in this chapter.
Example 11-8. TLD for tag files
<?xml version="1.0" encoding="ISO-8859-1" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"

  version="2.0">



  <tlib-version>1.0</tlib-version>

  <short-name>my</short-name>

  <uri>mytaglib</uri>



  <tag-file>

    <name>copyright</name>

    <path>/META-INF/tags/mytags/copyright.tag</path>

  </tag-file>



  <tag-file>

    <name>forEvenAndOdd</name>

    <path>/META-INF/tags/mytags/forEvenAndOdd.tag</path>

  </tag-file>



  <tag-file>

    <name>htmlFormat</name>

    <path>/META-INF/tags/mytags/htmlFormat.tag</path>

  </tag-file>



</taglib>
As you can see, this file is an XML document. Don't worry about the <taglib> element attributes; just copy the element exactly as its shown here into your TLD. I describe it in more detail in Chapter 21, along with the TLD elements not covered here.
The first elements provide information about the tag library itself. The
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 12: Accessing a Database
Inhaltsvorschau
Almost all the web applications that you see on the Internet access a database. Databases store customer information, order information, product information, even discussion forum messages—in short, all information that needs to survive a server restart and is too complex to handle in plain-text files.
There are many types of databases used in the industry today. However, relational databases are by far the most common. A relational database uses tables to represent the information it handles. A table consists of rows of columns, with each column holding a single value of a predefined data type. Examples of these data types are text data, numeric data, dates, and binary data such as images and sound. A specialized language called Structured Query Language (SQL) is used to access the data. SQL is an ANSI standard and is supported by all major database vendors.
Relational database engines come in all shapes and sizes, from simple one-person databases with limited features, to sophisticated databases capable of handling large numbers of concurrent users with support for transactions distributed over multiple servers and extremely optimized search algorithms. Even though they all use SQL as the data access language, the API used to execute SQL statements is different for each database engine. To help programmers write code that's portable between database engines, the standard Java libraries include an API called the Java Database Connectivity (JDBC) API. JDBC defines a set of classes that can execute SQL statements the same way in any relational database.
The complexity of databases varies extensively. A database for an online discussion forum, for instance, requires only one or two tables, while a database for a human resources system may contain hundreds of related tables. In this chapter, we look at a set of JSTL database actions you can use to build any type of database-driven web application. But if the database is complex, you may want to use another approach: hiding the database behind application-specific beans and custom actions, or moving all database processing to a servlet and using JSP only to show the result. Both these approaches are discussed briefly at the end this chapter and in more detail in Chapter 18, Chapter 19, and Chapter 24.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Accessing a Database from a JSP Page
Inhaltsvorschau
JSTL includes a number of actions for database access to make it easy to develop simple database-driven JSP applications. The actions provide the following features:
  • Using a connection pool for better performance and scalability
  • Supporting queries, updates, and inserts
  • Handling the most common data type conversions
  • Supporting a combination of database operations in one transaction
Each action is introduced as it's used in the example in this chapter. In addition, you can find a complete description of all the actions in Appendix B.
In this chapter, we build an employee register application. This application contains functions for adding and changing employee information, as well as for looking up employees matching a search criterion. The employee information is stored in a relational database and accessed through the JSTL database access actions.
The employee registration part of the application contains the pages shown in Figure 12-1.
Figure 12-1: Employee registration pages
This example looks similar to the example from Chapter 10. The enter.jsp page presents a form in which the user enters information about an employee. When the form is submitted, it invokes the validate.jsp page, where all input is validated. If the input is invalid, the request is forwarded back to the enter.jsp page to display error messages and the form with all the values the user previously entered. The user can then correct the invalid values and submit the form again. When all input is valid, the validate.jsp page forwards the request to the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Validating Complex Input Without a Bean
Inhaltsvorschau
Before we look at the two remaining database sections, let's go back and take a look at the two application pages we skipped earlier, namely the enter.jsp and validate.jsp pages used for input to the employee registration.
In Chapter 8, I introduced you to validation of user input using the JSTL <c:if> action as well as using an application-specific bean. The bean contains all validation code and can therefore validate the format of complex data, such as date strings, email addresses, and credit-card numbers. This is the approach I recommend, but if you're developing a JSP-based application without access to a Java programmer to develop the beans you need, I'll show you a trick you can use to validate dates and a custom action for email-address validation.
The validate.jsp page uses the JSTL <c:if> action and the custom action to validate all user input. If an input parameter isn't valid, an error message is saved in a variable, and the request is forwarded back to the enter.jsp page. The enter.jsp page adds all the error messages to the response, so to the user, the result is identical to the bean-based validation approach you saw in Chapter 8.
Let's look at validate.jsp first, shown in Example 12-8.
Example 12-8. Validation with application beans (validate.jsp)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%@ taglib prefix="ora" uri="orataglib" %>

  

<c:set var="isValid" value="true" />

<c:if test="${empty param.userName}">

  <c:set var="userNameError" scope="request"

    value="User Name missing" />

  <c:set var="isValid" value="false" />

</c:if>

<c:if test="${empty param.password}">

  <c:set var="passwordError" scope="request"

    value="Password missing" />

  <c:set var="isValid" value="false" />

</c:if>

<c:if test="${empty param.firstName}">

  <c:set var="firstNameError" scope="request"

    value="First Name missing" />

  <c:set var="isValid" value="false" />

</c:if>

<c:if test="${empty param.lastName}">

  <c:set var="lastNameError" scope="request"

    value="Last Name missing" />

  <c:set var="isValid" value="false" />

</c:if>

<c:if test="${empty param.dept}">

  <c:set var="deptError" scope="request"

    value="Department missing" />

  <c:set var="isValid" value="false" />

</c:if>

  

<%-- Validate date by catching a possible exception --%>

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Transactions
Inhaltsvorschau
There's one important database feature we have not discussed yet. In the examples in this chapter, only one SQL statement is needed to complete all database modifications for each request. This statement either succeeds or fails. However, sometimes you need to execute two or more SQL statements in sequence to update the database. A typical example is transferring money between two accounts; one statement removes some amount from the first account, and another statement adds the same amount to the second account. If the first statement is successful, but the second one fails, you have performed a disappearance act your customers aren't likely to applaud.
The solution to this problem is to group all related SQL statements into what is called a transaction. A transaction is an atomic operation, so if one statement fails, they all fail; otherwise, they all succeed. This is referred to as committing (if it succeeds) or rolling back (if it fails) the transaction. If there's a problem in the middle of a money transfer, for instance, the database makes sure the money is returned to the first account by rolling back the transaction. If no problems are encountered, the transaction is committed, permanently storing the changes in the database.
There's a JSTL database action to handle transactions, described in Table 12-9.
Table 12-9: Attributes for JSTL <sql:transaction>
Attribute name
Java type
Dynamic value accepted
Description
dataSource
javax.sql.DataSource
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Application-Specific Database Actions
Inhaltsvorschau
You can use the JSTL database actions described in this chapter to develop many types of interesting web applications, such as product catalog interfaces, employee directories, or online billboards, without being a Java programmer. These types of applications account for a high percentage of the web applications developed today. But at some level of complexity, putting SQL statements directly in the web pages can become a maintenance problem. The SQL statements represent business logic, and for more complex applications, business logic is better developed as separate Java classes.
For a complex application, it may be better to use application-specific custom actions instead of the JSTL database actions described in this chapter. For example, all the generic database actions in Example 12-1, to SELECT and then INSERT or UPDATE the database, can be replaced with one application-specific action like this:
<myLib:saveEmployeeInfo dataSource="${example}" />
Part III, especially Chapter 24, describes how you can develop this type of custom action. Besides making it easier for the page author to deal with, the beauty of using an application-specific custom action is that it lets you evolve the application behind the scene. Initially, this action can be implemented so it uses JDBC to access the database directly, similar to how the JSTL actions work. But at some point it may make sense to migrate the application to an Enterprise JavaBeans architecture, perhaps to support other types of clients than web browsers. The action can then be modified to interact with an Enterprise JavaBeans component instead of accessing the database directly. From the JSP page author's point of view, it doesn't matter; the custom action is still used exactly the same way.
Another approach is to use a servlet for all database processing and only use JSP pages to show the result. You will find an example of this approach in Chapter 19.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 13: Authentication and Personalization
Inhaltsvorschau
Authentication means establishing that a user really is who he claims to be. Today, it's typically done by asking the user for a username and a matching password, but other options are becoming more and more common. For example, most web servers support client certificates for authentication. Biometrics, which is the use of unique biological patterns such as fingerprints for identification, will likely be another common option in the near future. What's important is that an application should not be concerned with the way a user has been authenticated (since the method may change) but only that he has passed the test.
Access control, or authorization, is another security mechanism that's strongly related to authentication. Different users may be allowed different types of access to the content and services a web site offers. When you have established who the user is through an authentication process, access-control mechanisms ensure that the user can only access what he is allowed to access.
In the end, authentication provides information about who the user is, and that's what is needed to provide personalized content and services. For some types of personalization, the procedures we might think of as authentication may be overkill. If the background colors and type of news listed on the front page are the extent of the personalization, a simple cookie can be used to keep track of the user instead. But if personalization means getting access to information about taxes, medical records, or other confidential information, true authentication is definitely needed.
In this chapter we look at different approaches to authentication and access control with JSP, and we use the information about who the user is to provide modest personalization of the application pages. Security, however, is about more than authentication and access control. The last section of this chapter presents a brief summary of other areas that need to be covered for applications dealing with sensitive data.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Container-Provided Authentication
Inhaltsvorschau
A JSP page is always executing in a runtime environment provided by a container. Consequently, all authentication and access control can be handled by the container, relieving the application developer from the important task of implementing appropriate security controls. Security is hard to get right, so your first choice should always be to use the time-tested mechanisms provided by the container.
The servlet specification (starting with Version 2.2), on which JSP is based, describes three authentication mechanisms supported by most web clients and web servers:
  • HTTP basic authentication
  • HTTP digest authentication
  • HTTPS client authentication
In addition, it defines one mechanism that should be implemented by a compliant servlet container:
  • Form-based authentication
HTTP basic authentication has been part of the HTTP protocol since the beginning. It's a very simple and not very secure authentication scheme. When a browser requests access to a protected resource, the server sends back a response asking for the user's credentials (username and password). The browser prompts the user for this information and sends the same request again, but this time with the user credentials in one of the request headers so the server can authenticate the user. The username and password are not encrypted, only slightly obfuscated by the well-known base64 encoding. This means it can easily be reversed by anyone who grabs it as it's passed over the network. This problem can be resolved using an encrypted connection between the client and the server, such as the Secure Sockets Layer (SSL) protocol. We talk more about this in the last section of this chapter.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Application-Controlled Authentication
Inhaltsvorschau
Using one of the container-provided mechanisms described in the previous section should be your first choice for authentication. But, by definition, being container-provided means the application cannot dynamically add new users and roles to control who is granted access, at least not through a standard API defined by the servlet and JSP specifications.
For some types of applications, it's critical to have a very dynamic authentication model; one that doesn't require an administrator to define access rules before a new user can join the party. I'm sure you have seen countless sites where you can sign up for access to restricted content simply by filling out a form. One example is a project management site, where registered users can access document archives, discussion groups, calendars, and other tools for distributed cooperation. Another example is a personalized news site that you can customize to show news only about things you care about.
Unless you can define new users programmatically in the database used by an external authentication mechanism, you need to roll your own authentication and access-control system for these types of applications. In this section, we'll look at the principles for how to do this. Note that this approach sends the user's password as clear text, so it has the same security issues as the container-provided basic and form-based authentication methods.
Application-controlled authentication and access control requires the following pieces:
  • User registration
  • A login page
  • The authentication mechanism, invoked by the login page
  • Information saved in the session scope as proof of successful authentication
  • Validation of the session information in all JSP pages requiring restricted access
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Other Security Concerns
Inhaltsvorschau
In this chapter we have discussed only authentication and access control, but there's a lot more to web application security. You also need to ensure that no one listening on the network can read the data. In addition, you need to consider ways to verify that no one has hijacked the data and modified it before it reaches its final destination. Common terms for these concerns are confidentiality and data privacy for the first, and integrity checking for the second.
On an intranet, users can usually be trusted not to use network listeners to get to data they shouldn't see. But on the Internet, you can make no assumptions. If you provide access to sensitive data, you have to make sure it's protected appropriately. Network security is a huge subject area and clearly not within the scope of this book. Therefore I will touch only on the most common way to take care of both confidentiality and integrity checking, namely the Secure Socket Layer (SSL) protocol.
SSL is a protocol based on public key cryptography; it relies on a public key and a private key pair. Messages sent by someone, or something (like a server), are encoded using the private key and can be decoded by the receiver only by using the corresponding public key. Besides confidentiality and integrity checking, public key cryptography also provides very secure authentication; if a message can be decoded with a certain public key, you know it was encoded with the corresponding private key. The keys are issued, in the form of certificates together with user identity information, by a trusted organization such as VeriSign (http://www.verisign.com/).
Both the browser and the server can have certificates. However, the most common scenario today is that only the server has a certificate and can thereby positively identify itself to the browser. The SSL protocol takes care of this server authentication during the handshaking phase of setting up the connection. If the server certificate doesn't match the server's hostname, the user is warned, or the connection is refused. If the browser also has a certificate, it can authenticate the browser to the server in a more secure fashion than basic and digest authentication.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 14: Internationalization
Inhaltsvorschau
Taking the term World Wide Web literally means that your web site needs to respect the local languages and customs of all visitors, no matter where they come from. More and more, large web sites provide content in several different languages. Just look at sites like Yahoo!, which provide directory services in the local language of more than 20 countries in Europe, Asia Pacific, and North and South America. Other good examples are CNN, with local news for 3 continents in 7 different languages, and Vitaminic (http://www.vitaminic.com/), a site with MP3 music and artist information customized for different countries. If the site contains only static content, it's fairly easy to support multiple languages: just make a static version of the site for each language. But this approach is not practical for a site with dynamic content. If you develop a separate site for each language, you will have to duplicate the code that generates the dynamic content as well, leading to maintenance problems when errors are discovered or when it's time to add new features. Luckily, Java and JSP provide a number of tools to make it easier to develop one version of a site that can handle multiple languages.
The process of developing an application that caters to the needs of users from different parts of the world includes two phases: internationalization and localization.
Internationalization means preparing the application by identifying everything that will be different for different geographical regions and providing means to use different versions of all these items instead of hardcoded values. Examples of this are labels and messages, online help texts, graphics, format of dates, times and numbers, currencies, measurements, and sometimes even the page layouts and colors. Instead of spelling out the word internationalization, the abbreviation I18N is often used. It stands for "an I followed by 18 characters and an N."
When an application has been internationalized, it can also be localized for different regions. This means providing the application messages, help texts, graphics, and so forth, as well as rules for formatting dates/times and numbers, for one or more regions. Localization is sometimes abbreviated L10N, following the same logic as the I18N abbreviation. Support for new regions can be added without changing the application itself, simply by installing new localized resources.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
How Java Supports Internationalization and Localization
Inhaltsvorschau
Java was designed with internationalization in mind and includes a number of classes to make the effort as painless as possible. The primary class used for internationalization represents a specific geographical region. Instances of this class are used by other classes to format dates and numbers, and include localized strings and other objects in an application. There are also classes for dealing with different character encodings, as you will see later in the chapter.
All Java classes that provide localization support use a class named java.util.Locale. An instance of this class represents a particular geographical, political, or cultural region, as specified by a combination of a language code and a country code. Java classes that perform tasks that differ depending on a user's language and local customs—so called locale-sensitive operations—use a Locale instance to decide how to operate. Examples of locale-sensitive operations are interpreting date strings and formatting numeric values.
You create a Locale instance using a constructor that takes the country code and language code as arguments:
java.util.Locale usLocale = new Locale("en", "US");
Here, a Locale for U.S. English is created. George Bernard Shaw (a famous Irish playwright) once observed that "England and America are two countries divided by a common language," so it's no surprise that both a language code and a country code are needed to describe some locales completely. The language code, a lowercase two-letter combination, is defined by the ISO 639 standard available at http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt. The country code, an uppercase two-letter combination, is defined by the ISO 3166 standard, available at http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html. Tables Table 14-1 and Table 14-2 show some of these codes.
Table 14-1: ISO-639 language codes
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Generating Localized Output
Inhaltsvorschau
Now that you have an understanding of the type of internationalization support Java provides, let's look at a concrete example. However, instead of using the internationalization classes directly in the pages, we'll use the JSTL I18N actions based on these classes.
The example application, briefly described in the introduction to this chapter, lets visitors voice their opinion by selecting one of the answers to a question, as well as seeing how others have answered. The text, numbers, and dates are available in three different languages. Figure 14-1 shows all the pages used in this application and how they are related.
Figure 14-1: Localized poll application pages
The first page the user sees is the poll.jsp page, shown in Figure 14-2. The language that displays the contents the first time this page is requested is based on the Accept-Language request header value. The top part of the page contains radio buttons for the three supported languages and a Submit button. If the user wants the application to be presented in another language, he selects the corresponding radio button and clicks Submit, causing the page to be requested again, this time with a language parameter included in the request. The value of the language parameter is then used to select the corresponding locale and display the page in the selected locale's language. Information about the selected locale is saved as session data, so it's available to all the other application pages as well.
Figure 14-2: The language selection and question page
The poll.jsp page also includes the question, linked to a page with background information for the question, and a group of radio buttons representing the different answers, as well as a Submit button. Clicking on the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
A Brief History of Bits
Inhaltsvorschau
Let's shift gears a little and discuss additional issues to consider when dealing with non-Western European languages. Once upon a time, not so long ago, bits were very expensive. Hard disks for storing bits, memory for loading bits, communication equipment for sending bits over the wire; all the resources needed to handle bits were costly. To save on these expensive resources, characters were initially represented by only seven bits. This was enough to represent all letters in the English alphabet, 0 through 9, punctuation characters, and some control characters. That was all that was really needed in the early days of computing, because most computers were kept busy doing number crunching.
But as computers were given new tasks, often dealing with human-readable text, 7 bits didn't cut it. Adding one bit made it possible to represent all letters used in the Western European languages, but there are other languages besides the Western European languages, even though companies based in English-speaking countries often seem to ignore them. Eight bits is not enough to represent all characters used around the world. This problem was partly solved by defining a number of standards for how eight bits should be used to represent different character subsets. Each of the 10 ISO-8859 standards defines what is called a charset: a mapping between 8 bits (a byte) and a character. For instance, ISO-8859-1, also known as Latin-1, defines the subset used for Western European languages, such as English, French, Italian, Spanish, German, and Swedish. This is the default charset for HTTP. Other standards in the same series are ISO-8859-2, covering Central and Eastern European languages such as Hungarian, Polish, and Romanian, and ISO-8859-5, with Cyrillic letters used in Russian, Bulgarian, and Macedonian. You can find information about all 10 charsets in the ISO-8859 series at http://czyborra.com/charsets/iso8859.html.
Such languages as Chinese and Japanese contain thousands of characters but with 8 bits, you can only represent 256. A number of multibyte charsets have therefore been defined to handle these languages, such as Big5 for Chinese, Shift_JIS for Japanese, and EUC-KR for Korean.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Handling Localized Input
Inhaltsvorschau
So far we have discussed how to generate pages in different languages, but most applications also need to deal with localized input. As long as you're supporting only Western European languages, the only thing you typically need to worry about is how to interpret dates and numbers. The JSTL I18N actions can help you with this as well.
Example 14-5 shows a JSP page with the same form for selecting a language as in Example 14-1, plus a form with one field for a date and another for a number.
Example 14-5. Date and number input form (input.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

  

<%-- 

  Set the locale to the selected one, if any. Otherwise, let the

  <fmt:bundle> action pick the best one based on the Accept-Language

  header.

--%>

<c:if test="${param.language == 'en'}">

  <fmt:setLocale value="en" scope="session" />

</c:if>

<c:if test="${param.language == 'sv'}">

  <fmt:setLocale value="sv" scope="session" />

</c:if>

<c:if test="${param.language == 'de'}">

  <fmt:setLocale value="de" scope="session" />

</c:if>

<fmt:setBundle basename="input" var="inputBundle" />

<fmt:setBundle basename="input" scope="session" />

<html>

  <head>

    <title>

      <fmt:message key="title" />

    </title>

  </head>

  <body bgcolor="white">

    <h1>

      <fmt:message key="title" />

    </h1>

  

    <fmt:message key="select_language" />

    <form action="input.jsp">

      <c:set var="currLang" value="${inputBundle.locale.language}" />

      <input type="radio" name="language" value="en"

        ${currLang == 'en' ? 'checked' : ''}>

        <fmt:message key="english" /><br>

      <input type="radio" name="language" value="sv"

        ${currLang == 'sv' ? 'checked' : ''}>

        <fmt:message key="swedish" /><br>

      <input type="radio" name="language" value="de"

        ${currLang == 'de' ? 'checked' : ''}>

        <fmt:message key="german" />
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 15: Working with XML Data
Inhaltsvorschau
There's no escape from Extensible Markup Language (XML) these days. It's everywhere: in configuration files, messages between servers, web pages, even databases. Wherever there's structured data, XML is often found close by.
As I mentioned earlier, JSP pages can generate any type of text, including XML. In the simplest case, the JSP page includes static XML elements as template text and a few actions to add the dynamic data, similar to the HTML examples in previous chapters. A more sophisticated page gets raw XML data from somewhere and transforms it to different XML formats depending on the type of browser making the request.
More and more, web applications also consume XML data generated by an external source, perhaps a database or another server. Such an application may extract price information from different vendors' product catalogs, published as XML documents, and create a side-by-side comparison.
In this chapter we first look at the things you need to be aware of when generating XML responses with JSP, including device-dependent transformations, and then how to process XML data in different ways.
XML is a set of syntax rules for how to represent structured data using markup elements represented by an opening tag (optionally with attributes), a body, and a closing tag:
<employee id="123">

  <first-name>Hans</first-name>

  <last-name>Bergsten</last-name>

  <telephone>310-555-1212</telephone>

</employee>
This XML example contains four elements: <employee>, <first-name>, <last-name>, and <telephone>.
By selecting sensible element names, an XML file may be understandable to a human, but to make sense to a program, it must use only a restricted set of elements in which each element has a well-defined meaning. This is known as an XML application (the XML syntax applied to a certain application domain). A couple of examples are the Wireless Markup Language (WML) used for browsers in cellular phones and other small devices, and XHTML, which is HTML 4.0 reformulated as an XML application. Another example is the web application deployment descriptor, used to configure various aspects of a standard Java web application, as you have seen in the previous chapters.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Generating an XML Response
Inhaltsvorschau
XML is a set of syntax rules for how to represent structured data using markup elements represented by an opening tag (optionally with attributes), a body, and a closing tag:
<employee id="123">

  <first-name>Hans</first-name>

  <last-name>Bergsten</last-name>

  <telephone>310-555-1212</telephone>

</employee>
This XML example contains four elements: <employee>, <first-name>, <last-name>, and <telephone>.
By selecting sensible element names, an XML file may be understandable to a human, but to make sense to a program, it must use only a restricted set of elements in which each element has a well-defined meaning. This is known as an XML application (the XML syntax applied to a certain application domain). A couple of examples are the Wireless Markup Language (WML) used for browsers in cellular phones and other small devices, and XHTML, which is HTML 4.0 reformulated as an XML application. Another example is the web application deployment descriptor, used to configure various aspects of a standard Java web application, as you have seen in the previous chapters.
As I mentioned in Chapter 3 and Chapter 5, everything in a JSP page that is not a JSP element is template text. In all examples so far, I have used HTML as the template text, but it can be any markup, for instance XHTML or WML XML elements. Example 15-1 shows a JSP page that sends a simple phone book to a wireless device, using the XML elements defined by the WML specification as the template text.
Example 15-1. WML phone book JSP page (phone_wml.jsp)

                  <?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" 

  "http://www.wapforum.org/DTD/wml_1.1.xml">

<%@ page contentType="text/vnd.wap.wml" %>

<wml>

  <card id="list" newcontext="true">

    <p>Phone List</p>

    <p>

      <anchor>Bergsten, Hans

        <go href="#Bergsten_Hans"/>

      </anchor>

      <br/>

      <anchor>Eckstein, Bob

        <go href="#Eckstein_Bob"/>

      </anchor>

      <br/>

      <anchor>Ferguson, Paula

        <go href="#Ferguson_Paula"/>

      </anchor>

    </p>

  </card>

  

  <card id="Bergsten_Hans">

    <p>Bergsten, Hans</p>

    <p>

      Phone: 310-555-1212

      <do type="prev" label="Back">

        <prev/>

      </do>

    </p>

  </card>

  <card id="Eckstein_Bob">

    <p>Eckstein, Bob</p>

    <p>

      Phone: 800-555-5678

      <do type="prev" label="Back">

        <prev/>

      </do>

    </p>

  </card>

  <card id="Ferguson_Paula">

    <p>Ferguson, Paula</p>

    <p>

      Phone: 213-555-1234

      <do type="prev" label="Back">

        <prev/>

      </do>

    </p>

  </card>

</wml>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Transforming XML into HTML
Inhaltsvorschau
You may also have heard about the Extensible Stylesheet Language (XSL). XSL defines one set of XML elements to transform an XML document into some other type of document, and another set of elements to produce a formatted version of an XML document suitable for display. Browsers and other programs that need to render an XML document with different styles for different elements, such as a bold large font for a header and a regular font for paragraph text, use the formatting part of XSL. The transformation part of XSL is referred to as XSLT. XSLT can turn a source XML document, such as a document representing an order, into different forms using different stylesheets. This is useful in business-to-business (B2B) applications, where different partners often require the same information in slightly different formats. You can read more about XSL and XSLT at http://www.w3.org/TR/xsl/.
In a web application, XSLT can transform structured XML data into HTML. Example 15-2 shows an example of a JSP page in which the same phone book information used in Example 15-1 is transformed into an HTML table.
Example 15-2. Transforming XML to HTML (phone_html.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

<html>

  <head>

    <title>Phone List</title>

  </head>

  <body bgcolor="white">

  

    <c:import url="htmltable.xsl" var="stylesheet" />

    <x:transform xslt="${stylesheet}">

      <?xml version="1.0" encoding="ISO-8859-1"?>

      <employees>

        <employee id="123">

          <first-name>Hans</first-name>

          <last-name>Bergsten</last-name>

          <telephone>310-555-1212</telephone>

        </employee>

        <employee id="456">

          <first-name>Bob</first-name>

          <last-name>Eckstein</last-name>

          <telephone>800-555-5678</telephone>

        </employee>

        <employee id="789">

          <first-name>Paula</first-name>

          <last-name>Ferguson</last-name>

          <telephone>213-555-1234</telephone>

        </employee>

      </employees>

    </x:transform>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Transforming XML into a Device-Dependent Format
Inhaltsvorschau
A web application can use XSLT to respond with different content depending on the type of device making the request. Example 15-4 shows a page that serves both HTML and WML browsers by applying different stylesheets to the same XML document, transforming it to the appropriate markup for the browser that requests it.
Example 15-4. XSL stylesheet that generates HTML or WML (phone.jsp)

                  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" 

%><%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" 

%><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" 

%><%@ taglib prefix="ora" uri="orataglib" 

%><c:choose><c:when 

test="${fn:contains(header.Accept, 'text/vnd.wap.wml'}"

><ora:setHeader name="Content-Type" value="text/vnd.wap.wml" 

/><c:import url="wml.xsl" var="stylesheet" 

/></c:when><c:otherwise><ora:setHeader name="Content-Type" value="text/html"

/><c:import url="html.xsl" var="stylesheet" 

/></c:otherwise></c:choose><x:transform xslt="${stylesheet}">

  <?xml version="1.0" encoding="ISO-8859-1"?>

  <employees>

    <employee id="123">

      <first-name>Hans</first-name>

      <last-name>Bergsten</last-name>

      <telephone>310-555-1212</telephone>

    </employee>

    <employee id="456">

      <first-name>Bob</first-name>

      <last-name>Eckstein</last-name>

      <telephone>800-555-5678</telephone>

    </employee>

    <employee id="789">

      <first-name>Paula</first-name>

      <last-name>Ferguson</last-name>

      <telephone>213-555-1234</telephone>

    </employee>

  </employees>

</x:transform>

               
There are a number of things to note here. First, see how messy the page looks. That's because the start tag for all JSP directives and actions in this page are written on the same line as the end tag for the preceding element, to make sure that no extra linefeeds are added to the response. As described earlier, leading whitespace (such as linefeed characters) in a WML page can cause a WML browser to reject the page.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Processing XML Data
Inhaltsvorschau
XSLT is great for transforming an XML source into another format, but sometimes you need to process the XML data in other ways. For instance, you may want to use part of the XML data in a database query to get additional information and compose a response that merges the two data sources, or reformat date and numeric information in the XML source according to the user's preferred locale. To process XML data in this way, the JSTL XML library includes a number of actions for picking out pieces of an XML document, as well as iteration and conditional actions similar to the ones in the core library, but adapted to work specifically with XML data.
In this section, we look at an example that uses most of the JSTL XML actions. The XML data comes from the O'Reilly Meerkat news feed. Meerkat scans a large set of Rich Site Summary (RSS)—an XML application suitable for news, product announcements, and similar content—sources frequently and makes the aggregated data available in a number of formats, including a superset of the RSS format that includes category, source, and date information for each story. You can learn more about Meerkat and how to use it at http://www.oreillynet.com/pub/a/rss/2000/05/09/meerkat_api.html. Example 15-5 shows a sample of the XML data that Meerkat can deliver.
Example 15-5. Meerkat XML news feed format
<?xml version="1.0"?>

<!DOCTYPE meerkat_xml_flavour 

  SYSTEM "http://meerkat.oreillynet.com/dtd/meerkat_xml_flavour.dtd">

  

<meerkat>

 

  <title>Meerkat: An Open Wire Service</title> 

  <link>http://meerkat.oreillynet.com</link> 

  <description>

    Meerkat is a Web-based syndicated content reader providing

    a simple interface to RSS stories.  While maintaining the original 

    association of a story with a channel, Meerkat's focus is on 

    chronological order -- the latest stories float to the top, 

    regardless of their source.

  </description>

  <language>en-us</language> 

  

  <image> 

    <title>Meerkat Powered!</title> 

    <url>http://meerkat.oreillynet.com/icons/meerkat-powered.jpg</url>

    <link>http://meerkat.oreillynet.com</link> 

    <width>88</width> 

    <height>31</height> 

    <description>

      Visit Meerkat in full splendor at meerkat.oreillynet.com

    </description> 

  </image> 

  

  <story id="881051">

    <title>

      Clay Shirky: What Web Services Got Right ... and Wrong

    </title>

    <link>

      http://www.oreillynet.com/pub/a/network/2002/04/22/clay.html

    </link>

    <description>

      Web Services represent not just a new way to build Internet 

      applications, says Clay Shirky in this interview, but the second 

      stage of peer-to-peer, in which distinctions between clients and 

      servers are all but eliminated. 

    </description>

    <category>General</category>

    <channel>O'Reilly Network</channel>

    <timestamp>2002-04-23 17:02:50</timestamp>

  </story>

  ...

</meerkat>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 16: Using Scripting Elements
Inhaltsvorschau
Before reading this book, you may have heard that JSP is all about including Java code in web pages. If so, you may wonder why you haven't seen any Java code in the examples so far. That's because there's really no reason to embed raw Java code in JSP pages anymore. With JSP 1.0, it was the only way to do anything interesting. JSP 1.1 removed most reasons by introducing custom actions, but many developers figured developing custom actions for simple conditionals and loops was not worth the trouble and continued to embed Java code snippets for these things. Even with JSP 1.2, you still had to use Java code to assign dynamic values to JSP action element attributes, but JSTL 1.0 (and the EL it introduced) removed these excuses for most cases. With JSP 2.0, where the EL is part of the JSP specification so it can be used for all attributes and the greatly simplified mechanisms for developing custom actions, there are really no good reasons for embedding Java in your JSP pages.
JSP continues to support the scripting elements for putting code in JSP pages—even though their use is now discouraged—because all Java specifications go to great lengths to be backward compatible. There are three types of scripting elements: scriptlets for a block of code to be executed, expressions for a single statement to be evaluated with its result added to the response, and declarations for declaring variables and methods. In this chapter we look at how to use all of them, and the type of problems you should be prepared to encounter if you do.
Because using scripting elements means writing Java code, you should know how to program in Java before you read this chapter. If you don't know Java programming, my advice is that you steer clear from the scripting elements altogether and use the EL, JSTL and other custom actions exclusively.
The page directive has two attributes that may be used when you use scripting elements: language and import
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using page Directive Scripting Attributes
Inhaltsvorschau
The page directive has two attributes that may be used when you use scripting elements: language and import:
<%@ page language="java" import="java.util.*" %>
The language attribute specifies the scripting language used in the page. All containers are required to support Java. java is also the default value for the language attribute, but, for clarity, you may still want to specify it. Some JSP implementations support other languages besides Java and, hence, allow other values for the language attribute. For instance, both JRun (http://www.macromedia.com/) and Resin (http://www.caucho.com/) support JavaScript in addition to Java.
The JSP specification requires that the classes in the java.lang, javax.servlet, javax.servlet.jsp, and the javax.servlet.http packages are available by default to scripting elements when Java is used as the scripting language. If you use classes from packages other than these, they can be imported with the import attribute, to make it possible to use the short class names in the scripting elements.
If you need to import more than one package, you can use multiple page directives with import attributes in the same page or use one with a comma-separated list of import declarations. In other words, this directive:
<%@ page import="java.util.*, com.ora.jsp.util.*" %>
has the same effect as these two directives:
<%@ page import="java.util.* " %>

<%@ page import="com.ora.jsp.util.*" %>
Starting with JSP 2.0, classes without a package declaration (i.e., that are part of the unnamed package) are no longer supported. This is because the servlet the container creates from the JSP page (the page implementation class) may use a vendor-dependent package name. Java does not allow the use of classes from the unnamed package to be used in a class that belongs to a named package, and Sun's Java compiler (starting with the J2SE 1.4 version) enforces this rule.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Implicit JSP Scripting Objects
Inhaltsvorschau
Scripting elements can use predefined variables that the container assigns as references to implicit objects (Table 16-1) to access request and application data. These objects are instances of classes defined by the servlet and JSP specifications. Appendix D contains complete descriptions of all methods for each class, and they are briefly introduced here and used in a number of examples in this chapter.
Table 16-1: Implicit JSP objects
Variable name
Java type
application
javax.servlet.ServletContext
config
javax.servlet.ServletConfig
exception
java.lang.Throwable
out
javax.servlet.jsp.JspWriter
page
java.lang.Object
pageContext
javax.servlet.jsp.PageContext
request
javax.servlet.http.HttpServletRequest
response
javax.servlet.http.HttpServletResponse
session
javax.servlet.http.HttpSession
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Scriptlets
Inhaltsvorschau
The scriptlet element can be used to add a whole block of code to a page, including variable declarations. The code block must be enclosed by a scriptlet start-identifier, <%, and an end-identifier, %>. Example 16-1 shows a scriptlet that creates test data for action elements.
Example 16-1. Scriptlet creating test data (scriptlet.jsp)
<%@ page language="java" contentType="text/html" %>

<%@ page import="java.util.*" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>



<%

  // Create an ArrayList with test data

  ArrayList list = new ArrayList(  );

  Map author1 = new HashMap(  );

  author1.put("name", "John Irving");

  author1.put("id", new Integer(1));

  list.add(author1);

  Map author2 = new HashMap(  );

  author2.put("name", "William Gibson");

  author2.put("id", new Integer(2));

  list.add(author2);

  Map author3 = new HashMap(  );

  author3.put("name", "Douglas Adams");

  author3.put("id", new Integer(3));

  list.add(author3);

  pageContext.setAttribute("authors", list);

%>

<html>

  <head>

    <title>Search result: Authors</title>

  </head>

  <body bgcolor="white">

    Here are all authors matching your search critera:

    <table>

      <th>Name</th>

      <th>Id</th>

      <c:forEach items="${authors}" var="current">

        <tr>

          <td>${fn:escapeXml(current.name)}<td>

          <td>${fn:escapeXml(current.id)}<td>

        </tr>

      </c:forEach>

    </table>

  </body>

</html>
The scriptlet element contains Java code that creates a java.util.ArrayList with java.util.HashMap elements and saves the list as a page scope attribute named authors by calling the setAttribute( ) method on the implicit pageScope object. The ArrayList is then used as the items attribute value in a <c:forEach> action. You can use a scriptlet like this to test the main page functionality before the real data source is available. In the final version, the scriptlet can be removed, and the data passed to the page from another page or a servlet.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Expressions
Inhaltsvorschau
A JSP expression element is used to insert the result of a scripting code expression into the response. It's the Java scripting equivalent to an EL expression directly in template text. An expression starts with <%= and ends with %>. Note that the only syntax difference compared to a scriptlet is the equal sign (=) in the start identifier. Examples are:
<%= userInfo.getUserName(  ) %>

<%= 1 + 1 %>

<%= new java.util.Date(  ) %>
The result of the expression is written to the response body, converted to a String if needed. One thing is important to note: as opposed to statements in a scriptlet, the code in an expression must not end with a semicolon. This is because the JSP container combines the expression code with code for writing the result to the response body. If the expression ends with a semicolon, the combined code will not be syntactically correct.
As with EL expressions, a Java expression can also be used to assign a dynamic value to an action element attribute, but with a few restrictions as described later in this chapter.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Declarations
Inhaltsvorschau
I have described two of the three JSP scripting elements in this chapter so far: scriptlets and expressions. There's one more called a declaration element, which is used to declare Java variables and methods in a JSP page. My advice is this: don't use it. Let me explain why.
In general, Java variables can be declared either within a method or outside the body of all methods in a class, like this:
public class SomeClass {

  // Instance variable

  private String anInstanceVariable;

  

  // Method

  public void doSomething(  ) {

    String aLocalVariable;

  }

}
A variable declared outside the body of all methods is called an instance variable. Its value can be accessed from any method in the class, and it keeps its value even when the method that sets it returns. A variable declared within the body of a method is called a local variable; it can be accessed only within the method where it's declared. When the method returns, the local variable disappears.
Recall from Chapter 3 that a JSP page is turned into a servlet class when it's first requested, and the JSP container creates one instance of this class. If more than one user requests the same page at the same time, the single instance is used for all requests. Each user is assigned what is called a thread in the server, and each thread executes the same method in the JSP implementation class instance. When more than one thread executes the same code, you have to make sure the code is thread safe. This means that the code must behave the same when many threads are executing as when just one thread executes the code.
Multithreading and thread-safe code strategies are best left to experienced programmers. However, using a JSP declaration element to declare variables exposes your page to multithreading problems. That's because a variable that's declared using a JSP declaration element ends up as an instance variable in the generated servlet, not as a local variable in a method. All threads share the instance variable, so if one thread changes its value, the new value is seen by all threads. To put this in JSP terms, if the instance variable is changed because one user accesses the page, all users accessing the same page will use the new value.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Mixing Action Elements and Scripting Elements
Inhaltsvorschau
Even when you use custom actions and the JSTL, you may want occasionally to use small amounts of scripting code., e.g., as a quick fix or for prototyping, when creating a custom action, or an EL function seems like overkill. You can also use Java code to set an action attribute value.
In all examples so far, dynamic action attribute values are set using EL expressions, but an alternative is using a Java expression. In either case, the custom action attribute must accept what's formally called a request-time attribute value.
Here is an example of how a Java expression can be used to set the value attribute of the standard <jsp:param> action:
<jsp:forward page="prodInfo.jsp">

  <jsp:param name="id" value='<%= request.getParameter("prodId") %>' />

</jsp:forward>
The value attribute is set to the value of a request parameter. The container evaluates the request-time attribute value when the page is requested, and the corresponding attribute is set to the result of the expression. The Java type for the result of the expression must match the type of the attribute you set this way. In the <jsp:param> value attribute case, the expression must be of type String, but other action attributes may be of any type, including custom classes. This is in contrast to when an EL expression used; the container always tries to convert the EL expression evaluation result type to the attribute type, but with Java expressions it's up to you to make sure they match.
Another difference between using Java and EL expressions when assigning an attribute value is that with a Java expression, you can't combine expressions and static text as you can with EL expressions. For instance, this is illegal:
  <jsp:param name="ranking" 

    value='Ranking: <%= request.getParameter("ranking") %>' />
Instead, you have to combine the static text and the dynamic value within the expression:
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Dealing with Scripting Syntax Errors
Inhaltsvorschau
When you use scripting elements you must be prepared to deal with a new class of syntax errors. The scripting code is inserted into the servlet code, generated based on the JSP page in the translation-phase, more or less as is. A syntax error in a scripting element may therefore result in an error the JSP container can't report in a sensible way.
Directives and action elements don't have this problem. The container reads the JSP page and generates servlet code by replacing all JSP directives and action elements with code that produces the appropriate result. To do this, it needs to analyze these types of elements in detail. If there's a syntax error in a directive or action element, it can easily tell which element is incorrect (as you saw in Chapter 9). A syntax error in a scripting element, on the other hand, isn't discovered when the JSP page is read, but instead when the generated servlet is compiled with a Java compiler. The compiler reports an error in terms of its location in the generated servlet code (as opposed to the location in the JSP page), with messages that don't always make sense to a JSP page author.
Before we look at some real error examples, let's briefly look at how the scripting code is embedded in the generated servlet to really understand the problem. Example 16-5 shows a simple JSP page that uses all three scripting element types.
Example 16-5. JSP page with all scripting element types (allinone.jsp)
<%@ page language="java" contentType="text/html" %>

<%@ page import="java.util.Date" %>

<%!

  private String getGreeting(  ) {

    Date now = new Date(  );

    String greeting = null;

    if (now.getHours(  ) < 12) {

      greeting = "Good morning";

    }

    else if (now.getHours(  ) < 18) {

      greeting = "Good day";

    }

    else {

      greeting = "Good evening";

    }

    return greeting;

  }

%>

<html>

  <head>

    <title>All Scripting Elements</title>

  </head>

  <body bgcolor="white">

    <%= getGreeting(  ) %>

    <% if (request.getParameter("name") == null) { %>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 17: Bits and Pieces
Inhaltsvorschau
In the previous chapters, I have demonstrated the standard JSP features as well as the JSTL actions and a few custom actions through practical, complete examples. But some features are hard to fit nicely into these examples without losing focus, so I describe them separately in this chapter instead. Topics covered here include buffering of the response body, ways to include shared page segments, global configuration settings, using client-side code to provide a more interactive interface, preventing JSP pages from being cached, writing JSP pages as well-formed XML documents, and a discussion about the different types of URIs used in JSP pages.
There's one important thing about how a JSP page is processed that has not been covered in any example so far: buffering of the response body. As you may recall from Chapter 2, an HTTP response message contains both headers and a body. The headers tell the browser such things as what type of data the body contains (HTML text, an image), the size of the body, if the body can be cached, and so forth. Headers are also used to set cookies and to tell the browser to automatically get another page (a redirect). All response headers must be sent to the browser before the body is sent.
As soon as a JSP page writes something to the body of the message, the JSP container may start sending the response to the browser. It's then too late to set headers, since they have to be sent first. In a servlet, you have full control over when something is written to the response body, so you can make sure that you set all headers you need before you generate the body. In a JSP page, however, it's not that easy. Everything you put in a JSP page that is not a JSP element is written to the response body automatically by the JSP container. Here's the top part of the autheticate.jsp page from Chapter 13:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<%@ taglib prefix="ora" uri="orataglib" %>

  

<%-- Remove the validUser session bean, if any --%>

<c:remove var="validUser" />

...
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Buffering
Inhaltsvorschau
There's one important thing about how a JSP page is processed that has not been covered in any example so far: buffering of the response body. As you may recall from Chapter 2, an HTTP response message contains both headers and a body. The headers tell the browser such things as what type of data the body contains (HTML text, an image), the size of the body, if the body can be cached, and so forth. Headers are also used to set cookies and to tell the browser to automatically get another page (a redirect). All response headers must be sent to the browser before the body is sent.
As soon as a JSP page writes something to the body of the message, the JSP container may start sending the response to the browser. It's then too late to set headers, since they have to be sent first. In a servlet, you have full control over when something is written to the response body, so you can make sure that you set all headers you need before you generate the body. In a JSP page, however, it's not that easy. Everything you put in a JSP page that is not a JSP element is written to the response body automatically by the JSP container. Here's the top part of the autheticate.jsp page from Chapter 13:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<%@ taglib prefix="ora" uri="orataglib" %>

  

<%-- Remove the validUser session bean, if any --%>

<c:remove var="validUser" />

...
It doesn't contain any HTML, so you may think that this doesn't add anything to the response body. But it does. This page snippet contains six lines: five lines with JSP elements and one blank line. The JSP elements themselves are evaluated by the JSP container and never show up in the response, but the linefeed character at the end of each line is not a JSP element, so it's added to the response body.
Later in the same page, custom actions are used to set cookies, or in other words, set response headers:
<c:choose>

  <c:when test="${!empty param.remember}">

    <ora:addCookie name="userName" 

      value="${param.userName}"

      maxAge="2592000" />

    <ora:addCookie name="password" 

      value="${param.password}"

      maxAge="2592000" />

  </c:when>

  <c:otherwise>

    <ora:addCookie name="userName" 

      value="${param.userName}"

      maxAge="0" />

    <ora:addCookie name="password" 

      value="$param.password}"

      maxAge="0" />

  </c:otherwise>

</c:choose>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Including Page Segments
Inhaltsvorschau
You can use either a JSP directive or a standard action to include content in a JSP page. This is a useful technique when parts of all pages in an application are the same, such as headers, footers, and navigation bars.
The JSP include directive reads the content of the specified page in the translation phase (when the JSP page is converted into a servlet) and merges it with the original page:
<%@ include file="header.htmlf" %>
The file attribute is a relative path. If it starts with a slash, it's a context-relative path, interpreted relative to the context path assigned for the application. If it doesn't start with a slash, it's a page-relative path, interpreted relative to the path for the page that includes the file.
The included file can contain either only static content (such as HTML) or it can be a file with JSP elements. Its content is merged with the page that includes it, and the resulting page is converted into a servlet as described in Chapter 3. This means that the main page and all included pages share all page scope data. Scripting variables declared in JSP declarations, scriptlets, or actions, such as <jsp:useBean> or custom actions that introduce scripting variables, are also shared. Consequently, if the main page declares a variable, and the same name is used for another variable in an included page, it results in a translation phase error, because the combined page can't be compiled.
The JSP specification recommends you use a different file extension than .jsp for partial JSP pages that you include using the include directive, because they typically aren't complete, valid JSP pages. An alternative extension you can use is .jspf ("f" as in fragment, the term used for partial pages before JSP 2.0 started to use the same term for executable attribute values; the term segment is now used for partial pages, but the recommended file extensions remain). I follow this recommendation for HTML files as well and use .htmlf as the extension for static files that aren't complete HTML pages.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Global Configuration Options
Inhaltsvorschau
You can use the application deployment descriptor (web.xml) to define configuration options that apply to a group of JSP pages. These options are defined as subelements of the <jsp-property-group> element, which in turn is a subelement of the <jsp-config> element. More than one <jsp-property-group> element can be used, each with one or more nested <url-pattern> elements that associate the properties with all JSP pages that match the specified URL patterns:
<web-app>

  ...

  <jsp-config>

    <jsp-property-group>

      <url-pattern>*.jsp</url-pattern>

      ...

    </jsp-property-grop>

    <jsp-property-group>

      <url-pattern>/jsp12/*</url-pattern>

      ...

    </jsp-property-grop>

  </jsp-config>

  ...

</web-app>
With exception for automatic include properties (described later), the JSP container applies the properties only from the <jsp-property-group> with the URL pattern that most closely matches the requested page. The specified properties apply to an entire translation unit, i.e., both the main JSP page and all files it includes using the include directive (with the exception for the file encoding property, which applies to individual files).
The URL pattern format and interpretation are the same as for servlet and filter mappings, described in Chapter 19. That is, one of the following types of patterns can be used:
Exact match rule
A complete context-relative path, e.g., /admin/authenticate.jsp. This rule matches only the specific path.
Longest path prefix rule
A context-relative path with a wildcard character (*), e.g., /admin/*. This rule matches all request with the same path before the wildcard character, and if there's more than one pattern that matches, the one with the longest matching path applies.
Extension rule
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Mixing Client-Side and Server-Side Code
Inhaltsvorschau
I touched on the difference between server-side code and client-side code in Chapter 3. JSP is a server-side technology, so all JSP elements, such as actions and scriptlets, execute on the server before the resulting page is sent to the browser. A page can also contain client-side code, such as JavaScript code or Java applets, to provide a more interactive user interface. This code is executed by the browser itself.
A JSP page can generate JavaScript code dynamically the same way it generates HTML, WML, or any other type of text contents. Therefore, you can add client-side scripting code to your JSP pages. The important thing to keep in mind here is that even though you can include JavaScript code in your JSP page, the container doesn't see it as code at all. It treats it as template text and just sends it to the browser together with the rest of the response. Also remember that the only way a browser can invoke a JSP page is to send an HTTP request; there is no way that a JavaScript event handler such as onClick or onChange can directly invoke a JSP element such as an action, a scriptlet, or a Java method declared with a JSP declaration in a JSP page. A client-side script can ask the browser to make a request for a complete page, but there is no way that the script can process the response and use it to do something such as populate a selection list with the data.
Applets can make your pages more interesting and provide an easier-to-use interface than what's possible with pure HTML. As you will see, JSP includes a standard action for generating the HTML needed for embedding applets in a page in a browser-independent way.
Example 17-6 shows a modified version of the User Info page used in the examples in Chapter 10.
Example 17-6. Input form with client-side validation code (clientscript.jsp)
<%@ page contentType="text/html" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/core" %>

  

<html>

  <head>

    <title>User Info Entry Form</title>

    
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Precompiling JSP Pages
Inhaltsvorschau
To avoid hitting your site visitors with the delay caused by the conversion of a JSP page into a servlet on the first access, you can precompile all pages in the application. Another use of precompilation is if you don't want anyone to change the pages in a JSP-based application after the application has been deployed. In this case, you can precompile all pages, define URL mappings for all JSP pages in the application deployment descriptor, and install just the Java class files for the compiled pages. We look at both these scenarios in this section.
One way of precompiling all pages in an application is to simply run through the application in a development environment and make sure you hit all pages. You can then copy the class files together with all the rest of the application to the production server when you deploy the application. Where the class files are stored varies between containers. Tomcat stores all JSP page implementation classes in its work directory by default, in a subdirectory per web application. As long as the modification dates of the class files are more recent than the corresponding JSP pages, the production server uses the copied class files.
The JSP specification also defines a special request parameter that can give the JSP container a hint that the page should be compiled without letting the page process the request. An advantage of using this method is that you can automatically invoke each page, perhaps using a simple load-testing tool, without having to provide all the regular request parameters the pages use. Because the pages aren't executed, application logic that requires pages to be invoked in a certain order or enforces similar rules can't interfere with the compilation. The request parameter name is jsp_precompile, and valid values are true and false, or no value at all. In other words, the following URLs are all valid:
/ora/ch17/applet.jsp?jsp_precompile
/ora/ch17/applet.jsp?jsp_precompile=true
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Preventing Caching of JSP Pages
Inhaltsvorschau
A browser can cache web pages so that it doesn't have to get them from the server every time the user asks for them. Proxy servers can also cache pages that are frequently requested by all users going through the proxy. Caching helps cut down the network traffic and server load, and provides the user with faster responses. But caching can also cause problems in a web application in which you really want the user to see the latest version of a dynamically generated page.
Both browsers and proxy servers can be told not to cache a page by setting response headers. You can use a scriptlet like this in your JSP pages to set these headers:
<%

  response.addHeader("Pragma", "no-cache");

  response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

  response.addHeader("Cache-Control", "pre-check=0, post-check=0");

  response.setDateHeader("Expires", 0);

%>
An alternative is to use a custom action that's included with the book examples:
<%@ taglib uri="orataglib" prefix="ora" %>

<ora:noCache/>
The <ora:noCache> action sets the exact same headers as the scriptlet example, but it's cleaner.
The reason so many headers are needed is that different browsers and proxies respect different headers. The Pragma header is intended for old HTTP/1.0 clients. According to the HTTP/1. 0 specification, this header is really a request header but proxies and some browsers are known to respect it even when it's used as a response header. The Cache-Control header is an HTTP/1.1 header, so older browsers may not recognize it. The no-cache and no-store values mean that the client is not allowed to save a local copy of the page, and the must-revalidate that it must always ask the server if a new version is available. The second set of Cache-Control values are "extensions" supported by Internet Explorer, with basically the same meaning as the standard values used in the first set. The Expires header, finally, is defined by the HTTP/1.0 specification, so all browsers should recognize it. The value is the date and time when the response is no longer valid. The
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Writing JSP Pages as XML Documents
Inhaltsvorschau
An important part of JSP 2.0 is the added flexibility for writing JSP pages as well-formed, namespace-aware XML documents. Such JSP pages are referred to as JSP Documents, to distinguish them from the type of plain JSP pages described in the rest of this book. Tag files, described in Chapter 11, can also be written as XML documents. While all examples in this section show JSP Documents, you should be aware that everything said about JSP Documents also applies to tag files in XML format.
The main differences between a plain JSP page and a JSP Document are:
  • Template data and JSP elements, taken together, must form a well-formed XML document, which optionally can be validated. This means, among other things, that XML element equivalents must be used instead of the regular JSP directive and scripting elements.
  • A JSP Document is initially processed as a namespace aware XML document, meaning that standard XML entity resolution applies, page encoding determination is performed as defined by the XML specification, namespace declarations are honored and apply to both JSP elements and template data elements, XML quoting rules apply (special characters in attribute values and text nodes must be encoded), etc.
  • Whitespace is processed in the same manner as when XSLT is used to process an XML document. That is, text nodes that contain only whitespace are dropped, except for text nodes in the body of a <jsp:text> element (where whitespace is preserved).
  • An XML declaration may be generated for the response.
Prior to JSP 2.0, a JSP Document had to use <jsp:root> as its root element, making this syntax of interest primarily for validation and authoring tools. The more flexible rules introduced in JSP 2.0 extend the use of the XML syntax to other areas, such as pages used to generate any well-formed XML document and pages created with XML-aware editors.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
How URIs Are Interpreted
Inhaltsvorschau
One thing that can be confusing in a JSP-based application is the different type of URIs used in the HTML and JSP elements. The confusion stems from a combination of conflicting terms used to describe URIs in the HTTP, servlet, and JSP specifications, and the fact that some types of URIs are interpreted differently in the HTML and servlet worlds.
In HTML, URIs are used as attribute values in elements such as <a>, <img>, and <form>. JSP elements that use URI attribute values are the page, include, and taglib directives and the <jsp:forward> and <jsp:include> actions. JSTL and custom actions can also define attributes that take URI values.
The HTTP/1.1 specification (RFC 2616, with more details in RFC 2396) defines a URI as a string, following certain rules, that uniquely identifies a resource of some kind. A URL is just a special kind of URI that includes a location (such as the server name in an HTTP URL). An absolute URI is a URL that starts with the name of a so-called scheme, such as http or https, followed by a colon and then the rest of the resource identifier. An example of an absolute URI for a resource accessed through the HTTP protocol is:
http://localhost:8080/ora/ch12/login.jsp
Here http is the scheme, localhost:8080 is the location (a server name and a port number), and /ora/ch12/login.jsp is the path.
The URIs in HTML elements are interpreted by the browser. A browser needs the absolute URI to figure out how to send the requests for the resources referenced by the HTML elements. It uses the scheme to select the correct protocol and the location to know where to send the request. The path is sent as part of the request to the server, so the server can figure out which resource is requested. But when you write a URI in an HTML document, such as the action attribute of a form element or the src attribute of an image element, you don't have to specify an absolute URI if the resource is located on the same server. Instead you can use just the URI path:
<img src="/images/hello.gif">
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 18: Web Application Models
Inhaltsvorschau
Part II of this book describes how you can create many different types of applications using only JSP pages with generic components—JSTL actions, custom actions and beans—to access databases, present content in different languages, protect pages, and so forth—all without knowing much about Java programming. This approach works fine for many types of web applications, such as employee registers, product catalogs, and conference room reservation systems. But for applications with complicated schemas, intricate business rules, and tricky control flows, the generic components just don't cut it, and you suddenly find that you need a more powerful way to handle the request processing and the business logic.
As I mentioned in Chapter 3, JSP can be combined with other Java technologies such as servlets and EJB in more complex applications. In this chapter, we look at how JSP fits into this larger picture. After the brief description of the most common application models in this chapter, Chapter 19 describes the combination of servlets and JSP in detail.
The material presented in this part of the book is geared towards Java programmers. If you're not a programmer, you may still want to browse through this part to get a feel for the possibilities, but don't expect to understand everything. To really appreciate the techniques described in this part of the book, you should have experience with Java programming in general. Familiarity with Java servlets also helps, and a short introduction is included in Chapter 19 for those who are new to this technology.
At the JavaOne conference in San Francisco in June 1999, Sun Microsystems announced a new architecture for Java, with separate editions for different types of applications: the Java 2 Standard Edition (J2SE) for desktop and workstation devices; the Java 2 Micro Edition (J2ME) for small devices such as cell phones, pagers, and PDAs; and the Java 2 Enterprise Edition (J2EE) for server-based applications.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
The Java 2 Enterprise Edition Model
Inhaltsvorschau
At the JavaOne conference in San Francisco in June 1999, Sun Microsystems announced a new architecture for Java, with separate editions for different types of applications: the Java 2 Standard Edition (J2SE) for desktop and workstation devices; the Java 2 Micro Edition (J2ME) for small devices such as cell phones, pagers, and PDAs; and the Java 2 Enterprise Edition (J2EE) for server-based applications.
J2EE is a compilation of various Java APIs that have previously been offered as separate packages; an Application Programming Model (APM) (also known as the J2EE Blueprints) that describes how they can all be combined; and a test suite J2EE vendors can use to test their products for compatibility. J2EE has gone through a number of revisions since 1999, and the latest version (J2EE 1.4) includes the following enterprise-specific APIs among others:
  • JavaServer Pages (JSP)
  • Java Servlet
  • Enterprise JavaBeans (EJB)
  • Java Database Connection (JDBC)
  • Java Transaction API (JTA) and Java Transaction Service (JTS)
  • Java Naming and Directory Interface (JNDI)
  • Java Message Service (JMS)
  • Java IDL and Remote Method Invocation (RMI)
  • Java API for XML Parsing (JAXP), Java API for XML-based RPC (JAX-RPC), SOAP with Attachments API for Java (SAAJ), and Java API for XML Registries (JAXR)
  • JavaMail and JavaBeans Activation Framework (JAF)
  • J2EE Connector Architecture (JCX)
  • Java Authentication and Authorization Service (JAAS)
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
The MVC Design Model
Inhaltsvorschau
In addition to the separation of responsibilities into different tiers, J2EE also encourages the use of the Model-View-Controller (MVC) design model, briefly introduced in Chapter 3, when designing applications.
The MVC model was first described by Xerox in a number of papers published in the late 1980s in conjunction with the Smalltalk language. This model has since been used for GUI applications developed in all popular programming languages. Let's review: the basic idea is to separate the application data and business logic, the presentation of the data, and the interaction with the data into distinct entities labeled the Model, the View, and the Controller, respectively.
The Model represents pure business data and the rules for how to use this data; it knows nothing about how the data is displayed or the user interface for modifying the data. The View, on the other hand, knows all about the user interface details. It also knows about the public Model interface for reading its data, so that it can render it correctly, and it knows about the Controller interface, so it can ask the Controller to modify the Model.
Using an employee registry application as an example, an Employee class may represent a Model. It holds information about an employee: name, employment date, vacation days, salary, etc. It also holds rules for how this information can be changed; for instance, the number of vacation days may be limited based on the employment time. The user interface that shows the information is a View. It gets hold of an Employee object by asking the Controller for it and then renders the information by asking the Employee object for its property values. The View also renders controls that allow the user to modify the information. The Views sends the modification request to the Controller, which updates the Employee object and then tells the View that the Model has been modified. The View, finally, updates the user interface to display the updated values.
Using the MVC design model makes for a flexible application architecture, in which multiple presentations (Views) can be provided and easily modified, and changes in the business rules or physical representation of the data (the Model) can be made without touching any of the user interface code.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Scalability
Inhaltsvorschau
For a large, complex application, there are many reasons to move to a model that includes Enterprise JavaBeans components. But, contrary to popular belief, scalability and great performance should not be the one deciding factor. There are many ways to develop scalable applications using just JSP or the servlet/JSP combination, often with better performance than an EJB-based application, because the communication overhead between the web tier and EJB tier is avoided.
Scalability means that an application can deal with more and more users by changing the hardware configuration rather than the application itself. Typically this means, among other things, that it's partitioned into pieces that can run on separate servers. Most servlet- and JSP-based applications use a database to handle persistent data, so the database is one independent piece. They also use a mixture of static and dynamically generated content. Static content, such as images and regular HTML pages, is handled by a web server, while dynamic content is generated by the servlets and JSP pages running within a web container. So without even trying, we have three different pieces that can be deployed separately.
Initially, you can run all three pieces on the same server. However, both the web container and the database use a lot of memory. The web container needs memory to load all servlet and JSP classes, session data, and shared application information. The database server needs memory to work efficiently with prepared statements, cached indexes, statistics used for query optimization, etc. The server requirements for these two pieces are also different; for instance, the web server must be able to cope with a large number of network connections, and the database server needs fast disk access. Therefore, the first step in scaling a web application is typically to use one server for the web server and servlet container, and another for the database.
If this isn't enough, you can distribute the client requests over a set of servers processing HTTP requests. There are two common models: distributing the requests only for dynamic content (servlet and JSP requests) or distributing requests for all kinds of content.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 19: Combining JSP and Servlets
Inhaltsvorschau
As I described in the previous chapter, combining JSP with servlets lets you clearly separate the application logic from the presentation of the application; in other words, it lets you use the most appropriate component types for the roles of Model, View, and Controller. To illustrate how a servlet can act as the Controller for an application—using beans as the Model and JSP pages as Views—we redesign the Project Billboard application from Chapter 13 in this chapter. Along the way, we look at how servlets and JSP pages can share data, how to deal with references between servlets and JSP pages in a flexible manner, how to use filters and listeners, and how to handle runtime errors consistently in an application that mixes these two technologies.
Java servlets offer a powerful API that provides access to all the information about the request, the session, and the application. If you're not familiar with the Servlet API, I give you a crash course in the first section of this chapter. It's just a brief introduction, but it should be enough to get you going and to understand the rest of this chapter. If you're an old servlet pro, you may still want to scan through the last part of the introduction to learn about the new component types available in recent versions of the specification (Servlet 2.3 or later): filters and listeners. If you plan to make heavy use of servlets in your application, I recommend that you also read up on the details. You should pick up a copy of Java Servlet Programming by Jason Hunter and William Crawford (O'Reilly).
A servlet is a Java class that extends a server with functionality for processing a request and producing a response. It's implemented using the classes and interfaces defined by the Servlet API. The API consists of two packages: the javax.servlet package contains classes and interfaces that are protocol-independent, while the javax.servlet.http package provides HTTP-specific extensions and utility classes.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Servlets, Filters, and Listeners
Inhaltsvorschau
A servlet is a Java class that extends a server with functionality for processing a request and producing a response. It's implemented using the classes and interfaces defined by the Servlet API. The API consists of two packages: the javax.servlet package contains classes and interfaces that are protocol-independent, while the javax.servlet.http package provides HTTP-specific extensions and utility classes.
What makes a servlet a servlet is that the class implements an interface named javax.servlet.Servlet , either directly or by extending one of the support classes. This interface defines the methods used by the web container to manage and interact with the servlet. A servlet for processing HTTP requests typically extends the javax.servlet.http.HttpServlet class. This class implements the Servlet interface and provides additional methods suitable for HTTP processing.
The web container manages all aspects of the servlet's lifecycle. It creates an instance of the servlet class when needed, passes requests to the instance for processing, and eventually removes the instance. For an HttpServlet, the container calls the following methods at the appropriate times in the servlet lifecycle:
public void init( ) throws ServletExecption
Called once, before the first request is delivered. This method can be used to initialize the servlet's state, for instance by reading initialization parameters defined in the web application deployment descriptor and saving the values in instance variables to be used during request processing.
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Picking the Right Component Type for Each Task
Inhaltsvorschau
The Project Billboard application introduced in Chapter 13 is a fairly complex application. Half the pages are pure controller and business logic processing, it accesses a database to authenticate users, and most pages require access control. In real life, it would likely contain even more pages, for instance, pages for access to a shared document archive, time schedules, and a set of pages for administration. As the application evolves, it may become hard to maintain as a pure JSP application. It's easy to forget to include the access control code in new pages, for instance.
This is clearly an application that can benefit from using a combination of JSP pages and the component types defined by the servlet specification for the MVC roles. Let's look at the main requirements and see how we can map them to appropriate component types:
  • Database access should be abstracted, to avoid knowledge of a specific data schema or database engine in more than one part of the application: beans in the role of Model can be used to accomplish this.
  • The database access beans must be made available to all other parts of the application when it starts: an application lifecycle event listener is the perfect component type for this task.
  • Only authenticated users must be allowed to use the application: a filter can perform access control to satisfy this requirement.
  • Request processing is best done with Java code: a servlet, acting as the Controller, fits the bill.
  • It must be easy to change the presentation: this is where JSP shines, acting as the View.
Adding servlets, listeners and filters to the mix minimizes the need for complex logic in the JSP pages. Placing all this code in Java classes instead makes it possible to use a regular Java compiler and debugger to fix potential problems. Figure 19-2 shows the components of the new design.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Initializing Shared Resources Using a Listener
Inhaltsvorschau
The Project Billboard application uses two business logic beans that must be available to process requests from all users; in other words, available as application scope objects. You may remember the NewsBean from Chapter 13. This bean is the repository for all news items relating to projects, used as the source for the personalized message list. The other business logic bean is called EmployeeRegistryBean. It acts as an abstraction of the database with employee information, containing methods for user authentication and retrieving and saving employee information. The EmployeeRegistryBean class is described in more detail in Chapter 20.
Beans like this typically need to be initialized before they can be used. For instance, they may need a reference to a database or some other external data source and may create an initial information cache in memory to provide fast access even to the first request for data. You can include code for initialization of the shared resources in the servlet and JSP pages that need them, but a more modular approach is to place all this code in one place and let the other parts of the application work on the assumption that the resources are already initialized and available. An application lifecycle listener is a perfect tool for this type of resource initialization. Example 19-5 shows a listener suitable for the billboard application's needs. This type of listener implements the javax.servlet.ServletContextListener interface, with methods called by the container when the application starts and when it shuts down.
Example 19-5. Listener for application resource initialization
package com.ora.jsp.servlets;

  

import javax.servlet.*;

import javax.servlet.http.*;

import javax.sql.*;

import com.ora.jsp.beans.emp.*;

import com.ora.jsp.beans.news.*;

import com.ora.jsp.sql.*;

  

public class ResourceManagerListener implements ServletContextListener {

  

    public void contextInitialized(ServletContextEvent sce) {

  

        ServletContext application  = sce.getServletContext(  );

        String driverClass = application.getInitParameter("driverClass");

        String jdbcURL = application.getInitParameter("jdbcURL");

  

        DataSourceWrapper ds = null;

        try {

            ds = new DataSourceWrapper(  );

            ds.setDriverClassName(driverClass);

            ds.setUrl(jdbcURL);

        }

        catch (Exception e) {

            application.log("Error creating connection pool: ", e);

        } 

        EmployeeRegistryBean empReg = new EmployeeRegistryBean(  );

        empReg.setDataSource(ds);

        application.setAttribute("empReg", empReg);

  

        NewsBean news = new NewsBean(  );

        application.setAttribute("news", news);

    }

  

    public void contextDestroyed(ServletContextEvent sce) {

        ServletContext application  = sce.getServletContext(  );

        application.removeAttribute("empReg");

        application.removeAttribute("news");

    }

}
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Access Control Using a Filter
Inhaltsvorschau
The Project Billboard application uses application-controlled authentication and access control to ensure that only registered users can use the application. As discussed in Chapter 13, your first choice should be to use container-controlled authentication and access control, but let's assume that, in this case, there are valid reasons for going at it on our own.
Not all requests require a user to be logged in. For instance, if the login form and authentication request are protected, you're faced with a Catch 22; it's impossible to log in because you have to be logged in to load the login form. It's also reasonable to accept a log-out request from a user who isn't logged in; the session that contains the authentication information may have timed out before the user tries to log out.
You can use the URI path to distinguish between requests that need access control and those that don't. In this application, all requests that need access control include the /protected path element, as shown in Table 19-1.
Table 19-1: Project Billboard context-relative URI paths
Context-relative path
Resource
/ch19/login.jsp
The login JSP page
/ch19/protected/main.jsp
The main JSP page
/ch19/protected/enterMsg.jsp
The message entry form JSP page
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Centralized Request Processing Using a Servlet
Inhaltsvorschau
With resource initialization and access control out of the way, delegated to appropriate component types, we can focus on the implementation of the main application logic.
We have already decided to use a servlet as a Controller. With a servlet as the common entry point for all application requests, you gain control over the page flow of the application. The servlet can decide which type of response to generate depending on the outcome of the requested action, such as returning a common error page for all requests that fail, or different responses depending on the type of client making the request. With the help from some utility classes, it can also provide services such as input validation, I18N preparations, and in general, encourage a more streamlined approach to request handling.
When you use a servlet as a Controller, you must deal with the following basic requirements:
  • All processing requests must be passed to the single Controller servlet.
  • The servlet must be able to distinguish requests for different types of processing.
Here are other features you may want to support, even though they may not be requirements for all applications:
  • A strategy for extending the application to support new types of processing requests in a flexible manner
  • A mechanism for changing the page flow of the application without modifying code
You can, of course, develop a servlet that fulfills these requirements yourself, but there are servlets available as open source that do all of this and more. In this chapter, I describe how to use the servlet from the Apache Struts project (http://jakarta.apache.org/struts/), Version 1.0.2. It's probably the most popular framework for integration with JSP, and its servlet satisfies all our requirements. Using Struts gives you the following benefits:
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using a Common JSP Error Page
Inhaltsvorschau
Before we end the exploration of the combination of JSP and servlets, I'd like to give you one more useful tip, namely how to use a JSP error page that displays a user-friendly error page for all runtime errors, no matter if they originate in a JSP page, a servlet, or a filter.
In Chapter 9, I showed you how to use the page directive's errorPage attribute to specify a JSP page that is invoked in case an exception is thrown while processing the page. I also mentioned that an alternative is to declare an error page in the deployment descriptor (the WEB-INF/web.xml file). It's then used for exceptions thrown by a servlet, a filter, or a JSP page that doesn't declare an error page:
<error-page>

  <exception-type>java.lang.Throwable</exception-type>

  <location>/errorpage.jsp</location>

</error-page>
To recap, the <exception-type> element contains the fully qualified name of the type of exception you want to handle with the servlet, JSP page, or static page specified by the <location> element. The <location> value must be a context-relative path (starting with a slash). You can use multiple <error-page> elements to use different pages for different exceptions, and the container picks the one with the <exception-type> element that most closely matches the type of the exception thrown.
You can also define a custom handler for response status codes other than 200 (i.e., status codes that signal some kind of problem):
<error-page>

  <error-code>404</error-code>

  <location>/notfound.jsp</location>

</error-page>
If you use a JSP page as the handler, it has access to the all information about the request that failed and the reason (the exception or status code) through the properties of the pageContext.errorData variable, as described in Chapter 9. Prior to JSP 2.0, you had to work around a mismatch between the JSP and servlet specifications in order to access exception information in an error handling JSP page: the name of the request attributes used to pass on this information differed between the specifications. Fortunately, the JSP 2.0 specification is aligned with the servlet specification in this regard, so now you can use a JSP page like the one described in Chapter 9 even as a global error handler, without resorting to any tricks.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 20: Developing JavaBeans Components for JSP
Inhaltsvorschau
The JavaBeans specification was developed with graphical components in mind. But JavaBeans represents a design pattern for components that also makes sense for faceless components in a server-side application. The JSP and JSTL specifications provide a number of ways to use JavaBeans components in web applications through standard actions and the JSP EL, as described in the previous chapters.
You can use JavaBeans components in a pure JSP application to structure the application and minimize the amount of logic needed in the JSP pages. In an application that uses both servlets and JSP pages, beans carry data between the two domains. By using beans with an eye towards the recommendations in the J2EE application programming model, you can also make it easier to migrate the business logic to Enterprise JavaBeans when warranted by new requirements.
In this chapter, we look at the JavaBeans model and how it applies to the type of faceless beans used for server-side applications; beans used in previous chapters will serve as examples.
JavaBeans components, or beans for short, are simply regular Java classes designed according to a set of guidelines. By following these guidelines, development tools can figure out how you intend the bean to be used and how it can be linked to other beans. The JavaBeans specification characterizes beans as classes that support:
  • Introspection so that a builder tool can analyze how a bean works
  • Customization so that, when using an application builder, a user can customize the appearance and behavior of a bean
  • Events as a simple communication metaphor than notify beans of interesting things
  • Properties, both for customization through a tool and for programmatic use
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Beans as JSP Components
Inhaltsvorschau
JavaBeans components, or beans for short, are simply regular Java classes designed according to a set of guidelines. By following these guidelines, development tools can figure out how you intend the bean to be used and how it can be linked to other beans. The JavaBeans specification characterizes beans as classes that support:
  • Introspection so that a builder tool can analyze how a bean works
  • Customization so that, when using an application builder, a user can customize the appearance and behavior of a bean
  • Events as a simple communication metaphor than notify beans of interesting things
  • Properties, both for customization through a tool and for programmatic use
  • Persistence, so that a bean can be customized in an application builder and then have its state saved away and reloaded later
Introspection means that information about a class, such as details about its methods and their parameters and return types, can be discovered by another class. By following certain naming conventions for the methods, the external class can figure out how the bean class is intended to be used. Specifically, the beans properties and the events it generates or observes can be found using the Java Introspection API. For GUI beans, a builder tool uses introspection to discover the bean's properties and present them to the user in a property window where they can be modified. In a JSP scenario, the JSP standard actions and the EL evaluator use introspection to find the methods for reading or writing property values and to declare variables of appropriate types.
A property is an attribute of a bean that can be read or written by the bean's client through regular methods named according to the JavaBeans guidelines. Typically, the property value is represented by an instance variable in the bean, but a read-only property can also represent a value that's calculated at runtime. The property methods are used to customize the bean; for instance, you can set the label text for a bean used as a button in a GUI application or set the name of the data source for a faceless server-side bean. Besides property access methods, a bean class can have regular methods that perform actions such as saving the bean's properties in a database or sending a mail composed from its properties.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
JSP Bean Examples
Inhaltsvorschau
In a JSP-based application, two types of beans are primarily used: value beans and utility beans. A value bean encapsulates all information about some entity, such as a user or a product. A utility bean performs some action, such as saving information in a database or sending email. Utility beans can use value beans as input or produce value beans as a result of an action.
If you develop beans for your application, you're also preparing for migration to a full-blown J2EE application. The utility beans can be changed into proxies for one or more EJB session beans, acting as part of the Controller for the application.
Value beans may act as what are called Value Objects in the J2EE Blueprints. In an EJB-based application, the application's data is represented by EJB entity beans. Getting a property value from an EJB entity bean requires a remote call, consuming both system resources and bandwidth. Instead of making a remote call for each property value that is needed, the web component can make one remote call to an EJB session bean (possibly via a JSP utility bean) that returns all properties of interest packaged as a value bean. The web component can then get all the properties from the value bean with inexpensive local calls. The value bean can also act as cache in the web container to minimize remote calls even more, and it can combine information from multiple EJB entity beans that is meaningful to the web interface. If you plan to move to the EJB model eventually, I encourage you to read the J2EE Blueprint papers (http://java.sun.com/blueprints/enterprise/index.html) before you design your application to make the migration as smooth as possible.
Value beans are useful even without EJB. They are handy for capturing form input, because the <jsp:setProperty> JSP action automatically sets all properties with names corresponding to request parameter names, as described in Chapter 8. In addition, the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Unexpected <jsp:setProperty> Behavior
Inhaltsvorschau
The <jsp:setProperty> action can automatically set all properties in a bean with names matching the names of the parameters received with the request. This is a great feature that's used in many of the examples in this book, but unless you know how it works behind the scenes, you can be in for a surprise.
When the <jsp:setProperty> code is invoked, it gets a list of all request parameter names and uses bean introspection to find the corresponding property setter methods. It then calls all setter methods to set the properties to the values of the parameters. This means that if you have a property in your bean that doesn't match a parameter, the setter method for this property is not called. In most cases, this is not surprising. If the parameter is present in some requests but not in others, however, things may get a bit confusing. This is the case with parameters corresponding to checkbox, radio button, and selection list elements in an HTML form. If this type of element is selected, the browser sends a parameter with the element's name and the value of the selected item. If the element is not selected, it doesn't send a parameter at all.
For example, let's say you have a bean with an indexed property, such as the projects property in the com.ora.jsp.beans.emp.EmployeeBean used in Chapter 13. This bean is kept in the session scope. The user can change the value of the property through a group of checkboxes in a form. To unregister all projects, the user deselects all checkboxes and submits the form. You may think the following code would then clear the property (setting it to null):
<jsp:setProperty name="validUser" property="*" />
Yet it doesn't. Without any checkbox selections, the projects parameter is not sent, and the corresponding property setter method is not called. This is so even if you explicitly specify the property and request parameter names:
<jsp:setProperty name="validUser" property="projects" param="projects" />
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 21: Developing Custom Tag Libraries Using Java
Inhaltsvorschau
Custom actions let you encapsulate logic and make it available to page authors in a familiar format. Throughout this book, JSTL actions and a number of other custom actions are used for such tasks as accessing a database, including localized content, encoding URLs, and much more. Using these actions, the amount of Java code in your JSP pages can be kept to a minimum, making your application easier to debug and maintain. However, for complex applications, these generic actions may not be enough. Perhaps you want to develop business-specific actions to access the database instead of putting SQL statements in the JSP pages. You may want to present complex data as a set of nested HTML tables with cells formatted differently depending on their values. Instead of using JSTL conditional and loop actions in the JSP page to generate this table, an application-specific custom action can be used.
In Chapter 11, I showed you how to use tag files to implement custom actions. Tag files allow nonprogrammers to develop custom actions and are also suitable for custom actions that generate a lot of markup, such as HTML tables. But custom actions can also be implemented as Java classes, and that's the focus of this chapter. A Java implementation is a good choice for very complex actions or when you need to squeeze out every ounce of performance.
To develop a custom action as a Java class, you use a set of classes and interfaces referred to in the JSP specification as the tag extension mechanism. The class that implements the behavior of a custom action is called a tag handler class. It is basically a bean, with property setter methods corresponding to the custom action element's attributes, that also implements one of four Java interfaces defined as part of the tag extension mechanism.
JSP 2.0 introduces a new type of tag handler, represented by a single interface. A tag handler of this type is referred to as a simple tag handler. Tag handlers based on the three interfaces defined by JSP 1.1 and 1.2 are still supported and are now referred to as
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Developing Simple Tag Handlers
Inhaltsvorschau
The simple tag handler is new as of JSP 2.0. Don't be fooled by the name; a simple tag handler can implement complex behavior for a custom action, such as conditional evaluation of its body, iteration over its body any number of times, and processing of the body evaluation result. The name refers to the implementation task, which is indeed much simpler than it was for the type of tag handlers supported in previous versions of the JSP specification.
The simplifications are made possible by prohibiting the use of scripting elements (Java code) in the custom action's body. This would have been met with a great deal of resistance not too long ago, but with the introduction of the EL and JSTL, you rarely (if ever) need to use scripting elements. If this restriction is not acceptable for your application, you must implement the custom action using a classic tag handler instead.
A simple tag handler implements the javax.servlet.jsp.tagext.SimpleTag interface. This interface has five methods, but most tag handlers just extend a base class named javax.servlet.jsp.tagext.SimpleTagSupport and inherit implementations of all but one method: doTag( ) . In addition, the tag handler must implement standard JavaBeans setter methods for all of its custom action attributes (if it has any, of course).
As you may recall, a tag library is a collection of custom actions. For instance, all custom actions used in this book are packaged as one tag library. Besides the tag-handler class files, a tag library contains a Tag Library Descriptor (TLD) file. This is an XML file that maps all custom action names to the corresponding tag handlers and describes all attributes supported by each custom action. The class files and the TLD can be packaged in a JAR file to make installation easier. We look at the TLD syntax and packaging details at the end of this chapter.
Before getting into all the intricate details, let's use a simple example to see what it takes to develop, deploy, and use a custom action using a simple tag handler. First, you implement the tag handler class:
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Developing Classic Tag Handlers
Inhaltsvorschau
Classic tag handler is the designation used in the JSP 2.0 specification for the original version of the tag handler API, to distinguish it from the new, easier-to-use API. Given that a simple tag handler is so much easier to implement than a classic tag handler and can do exactly the same things, why bother with the classic tag handler at all? The answer is "you shouldn't," unless one of the following is true:
  • The tag library must work with JSP 1.1 or 1.2 as well as 2.0
  • The page author must be able to use Java code (scripting elements) in the custom action bodies
  • The tag handler instance is very expensive to create or initialize
It is hard to do anything about the first reason; if the tag library must work with JSP versions prior to 2.0, you have no choice but to use classic tag handlers.
Scripting code is rarely needed nowadays, so the second reason should be looked at with suspicion. I suggest that you think long and hard about other solutions, such as using JSTL, more custom actions, and EL expressions instead.
The third reason is related to the fact that simple tag handlers cannot be reused; the container creates a new instance for every invocation. A container is, however, allowed to reuse classic tag handlers for multiple custom action invocations, as long as the strict rules (described later) are followed. While this may sound like a great performance boost, benchmarks have shown that it has very little effect in reality when using a modern Java version (J2SE 1.4 or later). In most cases, the cost of maintaining the pool eats up most of the gain from reduced object creation, since modern Java versions are pretty good at dealing with short-lived objects. Reuse can make a difference with an efficient pool for tag handlers that use resources that are very expensive to create but can be retained between multiple invocations, but these are very rare. A workaround is to maintain the resources as scoped variables instead, created by the first tag handler instance and reused by all others.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Developing Tag Library Functions
Inhaltsvorschau
Besides tag handlers, a tag library can also contain EL functions. An EL function is implemented as a static method in a regular Java class. There are no special interfaces to implement or any special conventions to follow; any static method will do.
Example 21-12 shows a class with static methods for converting between degrees in Celsius and Fahrenheit.
Example 21-12. A class with static methods that can be used as EL functions
package com.ora.jsp.util;



public class TempConverter {

    public static double toCelsius(double fahrenheit) {

        return (fahrenheit - 32) * 5 / 9;

    }



    public static double toFahrenheit(double celsius) {

        return celsius * 9 / 5 + 32;

    }

}
The toCelsius( ) method takes a degree in Fahrenheit as its single argument and returns the corresponding Celsius value, and toFahrenheit( ) does the reverse.
To make these methods accessible as EL functions, they must be declared in the TLD for the tag library. We'll look at the details in the next section, but here's the bare minimum you need to add:
...

  <function>

    <name>toCelsius</name>

    <function-class>com.ora.jsp.util.TempConverter</function-class>

    <function-signature>double toCelsius(double)</function-signature>

  </function>



  <function>

    <name>toFahrenheit</name>

    <function-class>com.ora.jsp.util.TempConverter</function-class>

    <function-signature>double toFahrenheit(double)</function-signature>

  </function>

...
Each function is declared by three mandatory elements. The <name> element declares the function name to use in an EL expression. It doesn't have to match the method name, but it often does. The <function-class> element contains the fully qualified class name for the class containing the static method, and the <function-signature> element contains the method signature. It's declared as a return type (a primitive type or a fully qualified class name), the method name, and a comma-separated list of the argument types.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Creating the Tag Library Descriptor
Inhaltsvorschau
Now you have a good idea about what the Java classes for tag library functions and both simple and classic tag handlers looks like. When the JSP container processes a page, it converts EL functions and custom action elements into code that creates and calls the correct classes. To do this, it needs information about which tag handler implements which custom action element, and which Java method corresponds to an EL function. It gets this information from the Tag Library Descriptor (TLD). As you will see in Chapter 22, the JSP container also uses the TLD information to verify that the attribute list for an action element is correct.
The TLD is an XML file with information about all custom actions and functions in a library. A JSP page that uses a custom tag library must identify the corresponding TLD and the namespace prefix used for the actions and functions in the page with the taglib directive:
<%@ taglib prefix="ora" uri="orataglib" %>

...

<ora:addCookie name="userName" value="${param.userName}" />

...

${ora:toCelsius(param.f)}
The uri attribute identifies the TLD, in one of several ways that I describe later in this section. The prefix attribute assigns a prefix to use for the action elements and functions included in the library.
The JSP container then uses the TLD to find the information it needs to generate code for invoking the correct class when it encounters action elements and functions with a matching prefix.
Example 21-13 shows a part of the JSP 2.0 version of the TLD for the custom actions in this book. Some changes were made to the format of the TLD between JSP 2.0 and JSP 1.2, as well as between JSP 1.1 and 1.2; I describe the differences at the end of this section. A JSP 2.0 container is required to accept a TLD in the JSP 1.1 and 1.2 formats as well.
Example 21-13. Tag Library Descriptor (TLD)
<?xml version="1.0" encoding="ISO-8859-1" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"

  version="2.0">



  <description>

    A tag library for the examples in the O'Reilly JSP book

  </description>

  <tlib-version>3.0</tlib-version>

  <short-name>ora</short-name>

  <uri>orataglib</uri>

  

  <tag>

    <description>

       Processes the patterns specified as attributes to render a

       calendar for the specified month.

    </description>

    <name>calendar</name>

    <tag-class>com.ora.jsp.tags.MonthCalendarTag</tag-class>

    <body-content>empty</body-content>



    <attribute>

      <name>date</name>

      <required>true</required>

      <rtexprvalue>true</rtexprvalue>

    </attribute>

    ...

    <attribute>

      <description>

        A fragment used as a pattern for days in the previuous and following

        months, evaluated to get full weeks.

      </description>

      <name>padPattern</name>

      <required>false</required>

      <fragment>true</fragment>

    </attribute>

    ...

  </tag>

  ...

  <function>

    <description>

       Converts from Fahrenheit to Celsius

    </description>

    <name>toCelsius</name>

    <function-class>com.ora.jsp.util.TempConverter</function-class>

    <function-signature>double toCelsius(double)</function-signature>

  </function>

  ...

</taglib>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Packaging and Installing a Tag Library
Inhaltsvorschau
There are basically two ways the files that make up a tag library (the TLD and all the class files) can be made available to a container: packaged in a JAR file or kept as regular files directly in the web application structure in a WAR file (or the filesystem for most containers). On top of this, there are three ways to identify the tag library you use in a JSP page. Let's look at the topics one at a time.
During development, you may want to let the tag library classes and the TLD file reside as is in the filesystem, since it makes it easy to change the TLD and modify and recompile the classes. Just make sure the class files are stored in a directory that's part of the classpath for the JSP container, such as the WEB-INF/classes directory for the web application. The TLD must also be available as a file with a .tld extension in a directory where the JSP container can find it. The recommended location is the WEB-INF/tlds directory.
When you're done with the development, you may want to package all class files and the TLD in a JAR file. This makes it easier to install the library in an application. In this case, the TLD must be placed as a file with a .tld extension in the META-INF directory in the JAR file, for instance as META-INF/taglib.tld. Tag files, if any, must be stored under META-INF/tags, and the TLD must point to the exact location.
To create the JAR file, first arrange the files in a directory with a structure like this:
META-INF/

  taglib.tld

  tags/

    mytags/

      copyright.tag

      forEvenAndOdd.tag

com/

  ora/

    jsp/

      tags/

        AddCookieTag.class

        ...

      util/

        StringFormat.class

        ...
The structure for the class files must match the package names for your classes. I've shown a few of the classes in the tag library for this book as an example.
With the file structure in place, use the jar command to create the JAR file:
jar cvf orataglib_3_0.jar META-INF com
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 22: Advanced Custom Tag Library Features
Inhaltsvorschau
In the previous chapter, you learned how to develop basic tag handlers, such as conditional and iteration actions, with and without access to the element body. But there's a lot more that you can do. In this chapter we look at some more advanced features: how actions can cooperate, how to work with undeclared action element attributes, how to verify that actions are used correctly, how to bundle listener classes with a tag library, and how to convert text attribute values into types more appropriate for the tag handler. Most of these features work the same for both simple and classic tag handlers.
It's often necessary to develop custom actions so that they can be combined with other actions, letting them cooperate in some fashion. You have seen examples of this throughout this book. For instance, in Chapter 12, <sql:param> action elements are nested within the body of a <sql:query> action to set the values of placeholders in the SQL statement. Another example of cooperation is how the <c:forEach> action can use the query result produced by the <sql:query> action. In this section, we take a look at the cooperation techniques demonstrated by these two examples: explicit cooperation between a parent element and elements nested in its body and implicit cooperation through objects exposed as scoped variables.
Let's look at a possible implementation of the <sql:param> tag handler as one example of explicit parent-child cooperation. As you may recall from Chapter 12, this action can be nested within the body of either an <sql:query> or an <sql:update> action:
<sql:update sql="UPDATE Employee SET Salary = ? WHERE EmpId = ?">

  <sql:param value="${param.newSalary}" />

  <sql:param value="${param.empId}" />

</sql:update>
How does the <sql:param> action tell the enclosing <sql:update> action about the parameter it defines? The answer to this question lies in a couple of SimpleTag and Tag
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Developing Cooperating Actions
Inhaltsvorschau
It's often necessary to develop custom actions so that they can be combined with other actions, letting them cooperate in some fashion. You have seen examples of this throughout this book. For instance, in Chapter 12, <sql:param> action elements are nested within the body of a <sql:query> action to set the values of placeholders in the SQL statement. Another example of cooperation is how the <c:forEach> action can use the query result produced by the <sql:query> action. In this section, we take a look at the cooperation techniques demonstrated by these two examples: explicit cooperation between a parent element and elements nested in its body and implicit cooperation through objects exposed as scoped variables.
Let's look at a possible implementation of the <sql:param> tag handler as one example of explicit parent-child cooperation. As you may recall from Chapter 12, this action can be nested within the body of either an <sql:query> or an <sql:update> action:
<sql:update sql="UPDATE Employee SET Salary = ? WHERE EmpId = ?">

  <sql:param value="${param.newSalary}" />

  <sql:param value="${param.empId}" />

</sql:update>
How does the <sql:param> action tell the enclosing <sql:update> action about the parameter it defines? The answer to this question lies in a couple of SimpleTag and Tag interface methods that I didn't cover in Chapter 21, plus a utility method implemented by both the SimpleTagSupport class and the TagSupport class.
The interface methods are setParent( ) and getParent( ), implemented like this by the TagSupport class:
...

private Tag parent;

...

public void setParent(Tag t) {

    parent = t;

}



public Tag getParent(  ) {

    return parent;

}
These two methods are standard accessor methods for the parent instance variable. The SimpleTagSupport implementation differs only in that the parent's type is JspTag—the common superclass for
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Validating Syntax
Inhaltsvorschau
It's easy to make mistakes when using custom actions in a JSP page. Everyone types the wrong attribute name now and then or forgets to specify a mandatory attribute. When custom actions depend on each other, using the cooperation techniques described earlier in this chapter, they typically need to be used in a specific order or nesting structure, and this isn't always obvious from the documentation. As a custom action developer, you have a number of tools at your disposal to help the page author find and correct errors like these.
The first tool is the TLD. The TLD contains information about the attributes each action element supports and whether a body is supported or not. The JSP container uses this information to verify that the page author uses the custom action correctly, at least in the most basic sense.
For more advanced validation, I'm afraid you have to do a bit of coding yourself. The most powerful validation tool defined by the JSP specification is the TagLibraryValidator class. You can extend this class and bundle the subclass with your tag library to validate all aspects of JSP pages that use your library. A less powerful option, but still useful in some cases, is the TagExtraInfo class. Extensions of this class can validate the use of a single custom action, for instance that optional attributes are used correctly.
The next three sections describe these validation alternatives in detail.
When the JSP container converts a JSP page to a servlet, it compares each custom action element to the specification of the action element in the TLD. First, it makes sure that the action name matches the name of an action specified in the TLD corresponding to the action element's prefix. It then looks at the attribute list in the page and compares it to the attribute specification in the TLD. If a required attribute is missing or an attribute is used in the page but not specified in the TLD, it reports it as an error so the page author can correct the mistake. It also reports an error if a body is used for a custom action that is declared to be empty.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using a Listener in a Tag Library
Inhaltsvorschau
In Chapter 19, I described how to implement various types of listener components, as specified by the Servlet API: servlet context, session and request lifecycle event listeners, session attribute modification listeners, and session activation and passivation event listeners.
If you develop custom actions that interact with a listener in some way (for instance, an action that shows the current number of active sessions maintained by the session lifecycle event listener described in Chapter 19), you can bundle the event listener with your tag library. To get the listeners registered, you just define the listener implementation classes in the TLD for your library using the <listener> element (placed after the <validator> element):
<taglib ...>

  ...

  <listener> 

    <listener-class>

      com.ora.jsp.servlets.SessionCounterListener

    </listener-class> 

  </listener>

  ...

</taglib>
When the container loads the web application, it looks through all TLDs for listener definitions and registers all listeners it finds.
You can use listeners for a number of tasks. For instance, a servlet context lifecycle event listener can initialize resources used by the custom actions in the library (such as a connection pool) when the application starts and shut them down gracefully when it stops. A session lifecycle listener can initialize new sessions or keep track of the number of active sessions.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Dynamic Attribute Values and Types
Inhaltsvorschau
Throughout this book, you've seen how action element attributes can be given dynamic values, evaluated at runtime. A dynamic attribute value can be assigned by an EL expression, a Java expression (as shown in Chapter 16), or by a <jsp:attribute> element.
Not all attributes accept dynamic values, though. To tell the container that a custom action attribute accepts a dynamic value, or a request-time attribute value as it's also called, you have to declare this fact in the TLD:
<tag>

  <name>geekContestEntry</name>

  <tag-class>com.xmp.GeekContextEntry</tag-class>

  <description>

    Saves the submitted data in the Geek Contest database.

  </description>

  

  <attribute>

    <name>yearsSinceLastVacation</name>

    <rtexprvalue>true</rtexprvalue>

  </attribute>

  <attribute>

    <name>hoursWithoutSleep</name>

    <rtexprvalue>true</rtexprvalue>

  </attribute>

  <attribute>

    <name>employersInAMonth</name>

    <rtexprvalue>true</rtexprvalue>

  </attribute>

</tag>
An <rtexprexprvalue> element with the value true enables this feature. You can then assign dynamic values to the attributes in a page like this:
<xmp:geekContestEntry

  yearsSinceLastVacation="${param.noVacation}"

  hoursWithoutSleep='<%= request.getParameter("noSleep") %>'>

  <jsp:attribute name="employersInAMonth">

     <xmp:getAvgEmployers id="${param.geekId}" />

  </jsp:attribute>

</xmp:geekContestEntry>
An EL expression assigns the value of the noVacation request parameter to the first attribute, a Java expression assigns the noSleep parameter value to the second attribute, and a <jsp:attribute> element assigns the value produced by another custom action to the third attribute.
In the tag handler, each action attribute is implemented as a property setter method that takes one argument (the value), in accordance with the JavaBeans conventions. As with regular beans, the property type for a tag handler attribute can be of any Java type, for instance an int:
public setYearsSinceLastVacation(int value) {

    yearsSinceLastVacation = value;

}
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 23: Integrating Custom Code with JSTL
Inhaltsvorschau
In addition to providing a powerful set of JSP actions, the JSTL specification also contains a number of classes and interfaces for setting defaults for the JSTL actions and for developing custom actions that integrate nicely with JSTL actions. Another component of the JSTL specification is a couple of generic tag library validators you can use to enforce policies in your application, such as preventing scripting elements and restricting the set of tag libraries that can be used.
Some of the JSTL tag libraries use default values for attributes that are not specified explicitly in the action elements, e.g., the data source to be used by the database actions and the locale used by the I18N actions. As I described in Part II, you can set these default values using context parameters in the deployment descriptor, but you can also set them dynamically using a servlet, filter, or listener. A typical example is a filter or a servlet that sets the locale based on user profile information. The term used for the dynamic settings in the JSTL spec is configuration variables, and when combined with a context parameter, it's called a configuration setting.
Each configuration setting is identified by a unique name, such as javax.servlet.jsp.jstl.fmt.locale for the default locale. This is the name you use when you set a default value through a context parameter:
<web-app ...>

  ...

  <context-param>

    <param-name>

      javax.servlet.jsp.jstl.fmt.locale

    </param-name>

    <param-value>

      en-US

    </param-value>

  </context-param>

  ...

</web-app>
The same names are used to set, read, and remove the configuration variables programmatically, using a JSTL class called javax.servlet.jsp.jstl.core.Config. It has the following fields:
public static final String FMT_LOCALE = 

    "javax.servlet.jsp.jstl.fmt.locale";

public static final String FMT_FALLBACK_LOCALE = 

    "javax.servlet.jsp.jstl.fmt.fallbackLocale";

public static final String FMT_LOCALIZATION_CONTEXT = 

    "javax.servlet.jsp.jstl.fmt.localizationContext";

public static final String FMT_TIME_ZONE = 

    "javax.servlet.jsp.jstl.fmt.timeZone";

  

public static final String SQL_DATA_SOURCE = 

    "javax.servlet.jsp.jstl.sql.dataSource";

public static final String SQL_MAX_ROWS = 

    "javax.servlet.jsp.jstl.sql.maxRows";
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Setting and Using Configuration Variables
Inhaltsvorschau
Some of the JSTL tag libraries use default values for attributes that are not specified explicitly in the action elements, e.g., the data source to be used by the database actions and the locale used by the I18N actions. As I described in Part II, you can set these default values using context parameters in the deployment descriptor, but you can also set them dynamically using a servlet, filter, or listener. A typical example is a filter or a servlet that sets the locale based on user profile information. The term used for the dynamic settings in the JSTL spec is configuration variables, and when combined with a context parameter, it's called a configuration setting.
Each configuration setting is identified by a unique name, such as javax.servlet.jsp.jstl.fmt.locale for the default locale. This is the name you use when you set a default value through a context parameter:
<web-app ...>

  ...

  <context-param>

    <param-name>

      javax.servlet.jsp.jstl.fmt.locale

    </param-name>

    <param-value>

      en-US

    </param-value>

  </context-param>

  ...

</web-app>
The same names are used to set, read, and remove the configuration variables programmatically, using a JSTL class called javax.servlet.jsp.jstl.core.Config. It has the following fields:
public static final String FMT_LOCALE = 

    "javax.servlet.jsp.jstl.fmt.locale";

public static final String FMT_FALLBACK_LOCALE = 

    "javax.servlet.jsp.jstl.fmt.fallbackLocale";

public static final String FMT_LOCALIZATION_CONTEXT = 

    "javax.servlet.jsp.jstl.fmt.localizationContext";

public static final String FMT_TIME_ZONE = 

    "javax.servlet.jsp.jstl.fmt.timeZone";

  

public static final String SQL_DATA_SOURCE = 

    "javax.servlet.jsp.jstl.sql.dataSource";

public static final String SQL_MAX_ROWS = 

    "javax.servlet.jsp.jstl.sql.maxRows";
The fields are simply constants for all variables names, to make it a bit easier to use the class.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Integrating Custom Conditional Actions
Inhaltsvorschau
The JSTL core library contains one, generic conditional action: <c:if>. This action handles all conditions that can be expressed as Boolean EL expressions, but you often need more than that. Examples from Part II of this book include: testing if a mail address has valid syntax and if the current user belongs to a specific group.
To help developing this type of conditional custom action, JSTL includes a base class called javax.servlet.jsp.jstl.core.ConditionalTagSupport :
public abstract class ConditionalTagSupport

  extends javax.servlet.jsp.tagext.TagSupport
It contains the following public methods:
protected abstract boolean condition(  ) throws JspTagException

public void setVar(String var)

public void setScope(String scope)

public int doStartTag(  ) throws JspException

public void release(  )
The doStartTag( ) implementation calls the condition( ) method and takes care of saving the result if the var and scope attributes are set.
By extending this class and providing an implementation of the condition( ) and setter methods for all attributes you need, you get a conditional action that is consistent with the semantics of the JSTL version.
Example 23-1 shows the tag handler class for <ora:ifUserInRole>, which takes advantage of this JSTL support class.
Example 23-1. Tag handler for a conditional action
package com.ora.jsp.tags;

  

import javax.servlet.http.*;

import javax.servlet.jsp.*;

import javax.servlet.jsp.jstl.core.*;

import org.apache.taglibs.standard.lang.support.*;

  

public class IfUserInRoleTag extends ConditionalTagSupport {

    private String value;

  

    public void setValue(String value) {

        this.value = value;

    }

  

    public boolean condition(  ) throws JspTagException {

        HttpServletRequest request = 

            (HttpServletRequest) pageContext.getRequest(  );

        return request.isUserInRole(value);

    }

}
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Integrating Custom Iteration Actions
Inhaltsvorschau
JSTL offers two utilities for customized iterations: a support class that can be extended for application-specific iteration actions and interfaces that actions nested in the body of an iteration action can use to get information about the iteration status.
The JSTL <c:forEach> action is so flexible that it probably covers most cases, but to help develop application-specific iteration actions when needed, JSTL provides a base class for this as well. It's named javax.servlet.jsp.jstl.core.LoopTagSupport :
public abstract class LoopTagSupport 

  extends javax.servlet.jsp.tagext.TagSupport

  implements javax.servlet.jsp.jstl.core.LoopTag,

    javax.servlet.jsp.tagext.IterationTag,

    javax.servlet.jsp.tagext.TryCatchFinally
The class has the following fields a subclass can access:
protected int begin

protected int end

protected int step

protected String itemId

protected String statusId

protected boolean beginSpecified

protected boolean endSpecified

protected boolean stepSpecified
These variables hold the value of the corresponding attributes. The variable names for the var and varStatus attributes (itemId and statusId) are, unfortunately, not in sync with the attribute names, due to an oversight when the attribute naming conventions where changed. Nobody's perfect. For the int variables, there are also boolean variables that tell whether the corresponding attributes were set.
Here are the main methods a subclass must implement:
protected abstract void prepare(  ) 

  throws javax.servlet.jsp.JspTagException

protected abstract Object next(  ) throws javax.servlet.jsp.JspTagException

protected abstract boolean hasNext(  ) 

  throws javax.servlet.jsp.JspTagException
The prepare( ) method prepares for the iteration, for instance by creating an Iterator for the collection to iterate over. The next( ) method returns the next item from the collection, and the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Integrating Custom I18N Actions
Inhaltsvorschau
The default locale, resource bundle, and time zone for the JSTL I18N actions can be specified through four configuration settings, described in Tables Table 23-1 through Table 23-4.
Table 23-1: Locale configuration setting
Variable name:
Javax.servlet.jsp.jstl.fmt.locale
Java constant:
Config.FMT_LOCALE
Java type:
String or java.util.Locale
Set by:
<fmt:setLocale>, context parameter, or custom code
Used by:
<fmt:bundle>, <fmt:setBundle>, <fmt:message>, <fmt:formatNumber>, <fmt:parseNumber>, <fmt:formatDate>, and <fmt:parseDate>
Table 23-2: Fallback locale configuration setting
Variable name:
javax.servlet.jsp.jstl.fmt.fallbackLocale
Java constant:
Config.FMT_FALLBACK_LOCALE
Java type:
String
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Integrating Custom Database Actions
Inhaltsvorschau
The JSTL database access actions look for the default values set by the configuration settings described in Tables Table 23-5 and Table 23-6.
Table 23-5: Data-source configuration setting
Variable name:
javax.servlet.jsp.jstl.sql.dataSource
Java constant:
Config.SQL_DATA_SOURCE
Java type:
String or javax.sql.DataSource
Set by:
<sql:setDataSource>, context parameter or custom code
Used by:
<sql:query>, <sql:update>, and <sql:transaction>
Table 23-6: Maximum rows configuration setting
Variable name:
javax.servlet.jsp.jstl.sql.maxRows
Java constant:
Config.SQL_MAX_ROWS
Java type:
String or Integer
Set by:
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using JSTL Tag Library Validators
Inhaltsvorschau
JSP 1.2 introduced a powerful mechanism for validation of the elements used in a page: the tag library validator described in Chapter 22. JSTL includes two generic validators you can configure and use in your application to control how scripting elements and custom tag libraries are used.
The ScriptFreeTLV class is a validator that can be configured to reject pages with scripting elements. To use it, you can include it in the TLD for your custom library or create a TLD file that defines it as the validator for a dummy library, used only for validation:
<?xml version="1.0" encoding="ISO-8859-1" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"

  version="2.0">



  <description>

    Validates JSP pages to prohibit use of scripting elements.

  </description>

  <tlib-version>1.1</tlib-version>

  <short-name>scriptfree</scriptfree>

  <uri>http://mycompany.org/taglibs/scriptfree</uri>

  

  <validator>

    <validator-class>

      javax.servlet.jsp.jstl.tlv.ScriptFreeTLV

    </validator-class>

    <init-param>

      <param-name>allowDeclarations</param-name>

      <param-value>false</param-value>

    </init-param>

    <init-param>

      <param-name>allowScriptlets</param-name>

      <param-value>false</param-value>

    </init-param>

    <init-param>

      <param-name>allowExpressions</param-name>

      <param-value>true</param-value>

    </init-param>

    <init-param>

      <param-name>allowRTExpressions</param-name>

      <param-value>true</param-value>

    </init-param>

  </validator>

</taglib>
The initialization parameters define which type of scripting elements to accept and reject. By default, all are rejected. Starting with JSP 2.0, you can disable all types of scripting elements with a configuration setting in the web.xml file. I recommend that option, but this validator is still available and can be used if you need more fine-grained control.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Chapter 24: Database Access Strategies
Inhaltsvorschau
In this final chapter, we take a closer look at the strategies for using a database in a web application that I've mentioned in the previous chapters.
In case you're new to Java database access, we start with a brief overview of the most important JDBC classes and interfaces. Next, we focus in on the JDBC Connection class and how pooling Connection objects helps to solve a number of common problems. We look at two ways to implement connection-pooling capabilities: the JDBC 2.0 way and using a JDBC 1.0 connection pool that simulates a JDBC 2.0 pool.
A connection pool can be made available to the rest of the application—servlets as well as the JSTL database access actions—in a number of ways. In this chapter we discuss the approach used in Chapter 19 (using an application event listener) in more detail, as well as an approach that's more flexible but that only works in web containers that support the Java Naming and Directory Interface (JNDI).
No matter if you use a servlet or a custom action to access the database, there are a number of JDBC details that must be handled. To help with this grunt work, we look at a generic database access bean that simplifies life and makes the result of a query easy to use. The last section contains an example of an application-specific custom action using this bean.
If you need to learn more about JDBC programming than what's covered here, I recommend that you look at the JDBC documentation online at http://java.sun.com/products/jdbc/ or read a book about JDBC, such as George Reese's Database Programming with JDBC and Java (O'Reilly) or Java Database Best Practices (O'Reilly)—which also covers how to use Java Database Objects (JDO) and Enterprise JavaBeans (EJB) for database access.
The JDBC API is a set of classes and interfaces that allows a Java application to send SQL statements to a database in a vendor-independent way. The API consists mostly of interfaces that define the methods you use in your program. Database engine vendors and third parties provide implementations of these interfaces for a specific database engine; such an implementation is called a
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
JDBC Basics
Inhaltsvorschau
The JDBC API is a set of classes and interfaces that allows a Java application to send SQL statements to a database in a vendor-independent way. The API consists mostly of interfaces that define the methods you use in your program. Database engine vendors and third parties provide implementations of these interfaces for a specific database engine; such an implementation is called a JDBC driver. This allows you to develop your program in a database-independent way and connect to a specific database engine by plugging in the appropriate JDBC driver at deployment time. There are JDBC drivers for most database engines on the market, both commercial and open source. If you can't get one from your vendor, check out Sun's list of third-party drivers at http://industry.java.sun.com/products/jdbc/drivers.
Figure 24-1 shows how the main interfaces and classes are related.
Figure 24-1: Main JDBC interfaces and classes
All JDBC core classes and interfaces belong to the java.sql package. Of the types shown in Figure 24-1, only the DriverManager is a class (part of the standard J2SE package); the rest are interfaces implemented by each unique JDBC driver.
The Driver implementation is the entry point to all the other interface implementations. When the Driver is loaded, it register itself with the DriverManager. When the JDBC application needs a connection to a database, it asks the DriverManager for one, and the DriverManager asks each registered Driver if it knows how to create connections for the requested database. When a Driver replies "yes," the DriverManager asks it for a Connection on the application's behalf; the Driver attempts to create one and return it to the application.
The Connection is another core JDBC type. Through the Connection instance, the JDBC application can create Statement
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using Connections and Connection Pools
Inhaltsvorschau
In a JDBC-based application, a lot revolves around the java.sql.Connection interface. Before any database operations can take place, the application must create a Connection to the database. It then acts as the communication channel between the application and the database, carrying the SQL statements sent by the application and the results returned by the database. A Connection is associated with a database user account to allow the database to enforce access control rules for the SQL statements submitted through the Connection. Finally, the Connection is also the boundary for database transactions. Only SQL statements executed through the same Connection can make up a transaction. A transaction consists of a number of SQL statements that must either all succeed or all fail as one atomic operation. A transaction can be committed (the changes resulting from the statements are permanently saved) or rolled back (all changes are ignored) by calling Connection methods.
In a standalone application, a Connection is typically created once and kept open until the application is shut down. This isn't surprising, since a standalone application serves only one user at a time, and all database operations initiated by a single user are typically related to each other. In a server application that deals with unrelated requests from many different users, it's not so obvious how to deal with connections. There are three things to consider: a Connection is time-consuming to create, it must be used for only one user at a time to avoid transaction clashes, and it's expensive to keep open.
Creating a Connection is an operation that can actually take a second or two to perform. Besides establishing a network connection to the database, the database engine must authenticate the user and create a context with various data structures to keep track of transactions, cached statements, results, and so forth. Creating a new Connection for each request received by the server, while simple to implement, is far too time-consuming in a high-traffic server application.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Making a Connection Pool Available to Application Components
Inhaltsvorschau
The next part of the puzzle is how to make the DataSource available to the application components that need it. In principle, there are two ways to do this. The first one—using an application scope variable—works in any type of web container, while the second one—using JNDI—is more flexible but only works in a container that supports J2EE style resource access.
One place for resources that all components in an application need access to is the application scope, corresponding to ServletContext attributes in the servlet world. As I described in Chapter 19, the most appropriate component for initialization and release of this type of shared resources is the application lifecycle listener.
The container informs an application lifecycle listener when the application is started and stopped. It can create the resource objects and make them available to other application components in its contextInitialized( ) method before any user requests are received, and release them when the application is shut down in its contextDestroyed( ) method. Finally, a listener can use configuration data (defined as context parameters in the deployment descriptor) to work in different settings. To recap, here's an application lifecycle listener similar to the one used in Chapter 19:
package com.ora.jsp.servlets;

  

import javax.servlet.*;

import javax.servlet.http.*;

import oracle.jdbc.pool.*;

  

public class ResourceManagerListener2 implements 

    ServletContextListener {

    private OracleConnectionCacheImpl ds = null;

  

    public void contextInitialized(ServletContextEvent sce) {

  

        ServletContext application  = sce.getServletContext(  );

        String jdbcURL = application.getInitParameter("jdbcURL");

        String user = application.getInitParameter("user");

        String password = application.getInitParameter("password");

        String maxLimit = application.getInitParameter("maxLimit");

  

        try {

            ds = new OracleConnectionCacheImpl(  );

            ds.setURL(jdbcURL);

            ds.setMaxLimit(Integer.parseInt(maxLimit));

            ds.setUser("scott");

            ds.setPassword("tiger");

        }

        catch (Exception e) {

            application.log("Failed to create data source: " + 

                e.getMessage(  ));

        }

        application.setAttribute("appDataSource", ds);

    }

  

    public void contextDestroyed(ServletContextEvent sce) {

        ServletContext application  = sce.getServletContext(  );

        application.removeAttribute("appDataSource");

        // Close the connections in the DataSource

        try {

            ds.close(  );

        }

        catch (java.sql.SQLException e) {}

        ds = null;

    }

}
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Using a Generic Database Bean
Inhaltsvorschau
Some consider using the JSTL database access actions in JSP pages a bad idea because so much business logic ends up in the presentation layer (the View). For a very simple application, it's no big deal, but for a more complex application it's better to move the SQL statements to some other component type. You have basically two options: move it to a Controller servlet (or an action class that the servlet delegates to), as in the Chapter 19 example, or encapsulate it in a custom action. In both cases it makes sense to add yet another abstraction layer in the form of a bean that encapsulates the SQL statements and let the servlet or tag handler access the data in a purer form. One example of such a bean is the EmployeeRegistryBean used in Chapter 19 for authentication as well as for retrieving and saving information about an employee.
When you develop this type of database access components, you can of course use the JDBC API directly. I find it handy to use a generic JDBC bean, such as the com.ora.jsp.beans.sql.SQLCommandBean described in this section. Besides taking care of a lot of the grunt work, it also converts a query result into an instance of the same class that the JSTL <sql:query> action uses to expose the result. This makes it easy to use in a JSP page that renders the result.
The SQLCommandBean has three write-only properties. Example 24-4 shows the beginning of the class file with the setter methods.
Example 24-4. SQLCommandBean property setter methods
package com.ora.jsp.beans.sql;

  

import java.util.*;

import java.sql.*;

import javax.servlet.jsp.jstl.sql.*;

  

public class SQLCommandBean {

    private Connection conn;

    private String sqlValue;

    private List values;

  

    public void setConnection(Connection conn) {

        this.conn = conn;

    }

    

    public void setSqlValue(String sqlValue) {

        this.sqlValue = sqlValue;

    }

    

    public void setValues(List values) {

        this.values = values;

    }

    ...
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Developing Application-Specific Database Components
Inhaltsvorschau
The SQLCommandBean class described in this chapter can be used for application-specific components that access a database. The bean is used like this:
SQLCommandBean sqlCommandBean = new SQLCommandBean(  );

sqlCommandBean.setConnection(dataSource.getConnection(  ));

String sql = "SELECT * FROM Employee WHERE UserName = ?");

sqlCommandBean.setSqlValue(sql);

List values = new ArrayList(  );

values.add(userName);

sqlCommandBean.setValues(values);

Result result = sqlCommandBean.executeQuery(  );
Chapter 19 includes a more advanced example of an application-specific bean (the EmployeeRegisterBean) that uses the SQLCommandBean.
You can also use these classes in your application-specific custom actions. One example is the custom action that's mentioned in Chapter 12 as an alternative to the generic database actions for inserting or updating employee information:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<%@ taglib prefix="myLib" uri="mytaglib" %>

  

               <myLib:saveEmployeeInfo dataSource="${appDataSource}" />

  

<%-- Get the new or updated data from the database --%>

<sql:query var="newEmpDbInfo"="${example}" scope="session">

  SELECT * FROM Employee 

    WHERE UserName = ?

  <sql:param value="${param.userName}" />

</sql:query>

  

<%-- Redirect to the confirmation page --%>

<c:redirect url="confirmation.jsp" />
Example 24-8 shows one way to implement this custom action.
Example 24-8. SaveEmployeeInfoTag class
package com.mycompany.tags;

  

import java.sql.*;

import java.text.*;

import java.util.*;

import javax.sql.*;

import javax.servlet.*;

import javax.servlet.jsp.*;

import javax.servlet.jsp.tagext.*;

import javax.servlet.jsp.jstl.sql.Result;

import com.ora.jsp.beans.sql.SQLCommandBean;

import com.ora.jsp.util.*;

  

public class SaveEmployeeInfoTag extends SimpleTagSupport {

    private DataSource dataSource;

    

    public void setDataSource(DataSource dataSource) {

        this.dataSource = dataSource;

    }

    

    public void doTag(  ) throws JspException {

        // Get all request parameters

        PageContext pageContext = (PageContext) jspContext;

        ServletRequest request = pageContext.getRequest(  );

        String userName = request.getParameter("userName");

        String password = request.getParameter("password");

        String firstName = request.getParameter("firstName");

        String lastName = request.getParameter("lastName");

        String dept = request.getParameter("dept");

        String empDateString = request.getParameter("empDate");

        String emailAddr = request.getParameter("emailAddr");

        if (userName == null || password == null || 

            firstName == null || lastName == null || 

            dept == null || empDateString == null ||

            emailAddr == null) {

            throw new JspException("Missing a mandatory parameter");

        }

  

        SQLCommandBean sqlCommandBean = new SQLCommandBean(  );

        if (dataSource == null) {

            throw new JspException("The data source cannot be found");

        }

  

        Connection conn = null;

        try {

            conn = dataSource.getConnection(  );

            sqlCommandBean.setConnection(conn);

            

            // Get the current info, if any

            String sqlValue =

                "SELECT * FROM Employee WHERE UserName = ?";

            List values = new ArrayList(  );

            values.add(userName);

            sqlCommandBean.setSqlValue(sqlValue);

            sqlCommandBean.setValues(values);

            Result result = sqlCommandBean.executeQuery(  );

            

            // Create values for insert/update

            values.clear(  );

            values.add(password);

            values.add(firstName);

            values.add(lastName);

            values.add(dept);

            // Must convert the String value to java.sql.Date

            java.util.Date empDate = 

                StringFormat.toDate(empDateString, "yyyy-MM-dd")

            java.sql.Date empSQLDate = 

                new java.sql.Date(empDate.getTime(  ));

            values.add(empSQLDate);

            values.add(emailAddr);

            values.add(new Timestamp(System.currentTimeMillis(  )));

            values.add(userName);

            

            if (result.getRowCount(  ) == 0) {

                // New user. Insert

                StringBuffer sb = new StringBuffer(  );

                sb.append("INSERT INTO Employee ").

                    append("(Password, FirstName, LastName, Dept, ").

                    append("EmpDate, EmailAddr, ModDate, UserName) ").

                    append("VALUES(?, ?, ?, ?, ?, ?, ?, ?)");

                sqlCommandBean.setSqlValue(sb.toString(  ));

            }

            else {

                // Existing user. Update

                StringBuffer sb = new StringBuffer(  );

                sb.append("UPDATE Employee ").

                    append("SET Password = ?, FirstName = ?, ").

                    append("LastName = ?, Dept = ?, EmpDate = ?, ").

                    append("EmailAddr = ?, ModDate = ? ").

                    append("WHERE UserName = ?");

                sqlCommandBean.setSqlValue(sb.toString(  ));

            }

            sqlCommandBean.executeUpdate(  );

        }

        catch (SQLException e) {

            throw new JspException("SQL error: " + e.getMessage(  ));

        }

        catch (ParseException e) {

            throw new JspException("Invalid empDate format: " + 

                e.getMessage(  ));

        }

        finally {

            try {

                if (conn != null) {

                    conn.close(  );

                }

            }

            catch (SQLException e) {

                // Ignore

            }

        }

    }

}
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Appendix A: JSP Elements Reference
Inhaltsvorschau
JSP defines three types of elements: directives, scripting elements, and action elements. In addition, you can define your own custom actions. This appendix contains descriptions of all standard JSP elements, as well as the general syntax rules for custom actions.
Each element is described with an overview, a syntax reference, an attribute table, and an example. The syntax reference shows all supported attributes, with optional attributes embedded in square brackets ([]). Mutually exclusive attributes are separated with vertical bars (|). For attributes that accept predefined values, all values are listed separated with vertical bars; the default value (if any) is in boldface. Italics are used for attribute values that don't have a fixed set of accepted values.

Section A.1: Directive Elements

Section A.2: Scripting Elements

Section A.3: Action Elements

Section A.4: Custom actions

Section A.5: Comments

Section A.6: Escape Characters

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Directive Elements
Inhaltsvorschau
Directive elements are used to specify information about the page itself, especially information that doesn't differ between requests for the page. The classic general directive syntax is:
<%@ directiveName 

               attr1="value1" attr2="value2" %>
The following XML equivalent syntax must be used in a JSP Document (a JSP page written in XML syntax) and can optionally be used as an alternative to the classic syntax in a regular JSP page:
<jsp:directive.directiveName 

               attr1="value1" attr2="value2" />
Only the classic syntax is shown in the detailed sections that follow.
The attribute values can be enclosed with single quotes instead of double quotes. The directive name and all attribute names are case-sensitive.
Attribute Directive
This directive can only be used in tag files. It declares the attributes the tag file supports.
Syntax
<%@ attribute name="attrName" 

  [description="description"] [required="true|false"]

  [fragment="true|false" | [type="attrDataType"] [rtexprvalue="true|false"]]

%>
Attributes
Attribute name
Default
Description
description
No default
A description of the attribute that can be presented to a page author by an authoring tool.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Scripting Elements
Inhaltsvorschau
The scripting elements let you add small pieces of code in a JSP page, such as an if statement to generate different HTML depending on some condition. The scripting code must be written in the language defined by the page directive.
Declaration
Declarations are used to declare scripting language variables or methods. The content must be a complete valid declaration in the language defined by the page directive. The JSP implicit scripting variables aren't visible in a declaration element.
When the language is Java, a variable declared by a declaration element ends up as an instance variable in the JSP page implementation class. It's therefore visible to parallel threads (requests) processing the page and needs to be handled in a thread-safe manner. A thread-safe alternative is to declare variables within a scriptlet element instead. It then becomes a local variable of the method in the page implementation class used to process each request, and isn't shared by parallel threads.
Syntax 1: In a regular JSP page
<%! declaration %>
Syntax 2: In a JSP Document (a JSP page written in XML syntax)
<jsp:declaration>declaration</jsp:declaration>
Attributes
None.
Example
<%! int globalCounter = 0; %>
Expression
An expression is used to add the result of executing a scripting expression to the response. The content between the start and the end characters must be a complete valid expression in the language defined by the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Action Elements
Inhaltsvorschau
Action elements use XML element syntax and represent components that are invoked when a client requests the JSP page. They may encapsulate functionality such as input validation using beans, database access, or passing control to another page. The JSP specification defines a few standard action elements, described in this section, and also includes a framework for developing custom action elements.
An action element consists of a start tag (optionally with attributes), a body, and an end tag. Template text and other JSP elements can be nested in the body. Here's an example:
<jsp:forward page="nextPage.jsp">

  <jsp:param name="aParam" value="aValue" />

</jsp:forward>
If the action element doesn't have a body, a shorthand notation can be used where the start tag ends with "/>" instead of ">", as shown by the <jsp:param> action in this example. The action element name and attribute names are case-sensitive.
Some standard action attributes accept a request-time attribute value (marked with "Yes" in the "Dynamic value accepted" column in the Attributes table for each action that follows). For such an attribute, the value can be specified as an EL or Java expression, or by a <jsp:attribute> element:
<% String headerPage = currentTemplateDir + "/header.jsp"; %>

<%-- Using a Java expression --%>

<jsp:include page="<%= headerPage %>" />



<% pageContext.setAttribute("scopedVar", headerPage);



<%-- Using an EL expression --%>

<jsp:include page="${scopedVar}" />



<%-- Using a <jsp:attribute> element --%>

<jsp:include>

  <jsp:attribute name="page">

    ${scopedVar}

  </jsp:attribute>

</jsp:include>
The attribute descriptions for each action in this section define whether a request-time attribute value is accepted or not.
<jsp:attribute>
The <jsp:attribute> element defines an attribute value for another JSP action element, as an alternative to entering the attribute value as a regular XML attribute value in the opening tag or to define fragment input. It can also be used in conjunction with the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Custom actions
Inhaltsvorschau
A custom action can be developed by a programmer to extend the JSP language. The JSP Standard Tag Library (JSTL) actions are developed using the API defined by the JSP specification. Application-specific custom actions can also be developed using this API, such as the custom actions for adding cookies to a response and setting headers for no caching used in this book. The JSTL actions are described in Appendix B and all custom actions of a generic nature used in this book are described in Appendix E.
The general syntax for custom actions is the same as for the JSP standard actions: a start tag (optionally with attributes), a body, and an end tag. Other elements and template text can be nested in the body. Here's an example:
<ora:ifUserInRole value="admin">

  Greetings Master, I hope your day has been pleasant.

</ora:ifUserInRole>
The tag library containing the custom actions must be declared by the taglib directive, assigning a prefix for the custom action elements (ora in this example), before a custom action can be used in a JSP page.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Comments
Inhaltsvorschau
You can use JSP comments in JSP pages to describe what a scripting element or action is doing:
<%-- This is a comment --%>
All text between the start and stop tag is ignored by the JSP container and isn't included in the response. The comment text can be anything except the character sequence representing the closing tag: --%>.
Besides describing what's going on in the JSP page, comments can also be used to "comment out" portions of the JSP page, for instance during testing:
<jsp:useBean id="user" class="com.mycompany.UserBean" />

<%--

               <jsp:setProperty name="user" property="*" />

               <jsp:setProperty name="user" property="modDate" 

                 value="<%= new java.util.Date(  ) %>" />

               <% boolean isValid = user.isValid(  ); %>

               --%>

            
The action and scripting elements within the comment aren't executed.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Escape Characters
Inhaltsvorschau
Because certain character sequences are used to represent start and stop tags, you sometimes need to escape a character so the container doesn't interpret it as part of a special character sequence.
In a scripting element, if you need to use the characters %> literally, you must escape the greater-than character with a backslash:
<% String msg = "Literal %\> must be escaped"; %>
To avoid the character sequence <% in template text to be interpreted as the start of a scripting element, you must escape the percent sign:
This is template text and <\% is not a start of a scriptlet.
Similarly, the dollar sign that start an EL expression must be escaped in a page where EL evaluation is enabled:
This is template text and \${this is not an EL expression}.
In an attribute value, you must use the following escapes:
attr='a value with an escaped \' single quote'

attr="a value with an escaped \" double quote"

attr="a value with an escaped \\ backslash"

attr="a value with an escaped %\> scripting end tag"

attr="a value with an escaped <\% scripting start tag"

attr="a value with an escaped \$ dollar sign"
As an alternative to escaping quote characters, you can use the &apos; and &quot; character entities.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Appendix B: JSTL Actions and API Reference
Inhaltsvorschau
This appendix contains reference material for all JSTL actions, functions, support and utility classes, and configuration settings.
The actions are described using the same conventions as for the JSP standard actions in Appendix A.

Section B.1: JSTL Library URIs and Default Prefixes

Section B.2: Core Library Actions

Section B.3: Internationalization and Formatting Actions

Section B.4: Database Access Actions

Section B.5: XML Processing Actions

Section B.6: EL Functions

Section B.7: Support and Utility Types

Section B.8: Configuration Settings

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
JSTL Library URIs and Default Prefixes
Inhaltsvorschau
The URIs and default prefixes for the JSTL libraries are listed in Table B-1.
Table B-1: URIs and prefixes for the JSTL libraries
Library
URI
Prefix
Core
http://java.sun.com/jsp/jstl/core
c
XML Processing
http://java.sun.com/jsp/jstl/xml
x
I18N Formatting
http://java.sun.com/jsp/jstl/fmt
fmt
Database Access
http://java.sun.com/jsp/jstl/sql
sql
Functions
http://java.sun.com/jsp/jstl/functions
fn
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Core Library Actions
Inhaltsvorschau
The core library contains actions for control-flow, URL manipulation, importing resources, and other general-purpose tasks.
<c:catch>
The <c:catch> action catches an exception thrown by JSP elements in its body, providing fine-grained error control. The exception can optionally be saved as a page scope variable.
Syntax
<c:catch [var="var"]>

  JSP elements

</c:catch>
Attributes
Attribute name
Java type
Dynamic value accepted
Description
var
String
No
The variable name.
Example

                     <c:catch var="importException">

  <fmt:parseDate value="${param.empDate}" dateStyle="short" />

</c:catch>

<c:if test="${importException != null}">

  <jsp:forward page="input.jsp">

    <jsp:param name="msg" value="Invalid date format" />

  </jsp:forward>

</c:if>
<c:choose>
The <c:choose> action controls the processing of nested
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Internationalization and Formatting Actions
Inhaltsvorschau
<fmt:bundle>
The <fmt:bundle> action establishes a localization context for actions in its body. The localization context contains a locale and the best match for the specified resource bundle. The locale is either the locale defined by the locale configuration setting or the best match for the user preferences specified by the Accept-Language HTTP request header.
Syntax
<fmt:bundle basename="resourceBundleBasename" [prefix="keyPrefix"]>

  JSP elements

</fmt:bundle>
Attributes
Attribute name
Java type
Dynamic value accepted
Description
basename
String
Yes
The basename for a resource bundle, see java.util.ResourceBundle for details.
prefix
String
Yes
Prefix to be prepended to keys specified for nested <fmt:message> actions.
Example
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Database Access Actions
Inhaltsvorschau
<sql:dateParam>
The <sql:dateParam> action is used as a nested action for <sql:query> and <sql:update> to supply a date and time value for a value placeholder. If a null value is provided, the value is set to SQL NULL for the placeholder. To ensure portability between different database engines, this action must be used when setting values for DATE, TIME, and TIMESTAMP columns.
The value must be of type java.util.Date or one of the SQL specific subclasses: java.sql.Date, java.sql.Time or java.sql.Timestamp. If it's a java.util.Date, the action converts it to the specified subclass.
Syntax
<sql:dateParam value="parameterValue" 

  [type="timestamp|time|date"] />
Attributes
Attribute name
Java type
Dynamic value accepted
Description
value
java.util.Date
Yes
The parameter value.
type
String
Yes
The SQL type the value should be converted to, if needed.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
XML Processing Actions
Inhaltsvorschau
<x:choose>
The <x:choose> action controls the processing of nested <x:when> and <x:otherwise> actions. It allows only the first <x:when> action with a test expression that evaluates to true to be processed, or gives the go-ahead to the single <x:otherwise> action if none do.
Syntax
<x:choose>

  <x:when> actions and optionally one <x:otherwise> action

</x:choose>
Attributes
None.
Example

                     <x:choose>

                     <x:when select="category[. = 'General']">

    <td bgcolor="lightgreen">

  </x:when>

                     <x:otherwise>

    <td>

  </x:otherwise>

                     </x:choose>

                  
<x:forEach>
The <x:forEach> action evaluates its body once for each node in an XPath expression evaluation result and sets the context node used by XPath expressions in nested actions to the current node. The current node can also be exposed to action elements in the body through a nested variable.
Syntax
<x:forEach select="XPathExpression" [var="var"] [varStatus="varStatus"]

  [begin="startIndex"] [end="stopIndex"] [step="increment"]>

  JSP elements

</x:forEach>
Attributes
Attribute name
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
EL Functions
Inhaltsvorschau
Starting with JSTL 1.1, one tag library contains a set of functions for use in EL expressions. The description of each function follows a similar pattern as the action descriptions: an overview, a syntax reference, a parameter table, and an example. The syntax reference section shows the return type, followed by the function name and the parameters in italics within parentheses.
Unless otherwise stated, a parameter value of null is treated as an empty string.
fn:contains
This function tests if a string contains a substring and returns true if it does, otherwise false.
Syntax
boolean: fn:contains(string, substring)
Parameters
Parameter name
Java type
Description
string
String
The string to test.
substring
String
The substring to look for.
Example
<c:if test="${fn:contains(header['User-Agent'], 'MSIE')}">

  Your browser claims to be Internet Explorer

</c:if>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Support and Utility Types
Inhaltsvorschau
ConditionalTagSupport
The ConditionalTagSupport class can be extended by a tag handler for a custom conditional action.
Synopsis
Class Name:
javax.servlet.jsp.jstl.core.

ConditionalTagSupport
Extends:
javax.servlet.jsp.tagext.TagSupport
Implements:
None
Methods
protected abstract boolean condition( )throws javax.servlet.jsp.tagext.JspTagException
Returns the value of test condition. This method must be implemented by the subclass.
public void setScope(String scope)
Sets the scope attribute value.
public void setVar(String var)
Sets the var attribute value.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Configuration Settings
Inhaltsvorschau
Data Source
The data-source configuration setting can be set as a String in this format, in which optional parts are embedded in brackets:

                     url [, [driver] [, [user] [, [password]]]
This type of value creates a simple DataSource without any pooling capabilities, and is intended only for prototype and low-end applications, as described in Chapter 12. It can also be set to a JNDI path for a DataSource made available by the container, or to a DataSource created by custom code, such as a servlet or listener. These options are described in detail in Chapter 24.
Details
Variable name:
javax.servlet.jsp.jstl.sql.dataSource
Java constant:
Config.SQL_DATA_SOURCE
Java type:
String or javax.sql.DataSource
Set by:
<sql:setDataSource>, context parameter or custom code
Used by:
<sql:query>, <sql:update>, and <sql:transaction>
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Appendix C: JSP Expression Language Reference
Inhaltsvorschau
This appendix contains a reference to the JSP Expression Language (EL). EL expressions can be used directly in template text and in attribute values for action attributes declared to accept request-time attribute values, for both standard and custom actions.

Section C.1: Syntax

Section C.2: Variables

Section C.3: Data Types

Section C.4: Expressions and Operators

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Syntax
Inhaltsvorschau
An EL expression starts with the ${ delimiter (a dollar sign plus a left curly brace) and ends with } (a right curly brace):
${anExpression}
When used in an attribute value, any number of EL expressions and static text parts can be combined. The attribute is set to the evaluation result of each expression converted to a String concatenated with the text parts:
<c:out value="The result of 1 + 2 + 3 is ${1 + 2 + 3}" />
If the type for the attribute is not String, the result is converted to the attribute's Java type as described later.
The language is case-sensitive. All keywords are in lowercase, and identifiers must be written with correct capitalization.
Literals represent strings, numbers, Boolean values, and the null value.
String
Enclosed with single or double quotes. A quote of the same type within the string must be escaped with backslash: \' in a string enclosed with single quotes, \" in a string enclosed with double quotes. The backslash character must be escaped as \\ in both cases.
Integer
An optional sign (+ or -) followed by digits between 0 and 9.
Floating point
The same as an Integer literal, except that a dot is used as the separator for the fractional part and that an exponent can be specified as e or E followed by an Integer literal.
Boolean
true or false.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Variables
Inhaltsvorschau
Variables are named references to data (objects), created by the application or made available implicitly by the EL. Application-specific variables can be created in many ways, for instance using the <jsp:useBean> action. They can also be created by custom actions or be passed to the JSP page by a servlet. Every object that is available in one of the JSP scopes can be used as an EL variable:
${aScopedVariable}
All information about a request and other data can be accessed through the EL implicit variables:
Variable name
Description
pageScope
A collection (a java.util.Map) of all page scope variables.
requestScope
A collection (a java.util.Map) of all request scope variables.
sessionScope
A collection (a java.util.Map) of all session scope variables.
applicationScope
A collection (a java.util.Map) of all application scope variables.
param
A collection (a java.util.Map) of all request parameter values as a single String value per parameter.
paramValues
A collection (a java.util.Map) of all request parameter values as a String array per parameter.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Data Types
Inhaltsvorschau
A variable is always of a specific Java type. Besides the standard Java types for numeric, Boolean, and text values, the EL provides special support for custom classes developed according to the JavaBeans guidelines, java.util.Map objects, java.util.List objects, and arrays.
Bean properties can be accessed using the special property accessor operator (a dot), and be nested to any length:
${aBean.aProperty.aPropertyOfTheProperty.andSoOn}
Map entries can be accessed the same way:
${aMap.aKey}
List and array elements can be accessed using the array accessor operator (square brackets):
${aList[0]}

${anArray[0]}

${anArrayOrList[anExressionWithANumbericValue]}
The array accessor operator can also access bean properties and Map entries. It must be used when the property name is determined by a subexpression, the property name is a reserved word or contains characters used for operators, such as a dot:
${aMap[param.customerName]}

${aBean['empty']}

${aMap['com.mycomp.logo']}
The EL automatically converts, or coerces, variable values and the result of an expression to the type required by an attribute or an operator:
To Java type
Conversion rule
String
null: to empty string ("").
All other types: to the corresponding String value.
Primitive number or Number
null or empty string: 0.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Expressions and Operators
Inhaltsvorschau
The combination of literal values, variables, and the following operators form an EL expression:
Operator
Precedence
Operation performed
.
1
Access a bean property or Map entry.
[]
1
Access an array or List element.
(  )
2
Group a subexpression to change the evaluation order.
? :
10
Conditional test: condition ? ifTrue : ifFalse.
+
5
Addition.
-
5
Subtraction.
-
3
Negation of a value.
*
4
Multiplication.
/ or div
4
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Appendix D: JSP API Reference
Inhaltsvorschau
Besides the JSP elements described in Appendix A, the JSP specification also defines a number of Java classes and interfaces. Instances of some of these classes are assigned to the implicit variables available to scripting elements and Expression Language (EL) expressions in a JSP page. Others are used to develop custom actions and to allow JSP container vendors to encapsulate internal implementations. This appendix describes the classes and interfaces in all these categories in the JSP 2.0 specification, as well as the classes and interfaces exposed through the JSP types defined by the Servlet 2.4 specification.

Section D.1: Implicit Variables

Section D.2: Other Servlet Types Accessible Through Implicit Variables

Section D.3: Tag Handler Types

Section D.4: Translation Time Types

Section D.5: Other JSP Types

Section D.6: Expression Language Types

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Implicit Variables
Inhaltsvorschau
The JSP specification defines a number of implicit scripting variables. Most of the implicit variables have types defined by classes and interfaces in the Servlet specification's javax.servlet.http package, but two are part of the JSP javax.servlet.jsp package and one is part of the Java core API. Scripting elements in a JSP page can use these objects to access request and response information as well as objects saved in one of the JSP scopes: page, request, session, and application.
Most of these objects are also available to EL expressions through the EL implicit variables. The detailed sections include the EL expression in the Synopsis sections where applicable.
application
The application variable contains a reference to a ServletContext instance. The ServletContext provides resources shared within a web application. It holds attribute values representing the JSP application scope. An attribute value can be an instance of any Java class. It also defines a set of methods that a JSP page or a servlet use to communicate with its container, for example, to get the MIME type of a file, dispatch requests, or write to a log file. The web container is responsible for providing an implementation of the ServletContext interface.
A ServletContext is assigned a specific URI path prefix within a web server. For example a context could be responsible for all resources under http://www.mycorp.com/catalog. All requests that start with the /catalog request path, which is known as the context path, are routed to this servlet context.
A single instance of a ServletContext is available to the all servlets and JSP pages in a web application, unless the web application indicates that it is distributable. For a distributed application, there's a single instance of the ServletContext class per application per Java Virtual Machine (JVM).
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Other Servlet Types Accessible Through Implicit Variables
Inhaltsvorschau
This section contains descriptions of the servlet API classes that methods on the objects assigned to the implicit variables can return instances of.
Cookie
A Cookie object represents an HTTP cookie—a small amount of information sent by a server to a web browser, saved by the browser, and later sent back to the server with new requests. A cookie's value can uniquely identify a client, so cookies are commonly used for session management. A cookie has a name, a single value, and optional attributes such as a comment, path and domain qualifiers, a maximum age, and a version number.
This class supports both the Version 0 (the informal specification first introduced by Netscape) and the Version 1 (formally defined by RFC 2109) cookie specifications. By default, cookies are created using Version 0 to ensure the best interoperability.
Synopsis
Class name:
javax.servlet.http.Cookie
Extends:
None
Implements:
Clonable
Implemented by:
Internal container-dependent class. Most containers use the reference implementation of the class (developed in the Apache Jakarta project)
Constructor
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Tag Handler Types
Inhaltsvorschau
The JSP specification defines a number of classes and interfaces in the javax.servlet.jsp.tagext package. These classes are used to develop tag handler classes for JSP custom actions. This section contains descriptions of each class and interface. Chapter 21 and Chapter 22 show examples of how you can use these classes and interfaces to develop custom actions.
BodyContent
The container creates an instance of the BodyContent class to encapsulate the element body of a custom action element if the corresponding tag handler implements the BodyTag interface. The container makes the BodyContent instance available to the tag handler by calling the setBodyContent( ) method, so the tag handler can process the body content.
Synopsis
Class name:
javax.servlet.jsp.tagext.BodyContent
Extends:
javax.servlet.jsp.JspWriter
Implements:
None
Implemented by:
Internal container-dependent class
Constructor
protected BodyContent(JspWriter e)
Creates a new instance with the specified
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Translation Time Types
Inhaltsvorschau
This section describes the classes and interfaces used when a JSP page is translated into an implementation class, such as the types used for the tag library validation and the types for holding information about the JSP pages, tag files, and the TLD used by the container.
FunctionInfo
The container uses the FunctionInfo class to hold information about an EL function declaration from the TLD. It's primarily intended to be used by the JSP container itself during the translation phase.
Synopsis
Class name:
javax.servlet.jsp.tagext.FunctionInfo
Extends:
None
Implements:
None
Implemented by:
Internal container-dependent class; most containers use the reference implementation of the class (developed in the Apache Jakarta project)
Constructor
public FunctionInfo(String name, String klass, String signature)
Creates a new instance.
Methods
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Other JSP Types
Inhaltsvorschau
The JSP specification defines a number of other classes and interfaces that don't fit into the categories above. The exception classes, the interface for JSP page implementation classes, and the classes that let a JSP container vendor hide implementation details are described in this section.
ErrorData
The container makes an instance of ErrorData available to JSP error pages through the PageContext for the page.
Synopsis
Class name:
javax.servlet.jsp.ErrorData
Extends:
None
Implements:
None
Implemented by:
Internal container-dependent class; most containers use the reference implementation of the class (developed in the Apache Jakarta project)
Constructor
public ErrorData(Throwable throwable, int statusCode, String uri, String name)
Creates a new instance.
Methods
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Expression Language Types
Inhaltsvorschau
The API for EL evaluation is defined in the javax.servlet.jsp.el package. The types in this package are designed without dependencies on the rest of the JSP API, to allow the EL machinery to be used in other environments besides JSP. In a JSP environment, application code should rarely use these types directly—the container takes care of all EL evaluation—but they can be used for special cases, such as code getting text that contains EL expressions from an external source.
ELException
The EL evaluator signals parsing and evaluation errors by throwing an ELException .
Synopsis
Class name:
javax.servlet.jsp.el.ELException
Extends:
Exception
Implements:
None
Implemented by:
Internal container-dependent class; most containers use the reference implementation of the class (developed in the Apache Jakarta project)
Constructors
public ELException( )
Creates a new ELException instance.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Appendix E: Book Example Custom Actions and API Reference
Inhaltsvorschau
This appendix contains reference material for all custom actions, utility classes, and beans described in this book that can be used as is in other applications.
Example code used in the book that isn't intended for reuse isn't included in this appendix. All source code for the book can, however, be downloaded either from the O'Reilly web site at http://www.oreilly.com/catalog/jserverpages3/ or from the web site dedicated to this book at http://www.TheJSPBook.com/.
The actions are described using the same conventions as for the JSP standard actions in Appendix A and the JSTL actions in Appendix B. Most of the custom actions accept request-time attribute values (EL or Java expressions), indicated by "Yes" in the "Dynamic value accepted" column in the Attribute tables.

Section E.1: Generic Custom Actions

Section E.2: Generic Utility Classes

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Generic Custom Actions
Inhaltsvorschau
<ora:addCookie>
The <ora:addCookie> action sets response headers for creating or deleting a cookie. It must be used before the response is committed, for instance before a <jsp:include> action with the flush attribute set to true.
Syntax
<ora:addCookie name="cookieName" value="cookieValue"

  [maxAge="ageInSeconds"] />
Attributes
Attribute name
Java type
Dynamic value accepted
Description
name
String
Yes
The cookie name.
value
String
Yes
The cookie value.
maxAge
String
Yes
The number of seconds before the cookie expires. Default is -1, meaning that the cookie expires when the browser is closed. Use 0 to delete the cookie from the browser.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Generic Utility Classes
Inhaltsvorschau
ConnectionPool
This class implements a connection pool. It's the same class as the ConnectionPool class described in O'Reilly's Java Servlet Programming, copied with permission from Jason Hunter. It's used by the DataSourceWrapper class to provide a JDBC 2.0 DataSource interface to the pool. It's intended only as an example; there are many implementations with more features available on the Net.
Synopsis
Class name:
com.ora.jsp.sql.ConnectionPool
Extends:
None
Implements:
None
Constructors
public ConnectionPool(String driverClassName, String dbURL, String user, String password, int initialConnections) throws java.sql.SQLException, ClassNotFoundException
Creates a connection pool for the specified JDBC URL using the specified JDBC driver class and database user and password. The specified number of connections are created before service requests.
public ConnectionPool(java.util.Properties props, int initialConnections) throws java.sql.SQLException, ClassNotFoundException
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Appendix F: Web Application Structure and Deployment Descriptor Reference
Inhaltsvorschau
A complete web application may consist of several different resources: JSP pages, servlets, applets, static HTML pages, custom tag libraries, and other Java class files. Starting with Version 2.2, the servlet specification defines a portable way to package all these resources together with a deployment descriptor that contains configuration information, such as how all the resources fit together, security requirements, etc. This appendix describes the standard file structure for a web application and how to use the deployment descriptor elements defined by the Servlet 2.4 and JSP 2.0 specifications to configure the application.

Section F.1: Web Application File Structure

Section F.2: Web Application Deployment Descriptor

Section F.3: Creating a WAR File

Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Web Application File Structure
Inhaltsvorschau
The portable distribution and deployment format for a web application defined by the servlet specification is the Web Application Archive (WAR). All Servlet 2.2-compliant servers (or later) provide tools for installing a WAR file and associate the application with a servlet context.
A WAR file has a .war file extension and can be created with the Java jar command or a ZIP utility program, such as WinZip, as described at the end of this appendix. The internal structure of the WAR file is defined by the servlet specification:
/index.html

/company/index.html

/company/contact.html

/company/phonelist.jsp

/products/searchform.html

/products/list.jsp

/images/banner.gif

/WEB-INF/web.xml

/WEB-INF/lib/bean.jar

/WEB-INF/lib/actions.jar

/WEB-INF/classes/com/mycorp/servlets/PurchaseServlet.class

/WEB-INF/classes/com/mycorp/util/MyUtils.class

...
The top level in this structure is the document root for all application web page files. This is where you place all your HTML pages, JSP pages, and image files. A browser can access all these files, using a URI starting with the context-path. For instance, if the application has been assigned the context path /sales, the URI /sales/products/list.jsp is used to access the JSP page named list.jsp in the products directory in this example.
The WEB-INF directory contains files and subdirectories for other types of resources used by the application. Files under this directory aren't directly accessible to a browser. Two WEB-INF subdirectories have special meaning: lib and classes. The lib directory contains JAR files with Java class files, for instance JavaBeans classes, custom action handler classes, and utility classes. The classes directory contains class files that are not packaged in JAR files. The web application has access automatically to all class files in the lib and classes directories (in other words, you do not have to add them to the CLASSPATH environment variable).
If you store class files in the
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Web Application Deployment Descriptor
Inhaltsvorschau
A very important file is the WEB-INF/web.xml file. It is the application deployment descriptor that contains all configuration information for the application. If your application consists only of JSP and HTML files, you typically don't need to worry about this file at all. But if the application also contains servlets or uses the container provided security mechanisms, you often need to define some configuration information in the web.xml file.
The deployment descriptor is an XML file. Starting with Servlet 2.3 and JSP 2.0, the elements it can contain and how they must be arranged are controlled by a number of XML Schema documents. The main XML Schema document, which includes the others, is available online at http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd. This XML Schema document must be referenced in the root element of the deployment description, as shown in Example F-1.
Example F-1. Java Web Application Descriptor root element
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"

  xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"

  version="2.4>

  ...

</web-app>
If you're not familiar with the intricate details of XML Schema and namespace declarations, just accept the fact that you need to enclose all other elements in the deployment descriptor within a <web-app> element exactly as shown in Example F-1.
Within the <web-app> element body, top-level elements can be included in any order. Each top-level element is described in a separate section in this appendix. The top-level elements are all optional and can be included more than once, unless otherwise stated. Most top-level elements contain other elements.
I use syntax descriptions similar to those in the other appendixes to show the rules for the elements nested within top-level elements. The nested elements must be included in the order they are listed in the syntax description. Mutually exclusive elements are separated by vertical bars (
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
Creating a WAR File
Inhaltsvorschau
A WAR file is an archive file, used to group all application files into a convenient package. A WAR file can be created with the jar command, included in the Java runtime environment, or a ZIP utility program such as WinZip. To create a WAR file, you first need to create the file structure as directories in the filesystem and place all files in the correct location as described earlier.
With the file structure in place, cd to the top-level directory for the application in the filesystem. You can then use the jar command to create the WAR file:
C:\> cd myapp

C:\myapp> jar cvf myapp_1_0.war *

            
This command creates a WAR file named myapp_1_0.war containing all files in the myapp directory. You can use any filename that makes sense for your application, but avoid spaces in the filename, because they are known to cause problems on many platforms. Including the version number for the application in the filename is a good idea, because it is helpful for the users to know which version of the application the file contains.
Ende der Inhaltsvorschau. Der weiterere Inhalt dieses Abschnitts ist hier nicht einsehbar.
	

Zurück zu JavaServer Pages


Themen

Buchreihen

Special Interest

International Sites

O'Reilly China O'Reilly USA O'Reilly Japan O'Reilly Taiwan