1. Home
  2. Tutorials
  3. Java
  4. WAR files
Yolinux.com Tutorial

Java WAR Files:

Java WAR file generation and deployment for use with Tomcat or JBoss. This tutorial covers the typical directory layout for both the source tree and the deployment. The various pitfalls are also covered.

Java WAR file description:

Java Web ARchive files are used to bundle web applications in a "zip" file for use with a Java applications server such as Tomcat or JBoss. The Java WAR file is a Java standard for deployment of a bundled group of JSP, Java servlets, html, javascript, images and other files for necessary for the development of web applications.

The WAR file is generated with the Java "jar" command and follows a directory hierarchy as shown here:

WebAppX/
       /META-INF/MANIFEST.MF
       /WEB-INF/web.xml
       |       /classes/
       |       |       /ServletA.class
       |       |       /ServletB.class
       |       |       /ServletC.class
       |       |       /aa/bb/cc/ServletD.class
       |       |       /com/megacorp/ProjX/
       |       |       |                  /Abc.class
       |       |       |                  /Ijk.class
       |       /tags/
       /lib/
       |   /filea.jar
       |   /fileb.jar
       |   /filec.jar
       /index.html
       /my.css
       /images/my.png
       /xxx.jsp
       /yyy.jsp
       /zzz.jsp
Note:
  • /META-INF: This directory and its contents are generated by the "jar" command. Does not have to be explicitly generated.
    • /META-INF/services: contents of jar file
    • /META-INF/MANIFEST.MF: only one manifest
  • /WEB-INF: Required for servlet support and any class files to be called by JSP or servlets. There is only one /WEB-INF. It must be defined at the lot directory in the WAR file and can not be nested to a lower directory.
  • /WEB-INF/web.xml: Required only to register servlets.
  • Once deployed, this web application would be called using the URL http://localhost:8080/WebAppX/
  • Servlet URLs: http://localhost:8080/WebAppX/ServletA is mapped from its class name to its URL name by the web.xml file.
    ServletC mapping to URL: http://localhost:8080/WebAppX/ServletC

WAR File Creation:

Command: jar cf WebAppX.war .
Where this command is executed in the same directory which contains the index.html (or index.jsp) and WEB-INF directory.

Also see the jar man page


WAR file and Servlets:

Where the file /WEB-INF/web.xml maps the servlet name to the URL display name.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>
  <display-name>Welcome to our server</display-name>
  <description>Welcome to our server</description>
  <servlet>
    <servlet-name>Servlet-A</servlet-name>
    <servlet-class>ServletA</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>Servlet-B</servlet-name>
    <servlet-class>ServletB</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>Servlet-C</servlet-name>
    <servlet-class>aa.bb.cc.ServletC</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Servlet-A</servlet-name>
    <url-pattern>/ServletA</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Servlet-B</servlet-name>
    <url-pattern>/ServletB</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Servlet-C</servlet-name>
    <url-pattern>/ServletC</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>
</web-app>
Note that this example shows a web.xml file defining three separate servlets to be deployed in the WAR file.

Where XML tags must appear in the following order:
  • <context-param>
  • <filter>
  • <filter-mapping>
  • <listener>
  • <servlet>
  • <servlet-mapping>
  • <session-config>
  • <mime-mapping>
  • <welcome-file-list>
  • <error-page>
  • <taglib>
  • <resource-env-ref>
  • <resource-ref>
  • <security-constraint>
  • <login-config>
  • <security-role>
  • <env-entry>
  • <ejb-ref>
  • <ejb-local-ref>

Note that the following will NOT work:

<servlet>
..
</servlet>

<servlet-mapping>
..
</servlet-mapping>

<servlet>
..
</servlet>

<servlet-mapping>
..
</servlet-mapping>

Must order all <servlet> tags together then <servlet-mapping>, etc

When not ordered properly you will get the error:
Caused by: org.xml.sax.SAXException: The content of element type "web-app" must match ...

Example servlet:

