Configuring the web.xml File for Struts

Although the web.xml file is used for configuring any generic web application, there are a few Struts-specific configuration options that you must configure within this file when using the Struts framework. The next section describes the necessary steps that you’ll need to perform to ensure that your Struts application is properly configured.

Mapping the Struts ActionServlet

The first and perhaps most important step that you need to perform is to configure the ActionServlet that will receive all incoming requests for the application.

Tip

You need to configure only a single ActionServlet, regardless of the number of application modules that are being used. Some developers choose to set up multiple controller servlets to handle different functional areas of the application. Because servlets are multithreaded, you don’t gain any real performance or scalability value by using multiple ActionServlet mappings.

There are two steps in configuring the Struts controller servlet in the web.xml file. The first step is to use the servlet element to configure the servlet instance that can later be mapped in the servlet-mapping element. The child elements that can be used in the servlet element are shown here:

<!ELEMENT servlet (icon?, servlet-name, display-name?, description?,
   (servlet-class|jsp-file), init-param*, load-on-startup?, run-
   as?, security-role-ref*)
>

The child elements that we are most interested in are servlet-name, servlet-class, and init-param. The servlet-name element specifies the name used by the deployment descriptor to reference the servlet throughout the remainder of the file. When you’re configuring the servlet-class element for a Struts application, this element must specify a fully qualified class that extends the org.apache.struts.action.ActionServlet class.

Tip

Because the Struts ActionServlet class is not abstract, you are free to use that class and avoid having to create a subclass of the ActionServlet for your application. With earlier versions of the Struts framework, it was more important to extend the ActionServlet class with one of your own because most of the processing occurred there, and subclassing allowed you to override that functionality with your own. With Version 1.1, however, most of the processing functionality has been moved to another class, which you can configure declaratively (as you’ll see later in this chapter). There is little reason to create your own ActionServlet class, although you are still free to do so.

The following web.xml fragment illustrates how to use the servlet element to configure the servlet class:

<web-app>  
 <servlet>
  <servlet-name>storefront</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 </servlet>
</web-app>

The next step that needs to be performed to configure the Struts controller servlet in the deployment descriptor is to configure the servlet mapping. This is done using the servlet-mapping element. The following partial deployment descriptor illustrates how to combine the servlet-mapping element with the servlet element shown previously:

<web-app>  
 <servlet>
  <servlet-name>storefront</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>storefront</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
</web-app>

Notice that the value in the servlet-name element within the servlet element must match the value in the servlet-name element within the servlet-mapping element. This tells the web container that the ActionServlet should service all requests having an extension of .do.

Mapping requests to servlets

This is a good time to digress for a moment and discuss how the URLs that a user types into a browser are mapped to the correct web application and servlet. When a web application is installed in a container, the container is responsible for assigning a ServletContext to it. There is a single instance of a ServletContext object for each web application deployed in a container.

Tip

If the container is distributable and uses more than one JVM, the web application may have a separate ServletContext instance for each JVM.

The ServletContext provides an external view of the web container environment for a servlet. A servlet can use the ServletContext object to gain access to external resources, log events, and store attributes and objects that other servlet instances in the same context can access. It’s essentially an application-scope shared resource.

Because a servlet is associated with a specific web application, all requests that begin with a specific request path (known as the context path) are routed to the web application associated with that servlet. Servlets associated with the default application have an empty string (” “) as the context path.

When a web container receives a client request, it must determine the correct web application to forward it to. The web container determines this by matching the URL with the longest context path that matches an installed web application.

For example, suppose that there are two web applications installed in a container. One web application is given the name Storefront and is located off the root directory of the container at /storefront. The second web application is called Storefront_ demo and is located off the root directory at /storefront_demo.

If a client request arrives at the server with a URL of http://www.somehost.com/ storefront_demo/login.do, the server will match it to the web application that has the closest match, which in this case would be the Storefront_demo application. Once the container determines the correct context or web application, it must determine which servlet in the web application should process the request. The web container uses the request URL, minus the context path, to determine the path that will be used to map the request to the correct servlet.

