This FAQ describes how to set up the directory structure of a Web archive or WAR to deploy Java servlets, Java Server Pages (JSPs), and static content. This description assumes that you have already written some JSPs or servlets and that you are trying to figure out how to run them on the server. Under servlet 2.2, JSPs and servlets are put into a directory structure referred to as a Web application archive or WAR. When the WAR is finished, you can compress it into a file with a .war extension, but setting up the files to compress is the hard part. One advantage to the WAR construct is that once a WAR is set up, it can be moved from server to server without further configuration. A good way to begin understanding how to construct a war is to look at a simple example.
Assume that you have a JSP called Hello.jsp
and a
servlet called Hello.java
and that you want to deploy them. You
could set up the following directory structure:
The directory structure begins with a document root directory that has an arbitrary name,
in this case, webApp
. The JSP page can either be in the document root
directory or in any of its subdirectories. In this example, it's in an arbitrary subdirectory
named myJspDir
. The one required subdirectory is called WEB-INF
.
This special directory contains the configuration file web.xml
and
a directory called classes
that contains the compiled servlet classes.
If you are only using JSPs, you do not need
a classes
subdirectory. The servlet server adds the
classes
directory to its CLASSPATH, so the server automatically
finds servlets you placed in that directory.
The last required file is
the web.xml
file. It contains deployment information like name
mappings, parameters, and default file mappings. The web.xml
file in this simple example could contain the following essentially empty file:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> <web-app> <!-- configuration options would go here --> </web-app>
Once you register your web application with your servlet runner, you access the above pages with the following URL's:
The http://your_host section of the URL gets you to your host. When you configure the servlet runner
to run the Web application, you tell it the path to the document root is /tmp/webApp
an the URL prefix is some arbitrary string like /myPrefix. Therefore, every
request with the prefix myPrefix
will be forwarded to the servlet runner which, in turn, looks into your
application. The remainder of the URL for the JSP page corresponds to the
directory structure. You can put *.html
files in the same directory and request
them in a similar manner. The call to the servlet requires using the
reserved word "servlet" in the url. When the servlet server sees the
word "servlet" in the URL, it knows to look for the corresponding class in the classes
subdirectory of the WEB-INF
directory.
Once you get a simple WAR example working, you will probably want to see a more complicated example. There is an example that goes along with this document. Your servlet server probably also comes with an example WAR. Another good source of information about configuring a WAR is the Servlet 2.2 specification. It's easy to read and includes examples. You can download it from the following URL:
http://java.sun.com/products/servlet/download.html
web.xml
File
As mentioned above, the web.xml
file describes a number of
configuration parameters. The web.xml
file in the example
above is empty. It contains no configuration parameters. The following
web.xml
file shows how to do some common configuration
tasks. The tasks are describes by comments in bold.
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> <web-app> <!-- The next two sections define name/class mappings. --> <servlet> <servlet-name>BasicHello</servlet-name> <servlet-class>Hello</servlet-class> <init-param> <param-name>SomeParameter</param-name> <param-value>Parameterized hello from the web.xml file.</param-value> </init-param> </servlet> <servlet> <servlet-name>PackagedHello</servlet-name> <servlet-class>a.b.c.HelloPackage</servlet-class> </servlet> <!-- The next two sections define name/url mappings. --> <servlet-mapping> <servlet-name>BasicHello</servlet-name> <url-pattern>/Hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>PackagedHello</servlet-name> <url-pattern>/Howdy/*</url-pattern> </servlet-mapping> <!-- The next two sections define welcome files and the error page. --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> <welcome-file>myFunkyIndex.htm</welcome-file> </welcome-file-list> <error-page> <error-code>404</error-code> <location>/aDirectory/myFavoriteErrorPage.html</location> </error-page> <!-- This application wide parameter mapping is used to map the / to a page. This parameter is used by the index.jsp page in this example. --> <context-param> <param-name>welcomeServlet</param-name> <param-value>/Hello</param-value> </context-param> </web-app>
The first lines in the web.xml
file map servlet classes to arbitrary names.
For example, the Hello
servlet class is mapped to the name BasicHello. In another
example, the mapped class is in a package. The class file for the HelloPackage
servlet is located at
/someDir/webApps/webApp/WEB-INF/classes/a/b/c/HelloPackage.class
. Once
the servlet classes are mapped to names, the names can link the classes with
arbitrary URL mappings. For example, the HelloPackage
servlet is
mapped to /Howdy/*, so the following URL brings up the servlet:
http://localhost:8010/myPrefix/Howdy/aBigHello
Notice there is no use of the reserved word "servlet" in the URL. Frequently, every servlet in a web application is mapped to a corresponding URL to avoid using the word servlet. This example uses the wildcard * (asterisk), but you can map to specific names. The pattern-matching rules are described in more detail in the servlet specification. For security reasons, a single * is the only supported wildcard.
Everything in this section refers to servlets, but JSPs can be mapped to URLs in the same way. Just use the jsp-file tag instead of the servlet-class tag when you define the servlet.
This section of the web.xml
file defines default pages and the error page.
The welcome-file-list section lists the default pages. There are three
entries there: index.jsp, index.html, and myFunkyIndex.htm. If a URL is called without
a page specified, these are the default pages. As an example, assume a WAR has the following
configuration:
/tmp/webApp/aDirectory
containing a file index.html
.
/tmp/webApp
.
index.html
:
http://localhost:8010/myPrefix/aDirectory
If there was another subdirectory webApp/anotherDir
with the file myFunkyIndex.htm
, a call to the following
would return the contents of myFunkyIndex.htm
:
http://localhost:8010/myPrefix/anotherDirectory
The next section defines the default error page. In this case, the 404 File
Not Found error is mapped to a page called myFavoriteErrorPage.html
in the directory aDirectory
. Bogus URLs will map to this page.
Virtually every application uses parameters that are set in a configuration
file. In the servlet 2.2 model, the parameters used by an application
are included in the web.xml
file. This example web.xml
file includes one parameter set for a servlet and one parameter set for the entire
Web application. The Hello servlet includes a parameter defined
in the block beginning with the init-param tag. The servlet then
gets that value with the following call:
getInitParameter("SomeParameter")The application-wide parameter is defined in the block beginning with the tag context-param. This value can be accessed by any servlet or JSP with the following method call:
getServletContext().getInitParameter( "welcomeServlet" )Servlets talk to each other through the servlet context in a similar manner. For example, if you have a factory class you instantiate on startup and place in the servlet context, then all other servlets can access that factory object through servlet context. A full discussion of JNDI, security, and servlet/EJB communication is beyond the scope of this document, but you should be aware that they are an integral part of servlet 2.2.
While it is not used in this example, the load-on-startup tag is very
useful. Virtually all large Web applications start at least one
servlet that manages services for the rest of the application. That
central servlet might start a database connection pool manager,
verify that an email server is working, test a credit card verification
service, or instantiate objects used by the rest of the servlets.
This tag takes a positive integer as an argument. The number
determines what order the servlets are started in. For more information,
see the web.xml
DTD in the servlet specification. The DTD
includes descriptions of other tags not used here, including tags
that control the security context and references to Enterprise Java Beans.
Mapping the slash to a servlet is an apparently simple problem that requires a somewhat complicated solution. It's a very common task to map the opening page of an application to a servlet. In which case a request to the URL http://foo.com/myPrefix is forwarded to the servlet mapped to http://foo.com/myPrefix/Hello. Note that your application prefix can just be / if you want http://foo.com to go to http://foo.com/Hello.
The most intuitive answer is to simply define a URL mapping
to the URL "/". If you take this approach, the mapping appears to
act like mapping "/*" and every URL not defined in the web.xml
file appears to get the default page. Files like foo.html
are no longer served. This behavior comes from the fact that mapping
the slash takes over the default servlet. This behavior is defined in
the servlet specfication. Because *.html, *.wml, and other static files are handled by
the default servlet, the returned request looks like the page you mapped
to slash.
One good solution to this problem is to use a JSP page in the document root
that forwards the request to your welcome servlet. The server receives the
request for the slash and looks for the welcome-file mappings. It finds
an index.jsp
file and calls it. That JSP file then forwards
the request to your welcome servlet. The advantage to this approach is that
it leaves the default servlet that comes with the server in place. It also
takes advantage of the welcome-file approach defined in the servlet 2.2
specification. An example of this approach is included in the accompanying
WAR example. The index.jsp
in the example can be copied
to any subdirectory and it will forward the request to the default servlet
defined in the web.xml
file.
An important point to note with this approach is the possible security
risk of the default servlet showing directory listings. The Tomcat default
servlet will show a directory listing if an URL refers to a directory
that does not contain a welcome file. If a directory listing will compromise
your site's security, verify that you put an index.jsp
or index.html
in
every directory. For example, assume you have a webApp/media
directory
containing your site's images. Without a welcome file, a call to http://foo.com/myPrefix/media
returns a directory listing of all the images. If you do not want a user to
see that listing, put an index.jsp
or index.html
file in
the media
subdirectory.
web.xml
file
By now you may be wondering if there is some "behind the scenes" web.xml
file that defines default mappings. Yes there is. In Tomcat this file is
org/apache/tomcat/deployment/web.xml
in the JAR file.
In Enhydra, this file can be found in the enhydra.jar
.
You can extract the file from the JAR file using a zip utility or
jar
itself.
Reading this web.xml
file is instructive. For example, there is a mapping
for "/servlet/*" to the ServletInvoker servlet. If you want to see
what the default welcome mappings are, they are listed at the bottom
of the file.
web.xml
file defines hundreds of MIME mappings,
it does not define the MIME mappings used by the WAP protocol. WAP is the
protocol used to transmit content to the micro-browsers in cellular telephones.
If your WAR contains *.wml
and *.wbmp
files, you will want to
add the wireless MIME types to your web.xml
file. The
mappings are given in the web.xml
file in the demonstration
WAR that accompanies this example. With the example running, you can
access the following URL from a cellular phone emulator:
http://localhost:8010/myPrefix/wapPages/Hello.wml
To this point, this FAQ has only described how to add servlets or other
classes to the classes
subdirectory in the WEB-INF
directory. JAR files your application uses are put in the lib
subdirectory of the WEB-INF
directory. The name lib is a
reserved word. From the application server's point of view, it simply
adds the WEB-INF/classes
directory and every *.jar
file
in WEB-INF/lib
to its CLASSPATH. Servlets do not have to
be in the classes
subdirectory. They can be anywhere on
the application server's CLASSPATH if they are mapped in the web.xml
file. Deploying your Web application's servlets in a JAR file in the lib
directory is very common.
Frequently, a web application has an images
or
media
subdirectory that contains
all of the *.gif
or *.jpg
files.
How do you manage this directory during development and deployment?
During development you want the images to be part of your WAR, but at
deployment time you want the Web server to serve them.
Although images and static files can be served from a WAR,
the Web server will serve them more efficiently because Web servers are
written in native code and are optimized to serve static content.
The following steps describe a possible scenario for serving static content from the
WAR during development and the Web server's htdocs
directory after deployment.
images
subdirectory
of the top-level Web application directory.<img src="/images/Enhydra.gif">
WARConfig
directory:
mkdir /tmp/WARconfig
WARconfig.war
to /tmp/WARConig
.
WARConfig
:
cd /tmp/WARconfig
jar xf WARconfig.war
Makefile
to point to
your JDK and Enhydra installation.
make
.
cd ../multiserver
./start
This demo runs on the following ports:
8000 MultiserverAdmin
8010 HTTP connection to demo WAR
8020 Enhydra Director connection to demo WAR
Here are interesting URL's you might want to check out:
The previous information applies to any servlet/JSP container that is servlet 2.2-compliant. This section describes issues that are specific to the Enhydra Multiserver servlet runner.
Servlet
in the web.xml
file, and supplying the application's configuration file as an argument.
If you are using another application server, be sure to put Enhydra's classes
in your CLASSPATH after the server's classes or they will conflict. Here is an example of
the web.xml
settings:
<servlet> <servlet-name>welcome</servlet-name> <servlet-class>org.enhydra.Servlet</servlet-class> <init-param> <param-name>ConfFile</param-name> <param-value>/WelcomeWar/apps/welcome.conf</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>