C H A P T E R  2

The Structure of Web Applications

The chapter describes the structure of web applications, including:

This chapter discusses concepts that are fundamental only to the servlet container and its web components. It also describes supporting classes and files not directly managed by the servlet container. These classes and files are logically part of the web application and are deployed together with the web components.

As shown in FIGURE 2-1, a web application runs inside a servlet container. A servlet container, in turn, is contained within a web server. Each web application consists of one or more web modules. Each web module contains presentation, controller, and model elements. The presentation element, sometimes called the view element, is the physical page users see and interact with. It can consist of either a JSP page or an HTML file. The controller element, for example, the servlet, controls what users see and how they interact. The model element contains data used by the presentation and controller elements. The data might be included in Java libraries or other resources. These resources might include GIF images, HTML files, and so forth.

 FIGURE 2-1 The Structure of a Web Application

Figure showing web application and its components contained inside servlet container and web server.[ D ]


Web Servers

A web server provides the mechanisms for clients on the Internet, intranet, or extranet to access a repository of web resources. These resources might consist of HTML pages, CGI (Common Gateway Interface) scripts, images, and so forth. The web server mechanisms include:

An HTTP request is a message created in the client browser that includes attributes and cookies from the client browser. The web server routes the request to the servlet container. Request processing can occur in a servlet, in a JSP file, and in a servlet filter. The HTTP request ends when this processing is complete.

An HTTP response is a message that is generated in the servlet container and includes cookies, headers, and output that eventually go to the client browser. Response processing can also occur in a servlet, in a JSP file, and in a servlet filter. The web server routes the response from the servlet container to the client browser.


Servlet Containers and Web Components

Web servers can provide servlet containers. Servlet containers offer runtime services to support the execution of the web components of a web application. These services include:

Servlet containers forward client requests from a web server to web components in the application. They also forward the client-bound responses from the web components back to the web server. Servlet containers typically run in a web server process as a web server plug-in or in a J2EE application server process.

Servlet containers also provide the network services over which requests and responses are sent, requests decoded, and responses formatted. All servlet containers support HTTP (Hypertext Transfer Protocol) as a protocol for requests and responses. They also might provide for additional request-response protocols such as HTTPS (Hypertext Transfer Protocol Secure Sockets).

A distributed servlet container can run a web application that is tagged as distributable. This kind of web application must execute across multiple Java virtual machines running on the same host or on different hosts. In this situation, the scope of the objects in the web application is extended. A certain amount of overhead is involved in maintaining the synchronization of the common session information among multiple servers. This overhead includes performance penalties and storage considerations. For more information, see HTTP Sessions.

Web components are server-side J2EE components. They are managed by and communicate directly with a servlet container. They are capable of receiving HTTP requests through the servlet container, processing them, and returning HTTP responses. The J2EE platform defines two web component types: servlets and JSP pages.

Servlet Context

The servlet context for a web module is an object containing the servlet's view of the web application in which it is running. It defines a set of methods that a servlet uses to communicate with its servlet container, for instance to:

A web module is represented at runtime by an object implementing the ServletContext interface. The servlet context provides web components with access to resources available within the web module. There is one servlet context per web module per Java virtual machine.

A ServletContext instance is unique within a nondistributed web module. The instance is also shared by all web components within the web module. This object is implicitly available in JSP pages as the application instance variable. This variable is always available. It does not need to be declared.

A ServletContext instance (as well as the web module it represents) is rooted at a specific path within a web server. It could, for example, be rooted at http://www.myStore.com/productList. In this case, all requests starting with the /productList context path would be routed to the ServletContext instance.


Web Modules

Web applications consist of one or more web modules. A web module is a J2EE web component. A web module might be used to implement a web-based product catalog application. Such a program might contain:

Web modules are self contained. Only the contents of a single root directory are typically required to deploy a web module to a web server.

For more information, see Web Modules in the IDE.


JSP Pages

