CONTENTS | PREV | NEXT | INDEX Designing Enterprise Applications
with the J2EETM Platform, Second Edition



4.2 Web-Tier Technologies

This section presents a quick review of Web technologies in the J2EE platform, first describing legacy technologies, and then the Web-tier component types that supersede them. Feel free to skip this section if you are already familiar with these technologies. If you need to refresh your understanding beyond what this section offers, see the J2EE Tutorial (a reference to the J2EE Tutorial is listed in "References and Resources" on page 127).


4.2.1 Traditional Web-Tier Technologies

Understanding the history of dynamic Web content generation provides a context for understanding the benefits of Web technology in the J2EE platform. The earliest versions of the World Wide Web relied on basic HTTP servers to serve static HTML pages to HTML browsers. However, it quickly became clear that dynamic content, generated on demand, would make the Web a platform for delivering applications as well as content.

Several mechanisms were developed to allow Web servers to generate content on demand, all of which can be thought of as Web server functional extensions. In this context, a Web application is simply a complex Web server extension.

Web-tier technologies in the J2EE platform provide a superset of the functionality offered by the older technologies described here. Easy migration from or seamless integration with legacy Web applications is one of the strengths of Web- tier technologies in the J2EE platform.

The earliest standard server extension mechanism was the Common Gateway Interface (CGI), which defines a type of stand-alone executable program used by a server to produce dynamic content. While CGI remains a popular option for Web applications, it has some important limitations. CGI has performance limitations, because each HTTP request to a CGI program usually results in the creation of a heavyweight process in the host operating system. CGI is also a simple interface that offers no portable support for high-level system services, such as load balancing, scalability, high availability, security, state maintenance, and resource management, making scalable CGI solutions difficult to develop and maintain. CGI's simplicity is a double-edged sword: It is easy to understand, but it does not offer many portable system services to the developer.

Some of CGI's limitation can be overcome with a server extension API, which allows developers to create libraries that generate dynamic content. Examples of such APIs include NSAPI (for Netscape servers), Apache extension modules (for Apache), and ISAPI (for Microsoft Internet Information Server). While extension libraries alleviate the overhead of CGI process creation, server extension APIs are nonportable between server vendors, locking applications into a particular vendor's API and product line. Worse, server extension libraries can compromise system stability, because an extension library crash can take down the entire server.

An improvement to server extension APIs is server-side scripting, in which a script running inside the server produces dynamic content. Fast CGI is a server-side scripting interface that replaces an operating system CGI program with a server-side CGI script. Server-side scripts that fail usually do not crash the server, because the script interpreter can easily intercede to recover from script failures. Although server-side scripts may be somewhat more portable than extension APIs, they are non-portable to the extent that they use server-specific features. Server-side scripts also do not provide uniform, portable access to high-level system services.


4.2.2 Web-Tier Technologies in the J2EE Platform

Web-tier technologies in the J2EE platform provide the benefits of server-side scripting, using compiled Java classes in a standardized, secure, and vendor-neutral environment. This section briefly describes and provides best practices for Web-tier technologies in the J2EE platform.

A Web application is a collection of Web-tier components, content, and configuration information, which operates as a single functional unit. The runtime support environment for a Web application is called a Web container. A Web application archive (.war) file contains all of the class files and resources for the Web appli-cation, along with an XML deployment descriptor file that configures the application. See Chapter 7 in particular for more on packaging and deploying Web applications.

The platform specification defines a contract between the Web container and each Web component, defining the component's lifecycle, the behavior the com-ponent must implement, and the services that the server must provide to the component.

The platform specification also defines two types of Web component technologies: Java Servlets ("servlets") and JavaServer PagesTM (JSPTM pages) technology.

A servlet is a Java class that extends a J2EE server, producing dynamic content in response to requests from the server. The server passes service requests to the servlet through the standard interface javax.servlet, which every servlet must implement.

A JSP page is an HTML page with special markup that provides customizable behavior for generating dynamic content at runtime. A JSP page is usually translated into a servlet when it is deployed. JSP technology provides a document-centric, rather than programmatic, way to specify dynamic content generation.


4.2.3 The Web Container

A J2EE Web application runs inside a J2EE server's Web container. The container manages each component's lifecycle, dispatches service requests to application components, and provides standard interfaces to context data such as session state and information about the current request.