import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletA extends HttpServlet
{
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
                       throws ServletException, IOException
   {
      doit(request, response);
   }

   protected void doPost(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
   {
      doit(request, response);
   }

   /**
    * Class description goes here
    * 
    * @param request
    * @param response
    * @throws ServletException
    * @throws IOException
    */
   protected void doit(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException
   {
      String value = request.getParameter("param-name");

      ...
      ...
   }
}

JSP call to class in WAR file:

<%@ page language="java" import="com.megacorp.YYY.XXX.Abc" %>
<%
Abc abc = new Abc();
String sss = abc.methodA(argx);
...
%>
[Potential Pitfall]: incorrect object instantiation
Error: Abc abc = new Abc;
Syntax error on token "new", delete this token
Fix: Abc abc = new Abc();

Ant file to generate a WAR file:

file: build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="ProjX" default="all" basedir=".">
    <description>Builds, tests, and runs the project ProjX.</description>
    <property name="build.dir" value="./"/>
    <property name="lib.src.dir" location="${build.dir}/src/lib"/>
    <property name="servlets.src.dir" location="${build.dir}/src/servlets"/>

    <!-- Classpath to find servlet and java packages -->
    <path id="classpath.base">
      <pathelement location="/usr/java/latest/lib/tools.jar" />
      <pathelement location="/opt/jboss-6.0.0.20100721-M4/lib/jbosssx.jar" />
      <pathelement location="/opt/jboss-6.0.0.20100721-M4/client/jboss-servlet-api_3.0_spec.jar" />
    </path>

    <target name="usage">
       <echo message="Available targets are:"/>
       <echo message="clean            - Remove WebAppX.war and class files."/>
       <echo message="war              - Generate war file to deploy to JBoss."/>
       <echo message="war-deploy       - Copy war file to JBoss war file deployment directory."/>
    </target>

    <target name="clean" description="Remove .class and .jar files">
       <delete includeEmptyDirs="true" failonerror="false">
          <fileset dir="${servlets.src.dir}">
             <include name="**/*.class"/>
          </fileset>
          <fileset dir="${lib.src.dir}">
             <include name="**/*.class"/>
          </fileset>
          <fileset dir="WEB-INF/classes">
             <include name="**/*.class"/>
          </fileset>
          <fileset dir="./">
             <include name="WebAppX.war"/>
          </fileset>
    </target>

    <target name="compile-war-lib">
      <mkdir dir="WEB-INF/classes"/>
      <javac srcdir="${lib.src.dir}" destdir="WEB-INF/classes" debug="true" includeAntRuntime="false">
          <classpath refid="classpath.base"/>
          <include name="**/*.java"/>
      </javac>
    </target>

    <target name="compile-war" depends="compile-war-lib">
      <mkdir dir="WEB-INF/classes"/>
      <javac srcdir="${servlets.src.dir}" destdir="WEB-INF/classes" debug="true" includeAntRuntime="false">
          <classpath refid="classpath.base"/>
          <classpath refid="classpath.lib" />
          <include name="**/*.java"/>
      </javac>
    </target>

    <target name="war" depends="compile-war,other-dependencies-go-here">
       <war destfile="WebAppX.war" webxml="WEB-INF/web.xml">
          <fileset dir="./">
             <include name="**/*.jsp"/>
             <include name="**/*.css"/>
             <include name="**/*.png"/>
             <include name="index.html"/>
             <include name="WEB-INF/**/*.class"/>
             <exclude name="**/.svn/**"/>
             <exclude name="test/**"/>
             <exclude name="src/**"/>
          </fileset>
       </war>
    </target>

    <target name="war-deploy" depends="war" description="Deploy application as a WAR file">
       <copy todir="${deploy.dir}" preservelastmodified="true">
          <fileset dir=".">
             <include name="*.war"/>
          </fileset>
       </copy>
    </target>

    <target name="all" depends="war" />

</project>
Note the use of the <war> ant task. The <jar> ant task can also be used to generate a WAR file but jar is more work as the user must specify much more detailed information.

Given the following source tree:
ProjX/src/servlets/ServletA.java
     |   |        /ServletB.java
     |   /lib/com/megacorp/YYY/XXX/Abc.java
     |   |                        /Ijk.java
     /deploy/WebAppX/
                    /index.html
                    /xxx.jsp
                    /WEB-INF/web.xml
                    |       /classes/
                    |       |       /ServletA.class
                    |       |       /ServletB.class
                    |       |       /com/megacorp/YYY/XXX/Abc.class
                    |       |       |                    /Ijk.class
                    /...

or some put the source in deployed folders and let ant pick what is needed to assemble the WAR file:
ProjX/WebAppX/index.html
             /xxx.jsp
             /WEB-INF/web.xml
             |       /classes/
             |       |       /ServletA.class
             |       |       /ServletB.class
             |       |       /src/
             |       |       /src/servlets/ServletA.java
             |       |       /src/servlets/ServletB.java
             |       |       /src/com/megacorp/YYY/XXX/Abc.java
             |       |       |                        /Ijk.java
             |       |       /com/megacorp/YYY/XXX/Abc.class
             |       |       |                    /Ijk.class

WAR File Deployment:

Tomcat:

Copy the WAR file to $CATALINA_HOME/webapps/WebAppX.war

Where that resolves to (RHEL6 RPM package): /var/lib/tomcat6/webapps/
Tomcat 8 Apache binary download installation: /opt/apache-tomcat-8.0.0-RC1/webapps/

JBoss:

Simply copy the WAR file to $JBOSS_HOME/server/default/deploy/WebAppX.war

Exploded WAR files: Note that the WAR file can be "un-jar'ed" and expanded on the file system.

$JBOSS_HOME/server/default/deploy/WebAppX.war/WEB-INF/web.xml
                                                     /classes/
Sometimes this eases JSP development but can cause servlet complications as well. The JBoss server will not recognize servlet updates and you need to restart the JBoss server in order to pick up the changes. JSP development is simplified as JSP pages can be edited in place and tried immediately.
Use the URL http://localhost:8080/WebAppX/file.jsp

Individual JSP pages can also be developed in the default WAR directory:
$JBOSS_HOME/server/default/deploy/ROOT.war/file.jsp
Use the URL http://localhost:8080/file.jsp

Example:

Hello World Tomcat servlet example WAR file:

Directory set-up:
  • mkdir -p src/main/java/com/megacorp/projectx
  • mkdir -p src/main/webapp/WEB-INF

File: src/main/java/com/megacorp/projectx/HelloWorld.java
package com.megacorp.projectx;

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet {

    public void doGet(HttpServletRequest request, 
                      HttpServletResponse response)
    throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World!</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Hello World!</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

File: src/main/webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1"
         metadata-complete="true">

    <description>Hello World</description>
    <display-name>Hello World</display-name>

    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>com.megacorp.projectx.HelloWorld</servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld</url-pattern>
    </servlet-mapping>
</web-app>
This associates the class com.megacorp.projectx.HelloWorld to a URL path /HelloWorld

Maven Build File: ./pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.megacorp.projectx</groupId>
  <artifactId>ProjectX</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>projectx</name>
  <url>http://www.megacorp.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.3</version>
        <configuration>
          <warSourceDirectory>src/main/webapp</warSourceDirectory>
          <webappDirectory>/opt/apache-tomcat-9.0.30/webapps/projectx/</webappDirectory>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compile-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

[Potential Pitfall]: Error: package javax.servlet.http does not exist cannot find symbol
POM file requires dependency "javax.servlet-api" to fix this error.

Build:
  • Generate WAR file: mvn package
    This will generate target/Hello-1.0-SNAPSHOT.war
  • Deploy WAR file: mvn install
    This will install the servlet to Tomcat's "webappDirectory" /opt/apache-tomcat-9.0.30/webapps/projectx/
Inspect the contents of the war file: jar tf target/Hello-1.0-SNAPSHOT.war
META-INF/MANIFEST.MF
META-INF/
WEB-INF/
WEB-INF/classes/
WEB-INF/classes/com/
WEB-INF/classes/com/megacorp/
WEB-INF/classes/com/megacorp/projectx/
WEB-INF/classes/com/megacorp/projectx/HelloWorld.class
WEB-INF/web.xml
META-INF/maven/com.megacorp.projectx/Hello/pom.xml
META-INF/maven/com.megacorp.projectx/Hello/pom.properties
Test: http://localhost:8080/projectx/HelloWorld

Links:

Books:

"Core Java 2, Volume 1: Fundamentals "
by Cay S. Horstmann, Gary Cornell
ISBN # 0132354764, Prentice Hall PTR 8th edition

The industry standard. Need I say more?

Amazon.com
"Core Java 2: Volume 2 Advanced Features "
by Cay S. Horstmann, Gary Cornell
ISBN # 0132354799, Prentice Hall PTR 8th edition

The industry standard. Need I say more?

Amazon.com
"Core Java Server Faces"
by David Geary, Cay S. Horstmann
ISBN # 0131738860, Prentice Hall PTR 2nd edition

Amazon.com
"JSP, Servlets, and MySQL"
by David Harms
ISBN # 0764547879, Hungry Minds, Inc

Amazon.com
   
Bookmark and Share

Advertisements