A JSP page describes the client presentation, for example, a page displayed in a web browser, that enables your web application to interact with end users. A JSP page is translated to a servlet class within the servlet container. The JSP page describes how to process an HTTP request, and it generates an HTTP response. The JSP page's HTML-like syntax lets it focus on presentation and document issues rather than features provided by Java code. For more information on servlets, see Servlets. For details on support for JSP pages in the IDE, see Creating JSP Pages.

JSP Page Life Cycle

A JSP page is processed by its runtime environment, that is, the servlet container. The servlet container manages the creation, routing, and removal of requests and responses. Furthermore, it orchestrates the processing of requests and responses by activating the appropriate web components. The JSP page performs processing on an HTTP request and generates an HTTP response. The processes involved in this phase are JSP page translation, instantiation, request processing, and destruction.

Translation and Instantiation

JSP page translation refers to the process by which the servlet container converts a JSP file into a servlet class. The details of this process are specific to the servlet container. In the web server or servlet container, the JSP file is converted to a Java servlet source file. It is then compiled to a class file.

The servlet container translates a JSP file the first time it receives a request for it. On subsequent requests for the same JSP page, the servlet container typically bypasses this phase. Translation could occur if the date on the JSP implementation class is older than the date on the JSP file. Hence, JSP pages can be redeployed without restarting the web server. The translation process is managed by the servlet container.

After a JSP page has been translated to a servlet, it is instantiated by a call to its jspInit method. The jspInit method is typically used to prepare resources required by the JSP page.

Request Processing

In the simplest case, the JSP page receives a client request from the servlet container. It then processes the request according to its programmed logic and sends a response to the container. By default, each request executes in its own thread. Request processing can involve other components such as servlets, filters, or other JSP files that forward requests from the client.

Destruction

Servlet containers typically provide a way to limit how long a JSP instance can persist without receiving a request. After the user-specified limit, the servlet container can reclaim resources by destroying a JSP instance. Before doing so, it calls the instance's jspDestroy method, which corresponds to the jspDestroy method of the JSP file. The jspDestroy method is used to close resources that are no longer needed.

Code Constructs in JSP Pages

A JSP page can contain template data and elements. Template data consists of non-JSP constructs, such as HTML and XML code, passed through to the HTTP response word for word. Template data is generally used to provide static content and to format dynamic data. Because HTML is passed through literally, coding presentation content is very natural for a web page designer. Elements are constructs, recognized by the servlet container, that provide dynamic capabilities.

JSP elements are grouped into three categories: directive elements, action elements, and scripting elements.

Directive Elements

Directive elements provide global declarative information about a JSP page that is unrelated to any particular request. Directives are processed at translation time.

Directives are placed between <%@ and %> symbols. For example, the following page directive imports the java.util package and associates the JSP page with the current error page.

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

TABLE 2-1 describes the directives defined in the JSP specification:

TABLE 2-1 JSP Directives

JSP Directive

Description

page

Imports classes, sets session participation, and selects an error page

taglib

Identifies a tag library so that its tags can be used within a JSP file

include

Includes another file within a JSP file


Action Elements

Action elements are XML-style tags that provide a means of working with Java objects without writing Java code. For example, you can use actions to locate and instantiate objects, and to get and set an object's properties. Actions are processed at request time, that is, when the request is received by the servlet container. Some actions write output to the HTTP response.

Standard actions are implemented by the servlet container.

TABLE 2-2 describes JSP standard actions defined by the JSP specification.

TABLE 2-2 JSP Standard Actions

Standard Action

Description

forward

Immediately sends the processing of the request to another resource, including JSP pages, servlets, HTML pages, and so forth

include

Subsumes another file within this JSP file. The name of the included file can be computed at request time.

useBean

Identifies a bean that can be accessed from the JSP file

getProperty

Gets the value of a property from a bean associated with the JSP file through the useBean action

setProperty

Sets the value of a property in a bean associated with the JSP file through the useBean action

plugin

Enables the Java plug-in to be loaded in the client browser. If necessary, it executes an embedded applet or JavaBeans component.


The JSP specification also supports the development of custom actions to provide features not available through standard actions. Custom actions are implemented by creating or importing tag libraries. See Tag Libraries for more information.