The Web container provides a consistent interface to the components it hosts, so Web components are portable across application servers. And, because packaging and deployment of J2EE Web applications are standardized, a Web application can be deployed into any J2EE server without recompiling the code or rebuilding the application archive.

The next few sections describe Web-tier components in the J2EE platform and explain the benefits their features provide.


4.2.4 Java Servlets

A Java Servlet is a Java class that extends a J2EE-compatible Web server. Each servlet class produces dynamic content in response to service requests to one or more URLs.

Servlets offer some important benefits over earlier dynamic content generation technologies. Servlets are compiled Java classes, so they are generally faster than CGI programs or server-side scripts. Servlets are safer than extension libraries, because the Java Virtual Machine (JVM) can recover from a servlet that exits unexpectedly. Servlets are portable both at the source-code level (because of the Java Servlet specification) and at the binary level (because of the innate portability of Java bytecode). Servlets also provide a richer set of standard services than any other widely adopted server extension technology.

In addition to producing content, servlets have several features that support application structure. A developer can create classes that respond to events in a servlet's lifecycle by implementing listener interfaces. The sample application uses listener interfaces to initialize servlet data structures. A servlet can also be extended by one or more servlet filters, which are reusable classes that wrap calls to a servlet's service method, transforming the request or the response. Servlet filters can be organized into filter chains that perform successive transformations on servlet requests or responses.

Distributed servlets are more scalable than non-distributed servlets. The Web container can provide an application with load balancing and failover by migrating user sessions among cluster nodes. Distributed servlets are marked distributable in the Web application deployment descriptor. They must follow a set of restrictions beyond those required of non-distributed servlets. The additional restrictions ensure that servlet code operates properly across session migrations.

For an introduction to or review of servlets, see the section entitled "Java Servlet Technology" in The J2EE Tutorial.


4.2.5 JavaServer Pages (JSP) Technology

Most Web applications produce primarily dynamic HTML pages that, when served, change only in data values and not in basic structure. For example, all of the catalog pages in an online store may have identical structure and differ only in the items they display. JSP technology exists for producing such content.

A JSP page is a document containing fixed template text, plus special markup for including other text or executing embedded logic. The fixed template text is always served to the requester just as it appears in the page, like traditional HTML. The special markup can take one of three forms: directives, scripting elements, or custom tags (also known as "custom actions"). Directives are instructions that control the behavior of the JSP page compiler and therefore are evaluated at page compilation time. Scripting elements are blocks of Java code embedded in the JSP page between the delimiters <% and %>. Custom tags (discussed later in this section) are programmer-defined markup tags that generate dynamic content when the page is served. The JavaServer Pages specification defines a set of standard tags that are available in all platform implementations. Custom tags and scripting elements generate dynamic content that is included in a response when a page is being served.

JSP pages can specify dynamic content of any textual type, but they are primarily used for creating structured content such as HTML, XML, XHTML, and so on. JSP pages are easier to write than servlets, because they look like structured documents. JSP pages are a more natural development technology for page designers, who specialize in authoring structured documents. Although a JSP page looks to its author like a document, most J2EE implementations translate a JSP page into a servlet class when it is deployed. JSP pages are also compatible with a wide array of authoring tools that simplify page creation.

JSP pages differ from servlets in their programming model. A JSP page is primarily a document that specifies dynamic content, rather than a program that produces content. JSP page technology provides a "document-centric" alternative to "programmatic" servlets for creating dynamic, structured data.

4.2.5.1 XML JSP Page Syntax

The JSP specification defines an alternate XML syntax for JSP pages. Pages in standard JSP syntax cannot be well-formed XML because the markup does not conform to XML's requirements. Pages using the alternate JSP XML syntax can be validated against an XML Schema Definition Language (XSDL) schema to check for many potential errors that would otherwise appear only at runtime. XML syntax can also facilitate integration with development tools. For integrity, a single JSP file may not contain a mix of standard JSP syntax and XML syntax.

Writing JSP pages in XML syntax is different from using JSP pages to generate XML content. The XML JSP page syntax is a way to specify a JSP page using well-formed XML. JSP pages written in either standard or XML syntax are useful for generating dynamic XML content.

4.2.5.2 Custom Tags

JSP technology allows developers to define custom tags, which are markup tags that are replaced by dynamic content when the page is served. The dynamic content is created by a tag handler class, which a programmer creates and packages in a tag library archive file. A programmer defines the syntax for a tag and implements the tag's behavior in the handler class. Page authors can then import and use tags in tag libraries just as they use other markup tags.

