epubjs
Version:
Render ePub documents in the browser, across many devices
369 lines (367 loc) • 71.1 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>WAR Files and Deployment</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="WAR Files and Deployment"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-15-SECT-3"/>WAR Files and Deployment</h1></div></div></div><p>As we described in the introduction to this chapter, a WAR file is
an archive that contains all the parts of a web application: Java class
files for servlets and web services, JSPs, HTML pages, images, and other
resources. The WAR file is simply a JAR file (which is itself a fancy ZIP
file) with specified directories for the Java code and one designated
configuration file: the <span class="emphasis"><em>web.xml</em></span> file, which tells the
application server what to run and how to run it. WAR files always have
the extension <span class="emphasis"><em>.war</em></span>, but they can be created and read
with the standard <span class="emphasis"><em>jar</em></span> tool.</p><p>The contents of a typical WAR might look like this, as revealed by
the <span class="emphasis"><em>jar</em></span> tool:</p><a id="I_15_tt932"/><pre class="programlisting"> <code class="n">$</code> <strong class="userinput"><code><code class="n">jar</code> <code class="n">tvf</code> <code class="n">shoppingcart</code><code class="o">.</code><code class="na">war</code></code></strong>
<code class="n">index</code><code class="o">.</code><code class="na">html</code>
<code class="n">purchase</code><code class="o">.</code><code class="na">html</code>
<code class="n">receipt</code><code class="o">.</code><code class="na">html</code>
<code class="n">images</code><code class="o">/</code><code class="n">happybunny</code><code class="o">.</code><code class="na">gif</code>
<code class="n">WEB</code><code class="o">-</code><code class="n">INF</code><code class="o">/</code><code class="n">web</code><code class="o">.</code><code class="na">xml</code>
<code class="n">WEB</code><code class="o">-</code><code class="n">INF</code><code class="o">/</code><code class="n">classes</code><code class="o">/</code><code class="n">com</code><code class="o">/</code><code class="n">mycompany</code><code class="o">/</code><code class="n">PurchaseServlet</code><code class="o">.</code><code class="na">class</code>
<code class="n">WEB</code><code class="o">-</code><code class="n">INF</code><code class="o">/</code><code class="n">classes</code><code class="o">/</code><code class="n">com</code><code class="o">/</code><code class="n">mycompany</code><code class="o">/</code><code class="n">ReturnServlet</code><code class="o">.</code><code class="na">class</code>
<code class="n">WEB</code><code class="o">-</code><code class="n">INF</code><code class="o">/</code><code class="n">lib</code><code class="o">/</code><code class="n">thirdparty</code><code class="o">.</code><code class="na">jar</code></pre><p>When deployed, the name of the WAR becomes, by default, the root
path of the web application—in this case,
<span class="emphasis"><em>shoppingcart</em></span>. Thus, the base URL for this web app, if
deployed on <span class="emphasis"><em>http://www.oreilly.com</em></span>, is
<span class="emphasis"><em>http://www.oreilly.com/shoppingcart/</em></span>, and all
references to its documents, images, and servlets start with that path.
The top level of the WAR file becomes the document root (base directory)
for serving files. Our <span class="emphasis"><em>index.html</em></span> file appears at the
base URL we just mentioned, and our <span class="emphasis"><em>happybunny.gif</em></span>
image is referenced as
<span class="emphasis"><em>http://www.oreilly.com/shoppingcart/images/happybunny.gif.</em></span></p><p>The <a id="I_indexterm15_id779820" class="indexterm"/><span class="emphasis"><em>WEB-INF</em></span> directory (all caps,
hyphenated) is a special directory that contains all deployment
information and application code. This directory is protected by the web
server, and its contents are not visible to outside users of the
application, even if you add <span class="emphasis"><em>WEB-INF</em></span> to the base URL.
Your application classes can load additional files from this area using
<code class="literal">getResource()</code> on the servlet context,
however, so it is a safe place to store application resources. The
<span class="emphasis"><em>WEB-INF</em></span> directory also contains the
<span class="emphasis"><em>web.xml</em></span> file, which we’ll talk more about in the next
section.</p><p>The <a id="I_indexterm15_id779852" class="indexterm"/><span class="emphasis"><em>WEB-INF/classes</em></span> and <a id="I_indexterm15_id779860" class="indexterm"/><span class="emphasis"><em>WEB-INF/lib</em></span> directories contain Java
class files and JAR libraries, respectively. The
<span class="emphasis"><em>WEB-INF/classes</em></span> directory is automatically added to
the classpath of the web application, so any class files placed here
(using the normal Java package conventions) are available to the
application. After that, any JAR files located in <span class="emphasis"><em>WEB-INF/lib</em></span> are
appended to the web app’s classpath (the order in which they are appended
is, unfortunately, not specified). You can place your classes in either
location. During development, it is often easier to work with the “loose”
<span class="emphasis"><em>classes</em></span> directory and use the
<span class="emphasis"><em>lib</em></span> directory for supporting classes and third-party
tools. It’s also possible to install JAR files directly in the servlet
container to make them available to all web apps running on that server.
This is often done for common libraries that will be used by many web
apps. The location for placing the libraries, however, is not standard and
any classes that are deployed in this way cannot be automatically reloaded
if changed—a feature of WAR files that we’ll discuss later. Servlet API
requires that each server provide a directory for these extension JARs and
that the classes there will be loaded by a single classloader and made
visible to the web application.</p><div class="sect2" title="Configuration with web.xml and Annotations"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-15-SECT-3.1"/>Configuration with web.xml and Annotations</h2></div></div></div><p><a id="idx10879" class="indexterm"/> <a id="idx10901" class="indexterm"/> <a id="idx10910" class="indexterm"/>The <span class="emphasis"><em>web.xml</em></span> file is an XML
configuration file that lists servlets and related entities to be
deployed, the relative names (URL paths) under which to deploy them,
their initialization parameters, and their deployment details, including
security and authorization. For most of the history of Java web
applications, this was the only deployment configuration mechanism.
However, as of the Servlet 3.0 API, there are additional options. Most
configuration can now be done using Java annotations. We saw the
WebServlet annotation used in the first example, <code class="literal">HelloClient</code>, to declare the servlet and
specify its deployment URL path. Using the annotation, we could deploy
the servlet to the Tomcat server without any
<span class="emphasis"><em>web.xml</em></span> file. Another option with the Servlet 3.0
API is to deploy servlet procedurally—using Java code at runtime.</p><p>In this section we will describe both the XML and annotation style
of configuration. For most purposes, you will find it easier to use the
annotations, but there are a couple of reasons to understand the XML
configuration as well. First, the <span class="emphasis"><em>web.xml</em></span> can be
used to override or extend the hardcoded annotation configuration. Using
the XML, you can change configuration at deployment time without
recompiling the classes. In general, configuration in the XML will take
precedence over the annotations. It is also possible to tell the server
to ignore the annotations completely, using an attribute called
<a id="I_indexterm15_id779978" class="indexterm"/><code class="literal">metadata-complete</code> in
the <span class="emphasis"><em>web.xml</em></span>. Next, there may be some residual
configuration, especially relating to options of the servlet container,
which can only be done through XML.</p><p>We will assume that you have at least a passing familiarity with
XML, but you can simply copy these examples in a cut-and-paste fashion.
(For details about working with Java and XML, see <a class="xref" href="ch24.html" title="Chapter 24. XML">Chapter 24</a>.) Let’s start with a simple
<span class="emphasis"><em>web.xml</em></span> file for our <code class="literal">HelloClient</code> servlet example. It looks like
this:</p><a id="I_15_tt933"/><pre class="programlisting"> <code class="o"><</code><code class="n">web</code><code class="o">-</code><code class="n">app</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">helloclient1</code><code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">class</code><code class="o">></code><code class="n">HelloClient</code><code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">class</code><code class="o">></code>
<code class="o"></</code><code class="n">servlet</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">mapping</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">helloclient1</code><code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"><</code><code class="n">url</code><code class="o">-</code><code class="n">pattern</code><code class="o">>/</code><code class="n">hello</code><code class="o"></</code><code class="n">url</code><code class="o">-</code><code class="n">pattern</code><code class="o">></code>
<code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">mapping</code><code class="o">></code>
<code class="o"></</code><code class="n">web</code><code class="o">-</code><code class="n">app</code><code class="o">></code></pre><p>The top-level element of the document is called <code class="literal"><web-app></code>. Many types of entries may
appear inside the <code class="literal"><web-app></code>,
but the most basic are <a id="I_indexterm15_id780039" class="indexterm"/><code class="literal"><servlet></code>
declarations and <a id="I_indexterm15_id780052" class="indexterm"/><code class="literal"><servlet-mapping></code>
deployment mappings. The <code class="literal"><servlet></code> declaration tag is used to
declare an instance of a servlet and, optionally, to give it
initialization and other parameters. One instance of the servlet class
is instantiated for each <code class="literal"><servlet></code> tag appearing in the
<span class="emphasis"><em>web.xml</em></span> file.</p><p>At minimum, the <code class="literal"><servlet></code>
declaration requires two pieces of information: a <a id="I_indexterm15_id780092" class="indexterm"/><code class="literal"><servlet-name></code>,
which serves as a handle to reference the servlet elsewhere in the
<span class="emphasis"><em>web.xml</em></span> file, and the <a id="I_indexterm15_id780110" class="indexterm"/><code class="literal"><servlet-class></code>
tag, which specifies the Java class name of the servlet. Here, we named
the servlet <code class="literal">helloclient1</code>. We named it
like this to emphasize that we could declare other instances of the same
servlet if we wanted to, possibly giving them different initialization
parameters, etc. The class name for our servlet is, of course, <code class="literal">HelloClient</code>. In a real application, the
servlet class would likely have a full package name, such as <code class="literal">com.oreilly.servlets.HelloClient</code>.</p><p>A servlet declaration may also include one or more initialization
parameters, which are made available to the servlet through the <code class="literal">ServletConfig</code> object’s <code class="literal">getInitParameter()</code> method:</p><a id="I_15_tt934"/><pre class="programlisting"> <code class="o"><</code><code class="n">servlet</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">helloclient1</code><code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">class</code><code class="o">></code><code class="n">HelloClient</code><code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">class</code><code class="o">></code>
<code class="o"><</code><code class="n">init</code><code class="o">-</code><code class="n">param</code><code class="o">></code>
<code class="o"><</code><code class="n">param</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">foo</code><code class="o"></</code><code class="n">param</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"><</code><code class="n">param</code><code class="o">-</code><code class="n">value</code><code class="o">></code><code class="n">bar</code><code class="o"></</code><code class="n">param</code><code class="o">-</code><code class="n">value</code><code class="o">></code>
<code class="o"></</code><code class="n">init</code><code class="o">-</code><code class="n">param</code><code class="o">></code>
<code class="o"></</code><code class="n">servlet</code><code class="o">></code></pre><p>Next, we have our <code class="literal"><servlet-mapping></code>, which associates the
servlet instance with a path on the web server:</p><a id="I_15_tt935"/><pre class="programlisting"> <code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">mapping</code><code class="o">></code>
<code class="o"><</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">helloclient1</code><code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"><</code><code class="n">url</code><code class="o">-</code><code class="n">pattern</code><code class="o">>/</code><code class="n">hello</code><code class="o"></</code><code class="n">url</code><code class="o">-</code><code class="n">pattern</code><code class="o">></code>
<code class="o"></</code><code class="n">servlet</code><code class="o">-</code><code class="n">mapping</code><code class="o">></code></pre><p>Here we mapped our servlet to the path
<span class="emphasis"><em>/hello</em></span>. (We could include additional url-patterns
in the mapping if desired.) If we later name our WAR
<span class="emphasis"><em>learningjava.war</em></span> and deploy it on
<span class="emphasis"><em>www.oreilly.com</em></span>, the full path to this servlet
would be <span class="emphasis"><em>http://www.oreilly.com/learningjava/hello</em></span>.
Just as we could declare more than one servlet instance with the
<code class="literal"><servlet></code> tag, we could declare
more than one <code class="literal"><servlet-mapping></code>
for a given servlet instance. We
could, for example, redundantly map the same <code class="literal">helloclient1</code> instance to the paths
<span class="emphasis"><em>/hello</em></span> and <span class="emphasis"><em>/hola</em></span>. The <code class="literal"><url-pattern></code> tag provides some very
flexible ways to specify the URLs that should match a servlet. We’ll
talk about this in detail in the next section.</p><p>Finally, we should mention that although the
<span class="emphasis"><em>web.xml</em></span> example listed earlier will work on some
application servers, it is technically incomplete because it is missing
formal information that specifies the version of XML it is using and the
version of the <span class="emphasis"><em>web.xml</em></span> file standard with which it
complies. To make it fully compliant with the standards, add a line such
as:</p><a id="I_15_tt936"/><pre class="programlisting"> <code class="o"><?</code><code class="n">xml</code> <code class="n">version</code><code class="o">=</code><code class="s">"1.0"</code> <code class="n">encoding</code><code class="o">=</code><code class="s">"ISO-8859-1"</code><code class="o">?></code></pre><p>As of Servlet API 2.5, the <span class="emphasis"><em>web.xml</em></span> version
information takes advantage of XML Schemas. (We’ll talk about XML DTDs
and XML Schemas in <a class="xref" href="ch24.html" title="Chapter 24. XML">Chapter 24</a>.) The additional
information is inserted into the <code class="literal"><web-app></code> element:</p><a id="I_15_tt938"/><pre class="programlisting"> <code class="o"><</code><code class="n">web</code><code class="o">-</code><code class="n">app</code>
<code class="n">xmlns</code><code class="o">=</code><code class="s">"http://java.sun.com/xml/ns/j2ee"</code>
<code class="nl">xmlns:</code><code class="n">xsi</code><code class="o">=</code><code class="s">"http://www.w3.org/2001/XMLSchema-instance"</code>
<code class="nl">xsi:</code><code class="n">schemaLocation</code><code class="o">=</code><code class="err">"</code><code class="nl">http:</code><code class="c1">//java.sun.com/xml/ns/j2ee</code>
<code class="nl">http:</code><code class="c1">//java.sun.com/xml/ns/j2ee/web-app_2_5.xsd”</code>
<code class="n">version</code><code class="o">=</code><code class="err">”</code><code class="mf">2.5</code><code class="err">”</code><code class="o">></code></pre><p>If you leave them out, the application may still run, but it will
be harder for the servlet container to detect errors in your
configuration and give you clear error messages.</p><p>The equivalent of the preceding servlet declaration and mapping
is, as we saw earlier, our one line annotation:</p><a id="I_programlisting15_id780311"/><pre class="programlisting"><code class="nd">@WebServlet</code><code class="o">(</code><code class="n">urlPatterns</code><code class="o">={</code><code class="s">"/hello"</code><code class="o">,</code> <code class="s">"/hola"</code><code class="o">})</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">HelloClient</code> <code class="kd">extends</code> <code class="n">HttpServlet</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>Here the <code class="literal">WebServlet</code> attribute
<a id="I_indexterm15_id780326" class="indexterm"/><code class="literal">urlPatterns</code> allows us
to specify one or more URL patterns that are the equivalent to the
<code class="literal">url-pattern</code> declaration in the
<span class="emphasis"><em>web.xml.</em></span><a id="I_indexterm15_id780345" class="indexterm"/><a id="I_indexterm15_id780352" class="indexterm"/><a id="I_indexterm15_id780359" class="indexterm"/></p></div><div class="sect2" title="URL Pattern Mappings"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-15-SECT-3.2"/>URL Pattern Mappings</h2></div></div></div><p><a id="idx10873" class="indexterm"/> <a id="idx10874" class="indexterm"/> <a id="idx10884" class="indexterm"/> <a id="idx10906" class="indexterm"/>The <a id="I_indexterm15_id780423" class="indexterm"/><code class="literal"><url-pattern></code>
specified in the previous example was a simple string, <code class="literal">/hello</code>. For this pattern, only an exact match
of the base URL followed by <code class="literal">/hello</code>
would invoke our servlet. The <code class="literal"><url-pattern></code> tag is capable of more
powerful patterns, however, including wildcards. For example, specifying
a <code class="literal"><url-pattern></code> of <code class="literal">/hello*</code> allows our servlet to be invoked by
URLs such as
<span class="emphasis"><em>http://www.oreilly.com/learningjava/helloworld</em></span> or
<code class="literal">.../hellobaby</code>. You can even specify
wildcards with extensions (e.g., <code class="literal">*.html</code> or <code class="literal">*.foo</code>, meaning that the servlet is invoked for
any path that ends with those characters).</p><p>Using wildcards can result in more than one match. Consider URLs
ending in <code class="literal">/scooby*</code> and <code class="literal">/scoobydoo*</code>. Which should be matched for a URL
ending in <code class="literal">.../scoobydoobiedoo</code>? What
if we have a third possible match because of a wildcard suffix extension
mapping? The rules for resolving these are as follows.</p><p>First, any exact match is taken. For example, <code class="literal">/hello</code> matches the <code class="literal">/hello</code> URL pattern in our example regardless
of any additional <code class="literal">/hello*</code>. Failing
that, the container looks for the longest prefix match. So <code class="literal">/scoobydoobiedoo</code> matches the second pattern,
<code class="literal">/scoobydoo*</code>, because it is longer and
presumably more specific. Failing any matches there, the container looks
at wildcard suffix mappings. A request ending in <code class="literal">.foo</code> matches a <code class="literal">*.foo</code> mapping at this point in the process.
Finally, failing any matches there, the container looks for a default,
catchall mapping named <code class="literal">/*</code>. A servlet
mapped to <code class="literal">/*</code> picks up anything
unmatched by this point. If there is no default servlet mapping, the
request fails with a “404 not found” message.<a id="I_indexterm15_id780566" class="indexterm"/><a id="I_indexterm15_id780573" class="indexterm"/><a id="I_indexterm15_id780580" class="indexterm"/><a id="I_indexterm15_id780587" class="indexterm"/></p></div><div class="sect2" title="Deploying HelloClient"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-15-SECT-3.3"/>Deploying HelloClient</h2></div></div></div><p><a id="idx10850" class="indexterm"/> <a id="idx10880" class="indexterm"/> <a id="idx10902" class="indexterm"/>Once you’ve deployed the <code class="literal">HelloClient</code> servlet, it should be easy to add
examples to the WAR as you work with them in this chapter. In this
section, we’ll show you how to build a WAR by hand. In “Building WAR
Files with Ant” later in this chapter, we’ll show a more realistic way
to manage your applications using the popular build tool, Ant. You can
also grab the full set of examples, along with their source code, in the
<span class="emphasis"><em>learningjava.war</em></span> file from this
book’s website at <a class="ulink" href="http://oreil.ly/Java_4E">http://oreil.ly/Java_4E</a>.</p><p>To create the WAR by hand, we first create the
<span class="emphasis"><em>WEB-INF</em></span> and <span class="emphasis"><em>WEB-INF/classes</em></span>
directories. If you are using a <span class="emphasis"><em>web.xml</em></span> file, place
it into <span class="emphasis"><em>WEB-INF</em></span>. Put the
<span class="emphasis"><em>HelloClient.class</em></span> into
<span class="emphasis"><em>WEB-INF/classes</em></span>. Use the <a id="I_indexterm15_id780691" class="indexterm"/><span class="emphasis"><em>jar</em></span> command to create
<span class="emphasis"><em>learningjava.war</em></span> (WEB-INF at the “top” level of the
archive):</p><a id="I_15_tt939"/><pre class="programlisting"> <code class="n">$</code> <strong class="userinput"><code><code class="n">jar</code> <code class="n">cvf</code> <code class="n">learningjava</code><code class="o">.</code><code class="na">war</code> <code class="n">WEB</code><code class="o">-</code><code class="n">INF</code></code></strong></pre><p>You can also include documents and other resources in the WAR by
adding their names after the <span class="emphasis"><em>WEB-INF</em></span> directory.
This command produces the file <span class="emphasis"><em>learningjava.war</em></span>.
You can verify the contents using the <span class="emphasis"><em>jar</em></span>
command:</p><a id="I_15_tt940"/><pre class="programlisting"> <code class="n">$</code> <strong class="userinput"><code><code class="n">jar</code> <code class="n">tvf</code> <code class="n">learningjava</code><code class="o">.</code><code class="na">war</code></code></strong>
<code class="n">document1</code><code class="o">.</code><code class="na">html</code>
<code class="n">WEB</code><code class="o">-</code><code class="n">INF</code><code class="o">/</code><code class="n">web</code><code class="o">.</code><code class="na">xml</code>
<code class="n">WEB</code><code class="o">-</code><code class="n">INF</code><code class="o">/</code><code class="n">classes</code><code class="o">/</code><code class="n">HelloClient</code><code class="o">.</code><code class="na">class</code></pre><p><a id="I_indexterm15_id780746" class="indexterm"/>Now all that is necessary is to drop the WAR into the
correct location for your server. If you have not already, you should
download and install Apache Tomcat. The location for WAR files is the
<a id="I_indexterm15_id780755" class="indexterm"/><span class="emphasis"><em>webapps</em></span> directory within your Tomcat
installation directory. Place your WAR here, and start the server. If
Tomcat is configured with the default port number, you should be able to
point to the <code class="literal">HelloClient</code> servlet with
one of two URLs: <span class="emphasis"><em>http://localhost:8080/learningjava/hello</em></span>
or
<span class="emphasis"><em>http://<em class="replaceable"><code><yourserver></code></em>:8080/learningjava/hello</em></span>,
where <em class="replaceable"><code><yourserver></code></em> is the name or IP
address of your server. If you have trouble, look in the <a id="I_indexterm15_id780789" class="indexterm"/><span class="emphasis"><em>logs</em></span> directory of the Tomcat folder
for errors.</p><div class="sect3" title="Reloading web apps"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-15-SECT-3.3.1"/>Reloading web apps</h3></div></div></div><p><a id="idx10856" class="indexterm"/> <a id="idx10886" class="indexterm"/>All servlet containers are supposed to provide a
facility for reloading WAR files; many support reloading of individual
servlet classes after they have been modified. Reloading WARs is part
of the servlet specification and is especially useful during
development. Support for reloading web apps varies from server to
server. Normally, all that you have to do is drop a new WAR in place
of the old one in the proper location (e.g., the
<span class="emphasis"><em>webapps</em></span> directory for Tomcat) and the container
shuts down the old application and deploys the new version. This works
in Tomcat when the “autoDeploy” attribute is set (it is on by default)
and also in BEA’s WebLogic application server when it is configured in
development mode.</p><p>Some servers, including Tomcat, “explode” WARs by unpacking them
into a directory under the <span class="emphasis"><em>webapps</em></span> directory, or
they allow you explicitly to configure a root directory (or “context”)
for your unpacked web app through their own configuration files. In
this mode, they may allow you to replace individual files, which can
be especially useful for tweaking HTML or JSPs. Tomcat automatically
reloads WAR files when they change them (unless configured not to), so
all you have to do is drop an updated WAR over the old one and it will
redeploy it as necessary. In some cases, it may be necessary to
restart the server to make all changes take effect. When in doubt,
shut down and restart.</p><p>Tomcat also provides a client-side “deployer” package that
integrates with Ant to automate building, deploying, and redeploying
applications. We’ll discuss Ant later in this chapter.<a id="I_indexterm15_id780860" class="indexterm"/><a id="I_indexterm15_id780867" class="indexterm"/><a id="I_indexterm15_id780874" class="indexterm"/><a id="I_indexterm15_id780881" class="indexterm"/><a id="I_indexterm15_id780888" class="indexterm"/></p></div></div><div class="sect2" title="Error and Index Pages"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-15-SECT-3.4"/>Error and Index Pages</h2></div></div></div><p><a id="idx10848" class="indexterm"/> <a id="idx10881" class="indexterm"/> <a id="idx10903" class="indexterm"/>One of the finer points of writing a professional-looking
web application is taking care to handle errors well. Nothing annoys a
user more than getting a funny-looking page with some technical
mumbo-jumbo error information on it when he expected the receipt for his
Christmas present. Through the <span class="emphasis"><em>web.xml</em></span> file, it is
possible to specify documents or servlets to handle error pages that are
shown for various conditions, as well as the special case of
<span class="emphasis"><em>welcome files</em></span> (index files) that are invoked for
paths corresponding to directories. At this time, there is no
corresponding way to declare error pages or welcome files using
annotations.</p><p>You can designate a page or servlet that can handle various HTTP
error status codes, such as “404 Not Found” and “403 Forbidden,” using
one or more <a id="I_indexterm15_id780959" class="indexterm"/><code class="literal"><error-page></code>declarations:</p><a id="I_15_tt941"/><pre class="programlisting"> <code class="o"><</code><code class="n">web</code><code class="o">-</code><code class="n">app</code><code class="o">></code>
<code class="o">...</code>
<code class="o"><</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code>
<code class="o"><</code><code class="n">error</code><code class="o">-</code><code class="n">code</code><code class="o">></code><code class="mi">404</code><code class="o"></</code><code class="n">error</code><code class="o">-</code><code class="n">code</code><code class="o">></code>
<code class="o"><</code><code class="n">location</code><code class="o">>/</code><code class="n">notfound</code><code class="o">.</code><code class="na">html</code><code class="o"></</code><code class="n">location</code><code class="o">></code>
<code class="o"></</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code>
<code class="o"><</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code>
<code class="o"><</code><code class="n">error</code><code class="o">-</code><code class="n">code</code><code class="o">></code><code class="mi">403</code><code class="o"></</code><code class="n">error</code><code class="o">-</code><code class="n">code</code><code class="o">></code>
<code class="o"><</code><code class="n">location</code><code class="o">>/</code><code class="n">secret</code><code class="o">.</code><code class="na">html</code><code class="o"></</code><code class="n">location</code><code class="o">></code>
<code class="o"></</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code></pre><p>Additionally, you can designate error pages based on Java
exception types that may be thrown from the servlet. For example:</p><a id="I_15_tt942"/><pre class="programlisting"> <code class="o"><</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code>
<code class="o"><</code><code class="n">exception</code><code class="o">-</code><code class="n">type</code><code class="o">></code><code class="n">java</code><code class="o">.</code><code class="na">lang</code><code class="o">.</code><code class="na">IOException</code><code class="o"></</code><code class="n">exception</code><code class="o">-</code><code class="n">type</code><code class="o">></code>
<code class="o"><</code><code class="n">location</code><code class="o">>/</code><code class="n">ioexception</code><code class="o">.</code><code class="na">html</code><code class="o"></</code><code class="n">location</code><code class="o">></code>
<code class="o"></</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code></pre><p>This declaration catches any <a id="I_indexterm15_id781005" class="indexterm"/><code class="literal">IOException</code>s generated
from servlets in the web app and displays the
<span class="emphasis"><em>ioexception.html</em></span> page. If no matching exceptions
are found in the <code class="literal"><error-page></code>
declarations, and the exception is of type <a id="I_indexterm15_id781026" class="indexterm"/><code class="literal">ServletException</code> (or a
subclass), the container makes a second try to find the correct handler.
It looks for a wrapped exception (the “cause” exception) contained in
the <code class="literal">ServletException</code> and attempts to
match it to an error page declaration.</p><p>In the Servlet 3.0 API, you can also designate a catchall error
page that will handle any unhandled error codes and exception types as
follows:</p><a id="I_programlisting15_id781050"/><pre class="programlisting"> <code class="o"><</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code>
<code class="o"><</code><code class="n">location</code><code class="o">>/</code><code class="n">anyerror</code><code class="o">.</code><code class="na">html</code><code class="o"></</code><code class="n">location</code><code class="o">></code>
<code class="o"></</code><code class="n">error</code><code class="o">-</code><code class="n">page</code><code class="o">></code></pre><p>As we’ve mentioned, you can use a servlet to handle your error
pages, just as you can use a static document. In fact, the container
supplies several helpful pieces of information to an error-handling
servlet, which the servlet can use in generating a response. The
information is made available in the form of servlet request attributes
through the method <code class="literal">getAttribute()</code>:</p><a id="I_15_tt943"/><pre class="programlisting"> <code class="n">Object</code> <code class="n">requestAttribute</code> <code class="o">=</code> <code class="n">servletRequest</code><code class="o">.</code><code class="na">getAttribute</code><code class="o">(</code><code class="s">"name"</code><code class="o">);</code></pre><p>Attributes are like servlet parameters, except that they can be
arbitrary objects. We have seen attributes of the <code class="literal">ServletContext</code> in <a class="xref" href="ch15s02.html#learnjava3-CHP-15-SECT-2.11" title="The ServletContext API">The ServletContext API</a> section. In this case, we are
talking about attributes of the request. When a servlet (or JSP or
filter) is invoked to handle an error condition, the following string
attributes are set in the request:</p><a id="I_15_tt944"/><pre class="programlisting"> <code class="n">javax</code><code class="o">.</code><code class="na">servlet</code><code class="o">.</code><code class="na">error</code><code class="o">.</code><code class="na">servlet_name</code>
<code class="n">javax</code><code class="o">.</code><code class="na">servlet</code><code class="o">.</code><code class="na">error</code><code class="o">.</code><code class="na">request_uri</code>
<code class="n">javax</code><code class="o">.</code><code class="na">servlet</code><code class="o">.</code><code class="na">error</code><code class="o">.</code><code class="na">message</code></pre><p>Depending on whether the <a id="I_indexterm15_id781105" class="indexterm"/><code class="literal"><error-page></code>
declaration was based on an <a id="I_indexterm15_id781119" class="indexterm"/><code class="literal"><error-code></code> or
<a id="I_indexterm15_id781133" class="indexterm"/><code class="literal"><exception-type></code>
condition, the request also contains one of the following two
attributes:</p><a id="I_15_tt945"/><pre class="programlisting"> <code class="c1">// status code Integer or Exception object</code>
<code class="n">javax</code><code class="o">.</code><code class="na">servlet</code><code class="o">.</code><code class="na">error</code><code class="o">.</code><code class="na">status_code</code>
<code class="n">javax</code><code class="o">.</code><code class="na">servlet</code><code class="o">.</code><code class="na">error</code><code class="o">.</code><code class="na">exception</code></pre><p>In the case of a status code, the attribute is an <code class="literal">Integer</code> representing the code. In the case of
the exception type, the object is the actual instigating
exception.</p><p>Indexes for directory paths can be designated in a similar way.
Normally, when a user specifies a directory URL path, the web server
searches for a default file in that directory to be displayed. The most
common example of this is the ubiquitous <span class="emphasis"><em>index.html</em></span>
file. You can designate your own ordered list of files to look for by
adding a <a id="I_indexterm15_id781175" class="indexterm"/><code class="literal"><welcome-file-list></code> entry to your
<span class="emphasis"><em>web.xml</em></span> file. For example:</p><a id="I_15_tt946"/><pre class="programlisting"> <code class="o"><</code><code class="n">welcome</code><code class="o">-</code><code class="n">file</code><code class="o">-</code><code class="n">list</code><code class="o">></code>
<code class="o"><</code><code class="n">welcome</code><code class="o">-</code><code class="n">file</code><code class="o">></code><code class="n">index</code><code class="o">.</code><code class="na">html</code><code class="o"></</code><code class="n">welcome</code><code class="o">-</code><code class="n">file</code><code class="o">></code>
<code class="o"><</code><code class="n">welcome</code><code class="o">-</code><code class="n">file</code><code class="o">></code><code class="n">index</code><code class="o">.</code><code class="na">htm</code><code class="o"></</code><code class="n">welcome</code><code class="o">-</code><code class="n">file</code><code class="o">></code>
<code class="o"></</code><code class="n">welcome</code><code class="o">-</code><code class="n">file</code><code class="o">-</code><code class="n">list</code><code class="o">></code></pre><p><code class="literal"><welcome-file-list></code>
specifies that when a partial request (directory path) is received, the
server should search first for a file named
<span class="emphasis"><em>index.html</em></span> and, if that is not found, a file called
<span class="emphasis"><em>index.htm</em></span>. If none of the specified welcome files
is found, it is left up to the server to decide what kind of page to
display. Servers are generally configured to display a directory-like
listing or to produce an error message.<a id="I_indexterm15_id781220" class="indexterm"/><a id="I_indexterm15_id781227" class="indexterm"/><a id="I_indexterm15_id781234" class="indexterm"/></p></div><div class="sect2" title="Security and Authentication"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-15-SECT-3.5"/>Security and Authentication</h2></div></div></div><p><a id="I_indexterm15_id781248" class="indexterm"/> <a id="I_indexterm15_id781257" class="indexterm"/>One of the most powerful features of web app deployment
with the Servlet API is the ability to define <span class="emphasis"><em>declarative
security</em></span> constraints, meaning that you can spell out in the
<span class="emphasis"><em>web.xml</em></span> file exactly which areas of your web app
(URL paths to documents, directories, servlets, etc.) are
login-protected, the types of users allowed access to them, and the
class of security protocol required for communications. It is not
necessary to write code in your servlets to implement these basic
security procedures.</p><p>There are two types of entries in the <span class="emphasis"><em>web.xml</em></span>
file that control security and authentication. First are the <a id="I_indexterm15_id781287" class="indexterm"/><code class="literal"><security-constraint></code> entries, which
provide authorization based on user roles and secure transport of data,
if desired. Second is the <a id="I_indexterm15_id781302" class="indexterm"/><code class="literal"><login-config></code>
entry, which determines the kind of authentication used for the web
application.</p></div><div class="sect2" title="Protecting Resources with Roles"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-15-SECT-3.6"/>Protecting Resources with Roles</h2></div></div></div><p><a id="idx10857" class="indexterm"/> <a id="idx10883" class="indexterm"/> <a id="idx10905" class="indexterm"/>Let’s take a look at a simple example. The following
<span class="emphasis"><em>web.xml</em></span> excerpt defines an area called “Secret
documents” with a URL pattern of <a id="I_indexterm15_id781368" class="indexterm"/><span class="emphasis"><em>/secret/*</em></span> and designates that only
users with the role “secretagent”
may access them. It specifies the simplest form of login process: the
BASIC authentication model, which causes the browser to prompt the user
with a simple pop-up username and password dialog box:</p><a id="I_15_tt947"/><pre class="programlisting"> <code class="o"><</code><code class="n">web</code><code class="o">-</code><code class="n">app</code><code class="o">></code>
<code class="o">...</code>
<code class="o"><</code><code class="n">security</code><code class="o">-</code><code class="n">constraint</code><code class="o">></code>
<code class="o"><</code><code class="n">web</code><code class="o">-</code><code class="n">resource</code><code class="o">-</code><code class="n">collection</code><code class="o">></code>
<code class="o"><</code><code class="n">web</code><code class="o">-</code><code class="n">resource</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">Secret</code> <code class="n">documents</code><code class="o"></</code><code class="n">web</code><code class="o">-</code><code class="n">resource</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"><</code><code class="n">url</code><code class="o">-</code><code class="n">pattern</code><code class="o">>/</code><code class="n">secret</code><code class="o">/*</</code><code class="n">url</code><code class="o">-</code><code class="n">pattern</code><code class="o">></code>
<code class="o"></</code><code class="n">web</code><code class="o">-</code><code class="n">resource</code><code class="o">-</code><code class="n">collection</code><code class="o">></code>
<code class="o"><</code><code class="n">auth</code><code class="o">-</code><code class="n">constraint</code><code class="o">></code>
<code class="o"><</code><code class="n">role</code><code class="o">-</code><code class="n">name</code><code class="o">></code><code class="n">secretagent</code><code class="o"></</code><code class="n">role</code><code class="o">-</code><code class="n">name</code><code class="o">></code>
<code class="o"></</code><code class="n">auth</code><code class="o">-</code><code class="n">constraint</code><code class="o">></code>
<code class="o"></</code><code class="n">security</code><code class="o">-</code><code class="n">constraint</code><code class="o">></code>
<code class="o"><</code><code class="n">login</code><code class="o">-</code><code class="n">config</code><code class="o">></code>
<code class="o"><</code><code class="n">auth</code><code class="o">-</code><code class="n">method</code><code class="o">></code><code class="n">BASIC</code><code class="o"></</code><code class="n">auth</code><code class="o">-</code><code class="n">method</code><code class="o">></code>
<code class="o"></</code><code class="n">login</code><code class="o">-</code><code class="n">config</code><code class="o">></code></pre><p>Each <a id="I_indexterm15_id781402" class="indexterm"/><code class="literal"><security-constraint></code> block has one
<a id="I_indexterm15_id781416" class="indexterm"/><code class="literal"><web-resource-collection></code> section that
designates a named list of URL patterns for areas of the web app,
followed by an <a id="I_indexterm15_id781431" class="indexterm"/><code class="literal"><auth-constraint></code>
section listing user roles that are allowed to access those
areas.</p><p>We can do the equivalent configuration for a given servlet using
the SecurityServlet annotation with an <a id="I_indexterm15_id781449" class="indexterm"/><code class="literal">HttpConstraint</code>
annotation element as follows:</p><a id="I_programlisting15_id781463"/><pre class="programlisting"><code class="nd">@ServletSecurity</code><code class="o">(</code>
<code class="nd">@HttpConstraint</code><code class="o">(</code><code class="n">rolesAllowed</code> <code class="o">=</code> <code class="s">"secretagent"</code><code class="o">)</code>
<code class="o">)</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">SecureHelloClient</code> <code class="kd">extends</code> <code class="n">HttpServlet</code>
<code class="o">{</code> <code class="o">...</code></pre><p>You can add this annotation to our test servlet or add the XML
example setup to the <span class="emphasis"><em>web.xml</em></span> file for the
<span class="emphasis"><em>learningjava.war</em></span> file and prepare to try it out.
However, there is one additional step that you’ll have to take to get
this working: create the user role “secretagent” and an actual user with this role
in our application server environment.</p><p>Access to protected areas is granted to user roles, not individual
users. A user role is effectively just a group of users; instead of
granting access to individual users by name, you grant access to roles,
and users are assigned one or more roles. A user role is an abstraction
from users. Actual user information (name and password, etc.) is handled
outside the sc