Because actions use XML syntax, they provide web page designers with a familiar paradigm for working with dynamic data. Web page designers might not code actions themselves. However, they need to understand enough to work in a file containing actions. Web page designers might have to provide HTML template data for actions that produce output to a web page.

Scripting Elements

Scripting elements enable you to embed Java code within a JSP file. These elements can then be used for programming logic and for writing output to the HTTP response. Scripting elements are executed on the web server. The response page sent to the client displays only the result of the scripting element code. By contrast, JavaScript is routed through the server and returned to the client for processing.

Three syntactically distinct types of scripting elements are described in this section: declarations, expressions, and scriptlets.

Declarations help you declare and initialize variables, instantiate objects, and declare methods. Declarations are processed at translation time and do not write output to the HTTP response. Declarations are placed between <%! and %> symbols. The following example declares and initializes two String variables:


<%!
	String name = null;
	String title = null;
%>
 

Expression elements enable you to enter any valid and complete Java expression. The servlet container converts an expression element to a String at request time. The resulting String is then written to the HTTP response. Expressions are placed between <%= and %> symbols.

The following example inserts a piece of dynamic data into an HTML string.

<p>Hail the <%= title %>!

Scriptlets are useful to manipulate data for viewing purposes. They enable you to enter any piece of valid Java code. However, they are not recommended for performing business logic because they can be difficult to maintain. It is better to encapsulate business logic within reusable Java classes like beans or tag handlers.

You might start out with scriptlets for prototyping or for the testing of new code. After confirming that the feature set meets your requirements, move the code into a bean or tag library. For complicated view logic, see View Creation Helpers. For details about creating a tag library, see Developing Your Own Tag Libraries.

You should not use scriptlets in production web applications. This recommendation is especially important if a developer is maintaining the code and a web page designer is in charge of the visual aspects of a web application.

Variables and methods declared in a declaration element are available to scriptlets in the same JSP page. A Java statement can begin in one scriptlet and end in another, interspersed, for example, with HTML code. Scriptlets are processed at request time and write output to the HTTP response, if you code them to do so.

The following scriptlet example shows a Java if statement that spans two scriptlets. The if statement is used to conditionalize a fragment of HTML code that lies between them. The HTML code is included in the HTTP response only if the if statement evaluates to true. Note that scriptlets are placed between <% and %> symbols.


<% if (name.equals("Elvis Presley")){ 
%>
<p>Let's hear it for Elvis!
<% 	title = "King";
}
%>
 

HTTP Sessions

An HTTP session is a Servlet API mechanism that associates the many requests representing a conversation between a client browser and a server.

When a user requests a JSP page, a new session is automatically created if it does not already exist. Subsequent requests to pages within the web application are usually associated with the session. Requests are not associated with the session when the page directive session attribute is set to false.

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

The session ends when a time-out occurs or when the web application explicitly invalidates it. The session timeout value is set in the web module's deployment descriptor file. A JSP page or servlet class can invalidate a session using the invalidate method. For details on setting the session time-out value, see Configuring the Web Module Deployment Descriptor. For more information on the using the invalidate method, see Creating and Invalidating Sessions.

The typical JSP page is associated with a session. However, you might also include dynamic pages that are not specific to a particular client. Such pages can be generated once and shared among many sessions. The use of JSP pages not associated with a session can reduce your web application's requirements for system resources.

In a distributed environment, information for a particular session might only exist in the web server that initiated the session. If requests are routed to different web servers depending on overall load, the session information must be replicated. In this situation, the web servers need to access the shared session information and must keep in sync. The web server can manage the shared session information. However, this practice adds to the total load on the system, consuming time and resources.

The HTTP Monitor indicates whether a page is associated with a session or not. It also provides other useful information about HTTP requests. For details on the IDE's HTTP Monitor, see Viewing Monitor Data Records.

Scopes and Implicit Objects

When instantiating an object in a JSP file, you most likely want to make it available to other objects in your application. You might want to ensure that all objects in your application can access the object. On the other hand, you might want to restrict its availability to some subset of these objects. For example, you might want to make the object available only to other objects associated with the current user's HTTP session. The JSP specification defines a number of scopes in which you can place a reference to an object.