Custom tags provide several benefits to a J2EE application design.

4.2.5.3 Standard Tag Libraries

Standard tag libraries are sets of custom tags that provide a basic set of domain-neutral functionality for JSP pages. Standard tags typically perform such functions as Web resource inclusion, request forwarding, conditional logic, collection iteration, XSLT transformations, internationalization, state access, and HTML forms. Some companies have produced tag libraries that are intimately integrated with their tools and J2EE product lines. Other organizations have produced tag libraries for general use in J2EE applications. Apache Taglibs, for example, is an open-source project that contains dozens of custom tags.

The Java Standard Tag Library (JSTL) is now a part of the Java Community Process (JSR-52, A Standard Tag Library for JavaServer Pages). Once standardized, JSTL will provide a rich layer of portable functionality to JSP pages. It will be available in all compliant JSP containers. See the Apache Jakarta taglib page listed in "References and Resources" on page 127 for more on JSTL.

Standard tag libraries often provide much of the basic functionality that JSP pages need. Mature libraries have been tested and optimized by a community of developers. Adopting a high-quality standard tag library can save application development time.


4.2.6 Web-Tier Technology Guidelines

This section provides guidelines for effective use of servlets and JSP pages.

4.2.6.1 Where to Use Servlets

Servlets are most effectively used for implementing logic and generating binary content.

4.2.6.1.1 Use Servlets to Implement Services

Servlets are usually not visual components, except for some that generate binary content. Instead, think of a servlet as an information service provided by an application. A servlet can perform whatever service it provides--templating, security, personalization, application control--and then select a presentation component (often a JSP page) to which it forwards the request for display. The sample application implements its templating services as a servlet (see Section 4.4.3.1 on page 110). Just as a servlet can be thought of as a service, a servlet filter can be thought of as a customization or an extension of the services that a servlet provides.

4.2.6.1.2 Use Servlets as Controllers

Servlets are the preferred technology for implementing a Web-tier controller, which determines how to handle a request and chooses the next view to display. A controller activates application operations and makes decisions, which are essentially procedural tasks that are best suited for program code in servlets.

JSP pages should not be used as controllers. Because JSP pages that are mostly logic are a mixture of markup tags and program code, they are difficult to read and maintain, especially for Web developers who are not programmers.

public class extends HttpServlet {
  protected void doPost(HttpServletRequest req,
               HttpServletResponse res) throws... {

    String creditCard = req.getParameter("creditCard");
    String jspPage = "/process" + creditCard + ".jsp";
    ServletContext sc = getServletContext();
    RequestDispatcher rd = getRequestDispatcher(jspPage);
    rd.forward(req, res);
  }
}
Code Example 4.1 A Servlet Properly Used as a Controller

Code Example 4.1 is an example of a servlet used properly as a controller. The same controller is implemented improperly as a JSP page in Code Example 4.5 on page 91. Comparing the two, the pure servlet implementation is cleaner and easier to maintain.

See also Section 4.2.6.9 on page 91.

4.2.6.1.3 Use Servlets to Generate Binary Content

Binary content should be generated by servlets. Servlets that output binary content must set the Content-Type HTTP header to the MIME type of the content being generated. A servlet writes its binary data to an OutputStream acquired from the ServletRequest, as shown in Code Example 4.2.

