Tutorials / Server Tutorials / Anatomy of a Web App

Anatomy of a Web App

tutorial java server

So far, you’ve run a server using Tomcat or Jetty. You deployed a “hello world” web app to your server, and you’ve visited that web app by navigating to localhost:8080 in your web browser.

This tutorial takes a closer look at how a web app is structured. You’ll need to work with this structure in all of the following tutorials, so make sure you understand it before continuing!

If you’re using embedded Jetty, then you can skip this tutorial.

Webapps Directory

This tutorial assumes you’re either using a Jetty server with its own jetty-base directory, or a Tomcat server.

Both of these servers contain a webapps directory, which is where your code will go.

The rest of this tutorial walks through building what you’ll put in the webapps directory.

Example Project

You can see an example project that uses the command line to package a web app here, and you can download it as a .zip file here.

This section of the tutorial walks through this example project.

Servlets

You’ll learn more about servlets in the servlets tutorial, but for now, all you need to know is that a servlet is a Java class that runs code on a server when the user accesses a certain URL.

For example, here’s a hello world servlet class:

package io.happycoding;

import java.io.IOException;

import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    response.setContentType("text/html;");
    response.getWriter().println("<h1>Hello world!</h1>");
  }
}

This servlet uses the @WebServlet annotation to map to the /hello URL and writes a hard-coded <h1>Hello world!</h1> message to the response.

To include this servlet in your web app, you need to compile it and put the generated .class file in a specific directory. Keep reading to learn more!

Anatomy of a Web App

Each web app is a folder that contains files in a certain directory structure. The structure should be like this:

  • Web App Name
    • Static files like index.html, script.js, and styles.css go here
    • WEB-INF/
      • classes
        • Compiled server .class files go into packages here

For example, you might have a HelloWorld webapp directory that looks like this:

  • HelloWorld
    • index.html
    • WEB-INF/
      • classes
        • /io/happycoding/servlets/
          • HelloWorldServlet.class

Remember that you can also use root as the web app’s name to make it the “top level” web app without including its name in its URL.

Command Line

I don’t recommend trying to build your code directly from the command line, but doing it this way at first can help you understand how everything fits together.

You can manually create the above directory structure by creating folders and copying files into them. But how do you compile your servlet classes?

The HelloWorldServlet class references a few classes in the jakarta package. Where do those classes come from?

Both Jetty and Tomcat come with a lib directory, which contains all of the .jar files you need to build your server code, including the jar file that contains the jakarta package. To compile your server classes, you’d use that lib directory as your classpath, using the -cp argument.

You can compile your server code with one of these commands, depending on whether you’re using Jetty or Tomcat:

Jetty

javac -cp /path/to/jetty/lib/* /path/to/your/code/YourClass.java

For example, I would run this command:

javac -cp C:/Users/kevin/Desktop/jetty-home-11.0.5\lib\* io/happycoding/servlets/HelloWorldServlet.java

Tomcat

javac -cp /path/to/tomcat/lib/* /path/to/your/code/YourClass/java

For example, I would run this command:

javac -cp C:\Users\kevin\Desktop\apache-tomcat-10.0.7\lib\* io/happycoding/servlets/HelloWorldServlet.java

In either case, you should now have a .class file for the class you compiled, which you can include in the web app directory structure outlined above.

You can now copy your whole web app directory into the webapps directory of your server, run your server, and then navigate to http://localhost:8080/YourWebAppName/ to view your web app!

War Files

Now you know how to create a web app directory, which contains all of the files you need to serve your website, including the HTML files and the Java classes that run on the server.

Another common way to package your web app is into a .war file, which is a lot like a .zip file, or a .jar file. A .war file is a Web Application Resource (or a Web Archive, depending on who you ask) which collects an entire web app directory into a single file. This is handy for deploying to live servers, because you only need to upload a single .war file instead of a whole directory.

To create a .war file, cd into your web app directory (after compiling all of your classes) and then run this command:

jar -cfv YourWebAppName.war *

This runs the jar command, and the -cvf argument tells it to create a file and to verbosely print information about what it’s doing. Then YourWebAppName.war tells it to create a .war file, and * tells it to add all of the files and folders from the current directory.

That should give you a YourWebappName.war file. You can move that file into the webapps directory of your server, just like you could move the whole directory. Your server will automatically extract your web app into its own directory.

The .war format is commonly used by many live servers. If you can create a .war file, then you can deploy a live server to places like Amazon Web Services.

Maven

You can follow the above steps to build your web app using the command line to compile your classes and to create a .war file, but that’s going to get pretty annoying, especially as you start using other libraries.

Maven is a tool that manages your classpath for you, and makes it easier to compile and build (and eventually deploy) your server. To use Maven, first download and install it from here.

Example Project

You can see an example project that uses Maven to deploy package a web app here, and you can download it as a .zip file here.

The rest of this tutorial walks through this example project.

Directory Structure

Maven expects a specific directory structure:

  • Web App Name
    • pom.xml
    • src/
      • main/
        • java/
          • Java packages and classes go here
        • webapp/
          • Static files like index.html, script.js, and styles.css go here

For example, you might have a HelloWorld webapp directory that looks like this:

  • HelloWorld
    • pom.xml
    • src/
      • main/
        • java/
          • io/happycoding/servlets/
            • HelloWorldServlet.java
        • webapp/
          • index.html

pom.xml

Maven uses a pom.xml file to configure a project, including information about the classpath and how to build and package the code. Here’s an example pom.xml file:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>io.happycoding</groupId>
  <artifactId>hello-world-maven</artifactId>
  <version>1</version>
  <packaging>war</packaging>

  <properties>
    <!-- Java 11 -->
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- Jakarta Servlets API -->
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <version>5.0.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <!-- Enable building as a .war file with `mvn package` -->
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.1</version>
      </plugin>
    </plugins>

    <!-- The output .war file's name, which will be the name of the webapp. -->
    <finalName>${project.artifactId}</finalName>
  </build>
</project>

Packaging a Web App

If you put all of that together, you can now compile and build your project by running this command in the same directory that contains the pom.xml file:

mvn package

This command will create a target directory, and in there you’ll see a .war file and a directory with your web app’s name. You can copy either one to your webapps directory to run it locally!

You can go another step further and run your whole server from Maven. See the Jetty and Tomcat deployment pages.


Comments and Questions

Happy Coding is a community of folks just like you learning about coding.
Do you have a comment or question? Post it here!