Scopes enable you to control the availability of an object. You can place a reference to the object in any of these scopes. You typically only put an object in a single scope. The object is then available to all subsets of the chosen scope. In other words, page scope objects are available to objects in the request, session, and application scopes.

The concept of a scope in a web application is different from its use in traditional, standalone applications. In a web application, scope refers to an object's availability to an application's various components. These are the page, request, session, and application scopes. In standalone applications, scope refers to a variable or object's availability within blocks of code.

At runtime, these scopes are implemented as Java objects, as described in TABLE 2-3.

TABLE 2-3 Scopes in JSP Pages

Scope

Description

Object Type

page

Represents the current JSP page. This object is available only to JSP elements in the current page or in pages included by an include directive. This object is not available to pages included by an include action. The directive is executed at page translation time, and the included pages are concatenated into the same JSP implementation class.

javax.servlet.jsp.PageContext

request

Represents the current HTTP request. This object is available only to JSP pages and servlets executing in the current HTTP request. For example, if one JSP forwards to another using a forward action, both pages access the same ServletRequest object.

javax.servlet.ServletRequest

session

Represents the current user's HTTP session. This object is available only to JSP pages and servlets executing in requests associated with the current user's HTTP session.

javax.servlet.http.HttpSession

application

Represents the runtime web module. This object is available to all JSP pages and servlets in the web module.

javax.servlet.ServletContext


You can locate or make a bean available within one of these scopes with a useBean action. In this action, you supply a scope attribute in order to specify the availability of the bean instance, for example:

<jsp:useBean id="myCart" scope="session" class="Cart">

Scopes and the objects they represent are implicitly available to the scripting elements of a page. They use the scripting variables that the page automatically instantiates. By default, JSP pages have access to the session scope. However, if a page is not participating in a session, it cannot use the session scope. Furthermore, it cannot reference the session implicit variable. When a page is not participating in a session, the page directive session attribute is set to false. Some parts of an application do not require session data. An example of such data is background information about a site that does not require a user to log in. If the user remains only in those sections, then the overhead of creating a user session can be avoided.

You can use the IDE's code completion feature to show the methods available to different scoped objects. For details, see Modifying the JSP File.

You can set and use scoped objects from within servlets, tag handlers, and scriptlets. To set objects in scopes, use the addAttribute method on the relevant scope object. To retrieve objects in scopes, use the getAttribute method on the relevant scope object. See TABLE 2-3 regarding the available scopes.


Servlets

Servlets are Java classes that execute within a servlet container. They are used to:

  • Extend the capabilities of web servers and web-enabled application servers
  • Generate dynamic content
  • Interact with web clients using a request-response paradigm

For details on support for developing servlets in the IDE, see Creating Servlets.

Servlets are typically used as Front Controllers and dispatchers to control navigation through a web application. They are also used to control application flow. Servlets enable and disable access to certain web resources, depending on the particular state being tracked.

For more information on the use of the Front Controller design pattern, see Front Controllers.

Servlet Life Cycle

The servlet life cycle defines how the servlet is loaded, instantiated, and initialized. It also describes how it handles requests from clients, and how it is taken out of service.

Loading and Instantiation

Servlets execute within containers that provide the network services. These services include sending requests and responses, decoding requests, and formatting responses. All servlet containers support HTTP as a protocol for requests and responses. They might also provide for additional request-response protocols such as HTTPS.

The servlet container loads and instantiates servlets. An option enables loading and instantiation to occur once the servlet container is started. Servlets designated "load on startup" are loaded when the servlet container starts up. For more information, see Load on Startup. When the loading is complete, the container instantiates the Servlet class for use.

Initialization

Before the servlet can handle requests from clients, the servlet container initializes it. Initialization enables the servlet to:

  • Read persistent configuration data
  • Initialize two kinds of resources:
    • Those you only want one instance of
    • Those that are time-consuming to initialize, for instance, database connections
  • Perform any application-specific start-up activities

Request Handling

