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.
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.
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:
The container attempts to locate an exact match of the request path to the path of a servlet.
The container recursively tries to match the longest path prefix. The servlet that contains the longest match, if any, is selected.
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 (.).
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.
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.
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.
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
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.
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.
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.
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.
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
orError
ServletException
or subclassesIOException
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.