public class JpgWriterServlet extends HttpServlet {
  public void service(HttpServletRequest req,
              HttpServletResponse rsp) throws... {
    rsp.setHeader("Content-type", "image/jpg");
    OutputStream os = rsp.getOutputStream();
    // ... now write binary data to the OutputStream...

Code Example 4.2 A Servlet that Produces Binary Content

A servlet can write to either an OutputStream or a PrintWriter, but not both. JSP pages can't create binary content.

4.2.6.2 Avoid Writing Servlets That Print Mostly Static Text

Servlets composed mostly of println statements would be better implemented as JSP pages. JSP pages are for creating textual content that combines template data with dynamic data values. Servlets that print a great deal of text, and perform some logic between the print lines, are tedious to write and difficult to maintain. Every delimiter in the quoted strings written by the servlet must be properly escaped with a backslash, reducing readability. Updating the visual presentation of such a servlet requires modifying and recompiling a program, instead of updating a page of markup.

public class PopulateServlet extends HttpServlet {
  public void doGet(HttpServletRequest  req,
                    HttpServletResponse res) throws ... {
   ...
   if (dbConnectionClosed) {
     PrintWriter out = response.getWriter();
     out.println("<html>");
     out.println("<body bgcolor=white>");
     out.println("<font size=\"+5\" color=\"red\">Can't connect</font>");

     out.println("<br>Confirm your database is running");
     out.println("</body></html>");
   }
}

Code Example 4.3 Bad Practice: a Servlet that Prints Static Content

In Code Example 4.3, a servlet is used inappropriately to generate static content. The code is difficult to read, requires careful delimiter escaping, and would probably need a programmer for nontrivial modifications.

A better design, shown in Code Example 4.4, demonstrates a servlet that detects an error and forwards the request to a JSP page, which reports the error. This maintains proper separation of function from presentation, allowing Web developers and programmers to focus on their core skills.

PopulateServlet.java:
public class PopulateServlet extends HttpServlet {
  protected void doGet(HttpServletRequest  req,
                       HttpServletResponse res) throws ... {
    ...
   if (dbConnectionClosed) {
     ServletContext ctx = getServletContext();
     ctx.getRequestDispatcher("/db_failed.jsp").forward(req, res);
   }
}

db_failed.jsp:
<html>
 <body>
  <br><font color="red">Unable to Connect</font>
  <br>Confirm that your database is running
 </body>
<html>

Code Example 4.4 Servlet Logic that Delegates Display to a JSP Page
4.2.6.3 Use RequestDispatcher Methods forward and include Correctly

A servlet uses two RequestDispatcher methods, forward and include, to create a response using other components. However, the two methods are intended for fundamentally different operations. Use RequestDispatcher.forward to delegate processing of an entire request to another component, and use RequestDispatcher.include to build a response containing results from multiple Web resources.

When using the request dispatcher in a servlet, keep in mind that RequestDispatcher.forward requires that the body of the servlet response be empty. Writing something to the response and then calling forward either causes a runtime exception or discards any data previously written.

4.2.6.4 Where to Use JavaServer Pages

JSP pages are typically used for creating structured or free-form textual data. They are most appropriate where data values change between requests, but data structure either doesn't change, or changes very little.

4.2.6.4.1 Use JSP Pages for Data Presentation

JSP pages are most appropriately used for producing structured textual content. Enterprise application data view types typically include HTML, XHTML, and DHTML.

JSP pages are best used for content that is partially fixed, with some elements that are filled in dynamically at runtime. A JSP page contains fixed content called "template data" (not to be confused with the templating mechanism described in this chapter). Custom tags or scripting elements occur at various points in the template data, and are replaced at runtime with dynamic data, producing customized content.

JSP pages cannot create binary content. They are also usually not appropriate for creating content with highly variable structure or for controlling request routing. Servlets are better for those situations. (See Section 4.2.6.1 on page 82 for more on this topic.) JSP pages can reasonably activate business logic, if the implementation of that logic is in a custom tag instead of in a scriptlet; see Section 4.2.6.8 on page 89.

4.2.6.4.2 Use JSP Pages to Generate XML

JSP pages are an excellent technology for generating XML with fixed structure. They are particularly useful for generating XML messages in standard formats, where message tags are fixed and only attribute values or character data change each time the page is served. XML documents can also be created from templates, assembling several XML subdocuments into a composite whole.

4.2.6.4.3 Use JSP Pages to Generate Unstructured Textual Content

JSP pages are not limited to producing documents with structured markup. They can also create unstructured textual content such as ASCII text, fixed-width or delimited data, and even PostScript. For example, JSP pages would be an excellent choice for rendering personalized e-mail form letters to customers.

4.2.6.4.4 Use JSP Pages as Templates

JSP pages may also be appropriately used for assembling textual data from multiple sources, as described in Section 4.4.3.1 on page 110.

4.2.6.5 JSP Pages Character Encoding

JSP pages use class javax.servlet.jsp.JSPWriter to write content to the response stream. This class automatically ensures that any text output by the JSP page is properly encoded. But automatic encoding is also a limitation, because it means JSP pages cannot be used to produce binary content directly.

4.2.6.6 Avoid Heavy Use of Logic Tags

Standard tag libraries usually provide so-called "logic tags," which are custom tags that loop, perform iterations, evaluate expressions, and make decisions. Avoid using standard tag libraries to perform a great deal of logic in JSP pages. Using custom tags for logic provides little benefit, and violates separation of logic and presentation. JSP pages that are simply procedural programs written in XML syntax are at least as difficult to maintain as other types of programs.

Instead of creating "procedural" JSP pages, implement logic in a custom tag, servlet, or helper class. One powerful technique is to define custom tags for application logic, implementing the tag handlers using enterprise beans. A thin layer of code (the tag handler class) links the custom tag with enterprise bean lookup and method invocation. This approach provides the view (JSP page or servlet) with direct access to model data (in the enterprise beans), maintaining separation of presentation from function.

4.2.6.7 Use JSP Include Directives and Tags Appropriately

The JSP include directive and the JSP include tag have similar syntax but different purposes.

An include directive includes literal text "as is" in the JSP page and is not intended for use with content that changes at runtime. The include occurs only when the servlet implementing the JSP page is being built and compiled. For example, the following include directive includes a file at page compilation time:

<%@ include file="header.jsp" @%>

The JSP include tag includes either static or dynamic content in the JSP page when the page is being served. When used to include static content, the include tag works just the same as the include directive. But when an include tag includes dynamic content, the tag generates and includes the dynamic content in the context of the current request. The include occurs each time the JSP page is served. For example, the following JSP include tag includes dynamic content, which depends on the current request:

<jsp:include page="/servlets/currentUserInfoServlet"/>

In contrast, the JSP include directive is commonly used to modularize Web pages, to reuse content, and to keep Web page size manageable. For example, an include directive could include headers and footers on every page. Using a JSP include directive results in a larger servlet and, if abused, could lead to code bloat.

The JSP include tag is commonly used to insert dynamically generated content into a JSP page at the time it is served. An include tag is more flexible than an include directive, because it can select the content to include at runtime. But an include tag requires runtime processing, and is therefore slower than an include directive.

Each time a particular JSP page is requested, all of its included pages are evaluated and recompiled if necessary. A child page must redeclare the components it uses (for example, JavaBeans components and objects provided by the container). Pages share data by way of the HttpSession object.

The sample application uses primarily include tags, because most of its JSP pages produce dynamic content.

The include directive is problematic for internationalization, because the contentType:charset of the included page cannot be set independently of the including page. The include tag is the only choice for including content with page encoding in JSP version 1.1.

Implementation note: Some Web container implementations (including Tomcat) do not automatically track modifications to files included by an include directive. If you change a file that is included, you also need to force a recompile by "touching" (change the modification date of) the "parent" files that include the modified file.

4.2.6.8 Using Custom Tags to Avoid Scriptlets

Consider using custom tags instead of scriptlets in JSP pages for the following reasons:

Expressions sometimes also suffer from these problems, but they are somewhat less problematic than scriptlets because they tend to be small.

Custom tags maintain separation between developer roles. They encourage reuse of logic and state within a single source file. They also improve source code readability, and improve both testability and error reporting.

Some projects have Web page authors but few or no programmers. Page authors with limited programming skill can use scriptlets effectively if they use scriptlets for display logic only. Business logic should never be implemented in scriptlets.

4.2.6.9 Avoid Forwarding Requests from JSP Pages

When a JSP page calls RequestDispatcher.forward, either directly or with a custom tag, it is acting as a controller. Controllers are better implemented as servlets than as JSP pages, because controllers are logical components, not presentation components. Code Example 4.5 demonstrates a controller implemented as a JSP page.

<% String creditCard = request.getParameter("creditCard");
   if (creditCard.equals("Visa")) { %>
<jsp:forward page="/processVisa.jsp"/>
<% } else if (creditCard.equals("American Express")) { %>
<jsp:forward page="/processAmex.jsp"/>
<% } %>

Code Example 4.5 Bad Practice: JSP Page Acting as a Controller

In this example, the scriptlets and tags conditionally forward the request to another JSP page based on a request attribute. If each of the forward tags were replaced with a single line of Java code that performed the forward, the result would be a JSP page containing nothing but a scriptlet. This code would obviously be better implemented as a servlet. Code Example 4.1 on page 83 shows the code for a servlet implementation of this functionality.



CONTENTS | PREV | NEXT | INDEX
Copyright © 2002 Sun Microsystems, Inc. All Rights Reserved.