Once the servlet has been initialized, the servlet container can route requests to it. The servlet processes the requests and builds appropriate responses. The servlet passes these objects as parameters of the service method of the HTTPServlet interface. The service method is called by the servlet container. It enables the servlet to respond to a request only after the servlet's init method has been initialized.

Servlets typically run inside multi-threaded servlet containers that can handle multiple requests concurrently. As a developer, make sure to synchronize access to any shared resource such as files and network connections. Also make sure to synchronize access to the servlet's class and instance variables. If necessary, the servlet container can also serialize requests to a servlet.

A new servlet instance is created for each concurrent request. Therefore, if many requests arrive simultaneously, many new threads are created. To avoid overloading the server, the servlet container can limit the maximum number of servlets. For the Tomcat server, see the Configuration reference for information on setting these values: http://jakarta.apache.org/tomcat/tomcat-4.0-doc/config

Destruction

When a servlet container decides to remove a servlet from service, it calls the destroy method of the Servlet interface. This method enables the servlet to release its resources and save any persistent states.

Once the destroy method is called, the container cannot route other requests to that servlet instance. Furthermore, any currently running threads of the service method are permitted to complete their execution. Upon the completion of the destroy method, the container releases the servlet instance for garbage collection.

Unlike other Java classes, the servlet's life span might be hours, days or even weeks. Hence, you need to manage the use and creation of resources, such as database connections, so that they are available only when needed.


Tag Libraries

A tag library is a collection of custom actions. As shown in FIGURE 2-2, a tag library consists of a set of tag handlers and a tag library descriptor file. Each custom action, or tag, is implemented as a tag handler bean that contains its features. The tag library descriptor (TLD) is an XML document that maps each tag in the library to its associated tag handler. The TLD describes parameters and scripting variables associated with the tags in the tag library.

 FIGURE 2-2 The Structure of a Tag Library

Figure showing a tag placed within a JSP page.[ D ]

A tag library is typically packaged as a JAR file. It is made available to a JSP file through a taglib directive. The IDE supports the use of existing tag libraries such as JSTL (Java Server Pagestrademark Standard Tag Library) and other third-party libraries. It also provides for the creation of your own tag libraries. For details on tag library support in the IDE, see Using Tag Libraries.

JSP Standard Tag Library

You can use tags from the JSP Standard Tag Library (JSTL) to extend the set of actions available for use in your web application. The use of tags based on a standard helps to increase the portability of components within a web application. It also reduces the need for Java code in scriptlets, which can create maintenance difficulties in JSP files.

For example, instead of iterating over lists using different iteration tags from numerous vendors, you can use JSTL tags. They work the same way in all web environments. This standardization means you learn a single tag and use it on multiple JSP containers. Furthermore, the specification enables containers to recognize standard tags and optimize their implementations.

The JSTL introduces the concept of an expression language to simplify page development. It includes an experimental version of a language for testing purposes. JSTL also provides a framework for integrating existing custom tags with JSTL tags.