The web container uses the following guidelines to find the first successful match:

  1. The container attempts to locate an exact match of the request path to the path of a servlet.

  2. The container recursively tries to match the longest path prefix. The servlet that contains the longest match, if any, is selected.

  3. If the URL path contains an extension—for example, .do—the servlet container tries to match a servlet that handles requests for that extension. The extension is defined as the part of the segment after the last dot (.).

  4. If none of the previous rules produces a match, the container attempts to use a default servlet, if one is configured. Otherwise, the request returns an error response.

Tip

The web container uses case-sensitive string comparisons when checking for a match.

The concept of extension mappings was mentioned in Step 3 of the matching guidelines. There is another type of mapping that can be used, known as path mapping. A servlet-mapping that uses path mapping allows a URL that doesn’t contain an extension to match to the servlet. Using the earlier Storefront servlet mapping, the following partial web.xml file illustrates how path mapping is configured:

<web-app>  
 <servlet>
  <servlet-name>storefront</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>storefront</servlet-name>
  <url-pattern>/action/*</url-pattern>
 </servlet-mapping>
</web-app>

Using path mapping, all requests mapped to this web application that contain the string “/action” in the request URL will be serviced by the Storefront servlet, regardless of what is in place of the * character.

Specifying Multiple Application Modules

As was briefly discussed in Chapter 3, the Struts 1.1 release added the ability to define multiple Struts configuration files, one for each supported application module. In previous versions of the framework, you specified a relative path to the single Struts configuration file using the config initialization parameter. With Version 1.1 and introduction of the concept of application modules, you can now create multiple Struts configuration files and specify them in the web.xml file using multiple config initialization parameters and the application module prefix. The next section discusses the initialization parameters that can be configured for a servlet.

Declaring the Initialization Parameters

Initialization parameters are used to make configuration options available to a servlet. This allows the developer to declaratively affect the runtime environment of the servlet. Initialization parameters are configured within the servlet element using init-param elements, as shown in the following web.xml fragment:

<web-app>  
 <servlet>
  <servlet-name>storefront</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <init-param>
   <param-name>host</param-name>
   <param-value>localhost</param-value>
  </init-param>
  <init-param>
   <param-name>port</param-name>
   <param-value>7001</param-value>
  </init-param>
 </servlet>
 
 <servlet-mapping>
  <servlet-name>storefront</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
</web-app>

You can specify any parameter you need within the init-param element, as long as it’s a name/value pair. For example, the previous web deployment descriptor included initialization parameters for a host and port. If you were using EJB, this might be a way to include the server connection information. Zero or more init- param elements are allowed.

There are specific initialization parameters that can be specified for the Struts servlet. In earlier versions of Struts, many of the configuration options that are now in the Struts configuration file were configured by adding init-param elements. Although applications that were built and tested with Version 1.0 will continue to work using Version 1.1, you may want to move some of the initialization parameters that currently are specified in the web deployment descriptor to the proper location in the Struts configuration file. Although the framework includes functionality that allows the previous initialization parameters to work in the web.xml file, we will cover the 1.1 parameters here. Table 4-2 identifies the initialization parameters that can be specified for Struts 1.1.

Table 4-2. Initialization parameters for web.xml using Struts 1.1

Name

Purpose/default value

config

A context-relative path to the default Struts configuration file. The default value is /WEB-INF/struts-config.xml, which serves as the default application. Starting with Struts 1.1, you can specify a comma-separated list of configuration files for this paramter.

config/sub1

Specify additional application modules by using the value config/ and the prefix of the module. In this example, the init-param name would be config/module1, and the value might be WEB-INF/struts-sub1-config.xml. This tells the controller to load the application module mod1 from the additional Struts configuration file. You can declare as many application modules as you need.

convertNull

Force simulation of the Struts 1.0 behavior when populating forms. If set to true, the numeric Java wrapper class types such as java.lang.Integer will default to null rather than 0. The default is false.

validating

A validating XML parser is used to process the configuration file. This is strongly recommended. The default value is true.

Tip

There are several initialization parameters that have been deprecated in Version 1.1. Most of them are now supported through the Struts configuration file, which is discussed later in the chapter.

Using Multiple Struts Configuration Files

We’ve briefly mentioned using multiple application modules with Struts 1.1, but now you can use multiple configuration files as well. This is possible because the previously monolithic Struts configuration file has now been separated into individual XML files, making it possible to declare each them with the config initialization parameter. This is helpful because no single Struts configuration file now contends for resources during development. Using multiple files also makes is easier to support optional functionality. If, for example, you don’t need to deploy certain Struts actions or other configuration elements, you can group them into a single file and remove all of them at once by removing that file from the list in web.xml. The following init-param fragment shows how to include more than one Struts configuration file:

  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml,/WEB-INF/other-struts-config.xml
   </param-value>
  </init-param>

You can declare as many configuration files as needed.

Configuring the Tag Libraries

The Struts framework provides several JSP tag libraries that you must configure in the web application deployment descriptor if you choose to use them. You inform the container of these tag libraries by declaring one or more taglib elements within the web deployment descriptor. The following partial web.xml file illustrates how the tag libraries are configured within the web-app element:

<web-app>
 <servlet>
  <servlet-name>storefront</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <init-param>
   <param-name>host</param-name>
   <param-value>localhost</param-value>
  </init-param>
  <init-param>
   <param-name>port</param-name>
   <param-value>7001</param-value>
  </init-param>
 </servlet>
 
 <servlet-mapping>
  <servlet-name>storefront</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>

 <taglib>
  <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
 </taglib>

 <taglib>
  <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
 </taglib>

 <taglib>
  <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
 </taglib>
</web-app>

The taglib element has two subelements: taglib-uri and taglib-location. The taglib-uri element specifies a URI identifying a tag library that is used by the web application. The value may be either a relative or an absolute URI. It must be a valid URI, but here it’s used as a unique identifier for the tag library. The taglib-location element specifies the location (as a resource) of the tag library descriptor file.

The Struts tag libraries are not the only ones that can be declared in the web application deployment descriptor. If you create any of your own custom tag libraries, you should create taglib elements for them here as well.

Setting Up the Welcome File List

The welcome-file-list element allows you to configure default resources that should be used when a valid but partial URI is entered for a web application. You can specify multiple welcome files, and they will be used in the order in which they are listed.

Suppose we configured the welcome-file-list element for the Storefront application as in Example 4-1.

Example 4-1. The welcome-file-list element for the Storefront application

<welcome-file-list>
 <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

This indicates that a request to the server for http://www.somehost.com/storefront, which is the root of the Storefront application, should resolve to http://www.somehost.com/storefront/index.jsp. This is beneficial because most containers would, by default, look for index.html or index.htm instead. You can specify multiple welcome-file elements within the welcome-file-list. This might be helpful if, for example, you deployed your application on various types of containers and the first welcome-file resource was not found on the server. The container would continue to try to match the welcome files up to the request URI until it found one on the server and served that resource to the client. The order of the welcome file entries in the deployment descriptor is used for the matching process.

There should be no trailing or leading “/” characters in the welcome-file element. If no welcome files are declared for the web application or the URI entered by a client, the web container may handle the request appropriately—for example, it may return a 404 (File Not Found) error response or a directory listing. It’s a good idea to configure a welcome file for at least the root web application.

Using a Struts action in the welcome file list

Because the web containers don’t use the servlet mappings for resources in the welcome-file-list, you can’t directly set up a welcome-file element to use a Struts action.

However, there is an alternate way that allows you to achieve the same results. First, create a global forward in the Struts configuration file for the action that you would like to invoke:

<global-forwards>
 <forward name="welcome" path="viewsignin.do"/>
</global-forwards>

Then create a JSP page called welcome.jsp (the name actually can be anything you want) and use the Struts forward tag to forward to the global forward when the page is loaded. The welcome.jsp page only has to contain:

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
 <body>
  <logic:forward name="welcome"/>
 </body>
</html>

You then need to add a welcome-file element for the welcome.jsp page:

<welcome-file-list>
 <welcome-file>welcome.jsp</welcome-file>   
</welcome-file-list>

Containers using the welcome.jsp resource will automatically forward to the forward named welcome, which was defined in the global-forwards section. The welcome forward in turn invokes the viewsignin.do action and achieves the desired result.

Configuring Error Handling in web.xml

Although the Struts framework provides a suitable error-handling mechanism, there are times that problems slip through the exception-handling crack and users are shown a servlet or JSP exception. To absolutely prevent this from happening, you should use the error-page element available to the web application deployment descriptor. Example 4-2 shows a partial web.xml file that uses the error-page element to prevent users from seeing a 404 or a 500 (Internal Server) error.

Example 4-2. Using the error-page element

<web-app>
 <!-- Other elements go here -->

 <error-page>
  <error-code>404</error-code>
  <location>/common/404.jsp</location>
 </error-page>

 <error-page>
  <error-code>500</error-code>
  <location>/common/500.jsp</location>
 </error-page>
</web-app>

When an error status code is set in the response, the container consults the list of error-page declarations for the web application. If a match is found, the container returns the resource indicated by the location element. The value of the location element must begin with a “/” character, and it must refer to a resource within the web application.

If you need to refer to a resource outside of the web application, you can use the HTML Refresh meta tag. To do this, refer to a static HTML document in the location element that contains only the following line:

<meta http-equiv="Refresh" content="0;URL=http://www.somehost.com/404.jsp">

When the error occurs, the Refresh meta tag will reload immediately, but it will use the alternate URL provided. This strategy also is a good way to allow users to refer to resources with a static extension, such as .htm, but then reload to a dynamic page, such as a JSP page.

Tip

For example, you can use this approach to show a “Still Processing” page. You might want to set the reload time to a value greater than zero. The URL can be a Struts action—if the processing isn’t finished, it will just call the same page again. If processing has completed, it can forward to a completed page.

A servlet also can generate exceptions for which you can declare error pages. Instead of specifying the error-code element, you can specify a fully qualified Java class using the exception-type element. Servlets can throw the following exceptions during processing:

  • RuntimeException or Error

  • ServletException or subclasses

  • IOException or subclasses

The Java exception class declared in the exception-type element must be one of these.

Example 4-3 illustrates how you would substitute the exception-type element for the error-code.

Example 4-3. Using the exception-type instead of the error-code element

<web-app>
 <error-page>
  <exception-type>javax.servlet.ServletException</exception-type>
  <location>/common/system_error.jsp</location>
 </error-page>
</web-app>

For the majority of this chapter, you have been shown partial deployment descriptors. This was done mainly to save space, but also so that we could ease our way into the various supported elements. Now it’s time to include a complete example of a web deployment descriptor. Example 4-4 shows the web deployment descriptor for the Storefront application.

Example 4-4. A complete web.xml file configured for Struts 1.1

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
<web-app>  
 <servlet>
  <servlet-name>storefront</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>    

  <load-on-startup>1</load-on-startup>
 </servlet>
  
 <servlet-mapping>
  <servlet-name>storefront</servlet-name>
  <url-pattern>/action/*</url-pattern>
 </servlet-mapping>
 
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>   
 </welcome-file-list>
  
 <error-page>
  <error-code>404</error-code>
  <location>/common/404.jsp</location>
 </error-page>
 <error-page>
  <error-code>500</error-code>
  <location>/common/500.jsp</location>
 </error-page>

 <taglib>
  <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
 </taglib>
 <taglib>
  <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
 </taglib>
 <taglib>
  <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
 </taglib>
</web-app>

Get Programming Jakarta Struts, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.