For a tutorial and description of JSTL tags, see the JSTL reference pages included with the Java Web Services Developer Pack at http://java.sun.com/
webservices/docs/ea2/tutorial/doc/JSTL.html
(At the time of this book's publication, the Java Web Services Developer Pack is still in early access. This URL might change when the developer pack reaches its final release.)

To download the JSTL and the associated specification, visit the following website: http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html

You can use the tag library editing and management features of the IDE to facilitate the usage of JSTL tags. For details, see Using Existing Tag Libraries.


Servlet Filters

Servlet filters, also called filters in this book, are Java classes that modify requests to and responses from servlets. Filters can be used to perform many functions, such as:

  • Authentication. Assurance that a user can only access certain web resources
  • Logging and auditing web application users. Keeping track of each time a user accesses a web resource and recording the access in a log file
  • Localization. Choice of the appropriate resource for the user's locale
  • Data compression. Compression or decompression of data on its way to or from a servlet
  • Style translations of XML content. Translation of XML content before viewing a web resource

Filters are defined by version 2.3 of the Java Servlet Specification. Hence, they are called when the servlet context receives the request before it is passed on to the processing resource. Filters are not called if the request is redispatched internally, for example, because the request is forwarded. This behavior makes filters useful in some gate-keeping roles. For instance, you could use a filter for:

  • Logging. If a property of incoming requests interests you, the filter can extract the requests and write them to a file.
  • Changing or adding to data associated with the request. You can replace the original request and response with wrappers. They enable you to change the incoming request before it is processed by a JSP page or a servlet.
  • Handling preprocessing required by a group of resources. For example, you could ensure that a user profile is loaded into a session.

By contrast, you might require logging or preprocessing in case a request is forwarded from a servlet or JSP page using the RequestDispatcher API. In this situation, you need to implement the action as a servlet instead.

When the servlet context receives a request, it determines whether any filters match the path to the resource. If one or more filters are found, the servlet context constructs a FilterChain object. The chain consists of all matching filters in the order they are declared in the deployment descriptor. The servlet context calls the doFilter() method on the first filter. Each filter must call the next filter in the chain. Each filter gives control to the next filter and so forth. When the last filter in the chain calls the doFilter method, the request is processed by a JSP page or a servlet. The request could also be processed in a static content file such as an image being served. Once this process is complete, control is returned to the last filter. When the last filter's doFilter method is completed, control is returned to the next-to-the-last filter and so forth.

An example of a filter in action is the HTTP Monitor in the Forte for Java 4 IDE. It uses a filter to gather data about the request and the servlet context before and after the other web application resources process the request. The filter is also responsible for handling replay requests. The filter accomplishes this task by replacing the incoming request with a wrapper. Then the filter populates the wrapper with data from the original request. Hence, the HTTP Monitor filter needs to be the first one in the chain, so that it is called before any application-defined filters. Filters are usually declared in the deployment descriptor of individual web modules. However, because the HTTP Monitor gathers data for all web applications on the server, on the Tomcat servlet engine, filters are declared in the default deployment descriptor (conf/web.xml).

For information on the support for servlet filters in the IDE, see Creating Filters.

Filter Life Cycle

The filter life cycle delineates how the filter is loaded, instantiated, and initialized. It also describes how the filter handles requests from clients and how it is taken out of service.

Loading and Instantiation

Before a servlet container accesses a web resource, it locates the list of filters to be applied to the web resource. The servlet container ensures that it has instantiated a filter of the appropriate class for each filter on the list. It also calls the FilterConfig method for each filter.

Initialization

When the container receives a request, it calls the doFilter method for the first filter in the list of filters in the chain. The container then passes in the servlet's requests and responses and a reference to the filter chain it is to use. The filter chain is defined in the deployment descriptor.

The doFilter method for a filter might examine the headers of the request. In addition, the method could modify request or response headers or alter data by wrapping the request or response object.

The filter then calls the next entity in the filter chain. The entity could be a filter. A request works its way through the filter chain to the last filter. The last filter then calls the associated web resource, for instance, a servlet or a JSP page.

Destruction

Before a filter can be removed from service by the container, the container calls the destroy method on the filter. It also releases any other resources and performs cleanup operations.


Listeners

Application event listeners are new with the Servlet 2.3 Specification. They are classes that implement one or more of the servlet event listener interfaces. Application event listeners are instantiated and registered in the web application at the time the web application is deployed.

Listener classes provide a way to track sessions within a web application. It is often useful to determine why a session has become invalid. Either the container timed out the session or the application called the invalidate method. You can make this distinction using listeners and HTTPSession API methods.

Servlet event listeners support event notifications for state changes in:

  • Servlet context objects. Useful for managing resources at the virtual machine level for the application
  • HTTP session objects. Useful for managing state. Also helpful for handling resources associated with a series of requests from the same client related to the application.

Use multiple listeners to monitor changes occurring within the life cycle. They are also useful to track attributes of servlet contexts and HTTP session objects.

  • Servlet context events include:
    • Life cycle. Servlet context has just been created and can service its first request, or it is about to be shut down.
    • Changes to attributes. Servlet context attributes have been added, removed, or replaced.
  • HTTP Session events include:
    • Life cycle. An HTTP session has been created or invalidated, or has timed out.
    • Changes to attributes. Attributes have been added, removed, or replaced on an HTTP session.