Creating a simple web application using servlets and JSPs (part 1) Knowledge required to understand the article: You've already more or less figured out Java Core and would like to look at JavaEE technologies and web programming. It would make the most sense for you to be currently studying the Java Collections quest, which deals with topics close to the article.

Creating entities

In the entities package, we'll create a User class that has two private string variables: name and password. Create constructors (default and one that takes both values) and getters/setters, and override the toString() method just in case, along with the equals() and hashCode() methods. In other words, we'll do everything that a respectable Java developer does when creating a class.
public class User {
    private String name;
    private String password;

    public User() {
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (name != null ? !name.equals(user.name) : user.name != null) return false;
        return password != null ? password.equals(user.password) : user.password == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (password != null ? password.hashCode() : 0);
        return result;
    }
}
Now we can start creating a list of users. We'll add users to it, and take users from it to display them. However, we do have one problem. We don't create our servlet objects. Tomcat does this for us. The methods we override in them are already defined for us, and we can't parameters. How then do we create a shared list that will be visible in both our servlets? If we just create a list object in each servlet, then we would be adding users to one list, but displaying users from another in the ListServlet. So we need an object that is shared by both servlets. Generally speaking, we need an object that is shared by all the classes in our program: one object for the entire program. I hope you've heard something about design patterns. For some folks, this may be the first real need for the Singleton pattern in their program. You could go wacko and crank out some sweet Singleton with double checks and synchronization (yep, our application is multithreaded, since Tomcat servlets run on separate threads). But I'm going to use the early initialization technique, because it's entirely adequate for our purposes here.

Creating a model

Create a class (and implement the Singleton pattern) in the model package and call it something unusual. For example, Model. We'll create a private list of users in our class, and implement two method: one to add a user, and another to return a list of strings (usernames). Since our user object consists of a username and password, and we don't want to reveal user passwords, we'll only have a list of names.
public class Model {
    private static Model instance = new Model();

    private List<User> model;

    public static Model getInstance() {
        return instance;
    }

    private Model() {
        model = new ArrayList<>();
    }

    public void add(User user) {
        model.add(user);
    }

    public List<String> list() {
        return model.stream()
                .map(User::getName)
                .collect(Collectors.toList());
    }
}

A bit about MVC

Since you've already heard about singleton, you've probably heard about another design pattern model-view-controller (MVC). Its purpose is to separate business logic from the view. That is, to separate the code that determines what to do from the code that determines how to display stuff. The view is responsible for how data is presented. In our case, the views are our JSP pages. That's precisely why I put them in a folder named views. The model is the data the program actually works with. In our case, this is the users (list of users). And controllers are the link between them. They take data from the model and pass it to the views (or get some data from Tomcat, process it, and pass it to the model). You define your business logic (what the program should do) in them, not in the model or the view. Thus, each part handles its own business:
  • the model stores data;
  • views render beautiful representations of the data;
  • controllers handle data processing.
This allows the program to be quite simple and maintainable, rather than a monstrous heap of all the code in one class. MVC is not only suitable for web programming, but it is used especially often in this area (almost always). In our case, the servlets will act as controllers. This is a very superficial and brief description of the pattern, but MVC is not the main topic of this article. If anyone wants to learn more, Google is your friend! Create a form for adding a user. Add the form to add.jsp. It should consist of two text input fields (one ordinary, the other — a password field) and a button for sending the data to the server.
<form method="post">
    <label>Name:
        <input type="text" name="name"><br />
    </label>

    <label>Password:
        <input type="password" name="pass"><br />
    </label>
    <button type="submit">Submit</button>
</form>
Here the form has a method attribute with the value post. This indicates that the data from this form will go to the server as a POST request. The action attribute is not specified, which means the request will be sent to the same address that we came to this page from (/add). Thus, upon receiving a GET request, our servlet bound to this address returns the JSP with the add-user form. And if it receives a POST request, then we know the form sent its data here (which we extract from the request object in the doPost() method, process, and pass to the model for saving). It's worth noting that input fields have a parameter called name (for usernames, or pass for passwords). This is a very important point. Thus, to receive this data (the username and password that will be entered) from the request (inside the servlet), we'll use these name and pass fields. But more on that later. My button for sending data was again made as a button, not as an output field as is customary. I don't know how widely adopted this approach is, but it works for me (Chrome browser).

Servlet handling of POST requests

Let's return to the AddServlet. I remind you that to allow our servlet to "catch" GET requests, we overrode the doGet() method in the HttpServlet class. To teach our servlet to also catch POST requests, we must also override the doPost() method. Tomcat passes it similar request and response objects that we'll work with. To start, extract the request's name and pass parameters sent by the form (if you specified different names in the form, then use those names). After that, create a user object using the received data. Then we get the model object and add the created user to the model.
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    String password = req.getParameter("pass");
    User user = new User(name, password);
    Model model = Model.getInstance();
    model.add(user);
}

Passing data to the view

Let's move on to the ListServlet. The doGet() method is already implemented. It simply transfers control to the view (list.jsp). If you don't have this yet, then create it by analogy with method in the AddServlet. Now it would be nice to get the list of usernames from the model and pass them to the view, which will receive them and display them beautifully. To do this, we will again use the request object we received from Tomcat. We can add an attribute to this object, giving it some kind of name. In fact, we can add the object we want to pass to the view. Due to the fact that when transferring control from the servlet to the view we pass the view the same request and response objects that the servlet received, we can add our list of names to the request object and then get our list of usernames from the request object in the view. We're done with the ListServlet class, so I'll present the code of the entire class here:
package app.servlets;

import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class ListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Model model = Model.getInstance();
        List<String> names = model.list();
        req.setAttribute("userNames", names);

        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp");
        requestDispatcher.forward(req, resp);
    }
}

Running Java code in JSP files

It's time to look at list.jsp. It will only be executed when ListServlet transfers control to it. In addition, we already prepared the list of usernames from the model in the servlet and passed it here in the request object. Since we have the list of names, we can iterate over it using a for loop and display each name. As I said before, JSP files can execute Java code (which is what makes them different from static HTML pages). To execute some code, all we need to do is put the following construct in the appropriate place:
<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
Within this construct, we gain access to several variables:
  • request — our request object, which we passed from the servlet, where it was simply called req;
  • response — the response object (called resp in the servlet);
  • out — a JspWriter object (which inherits an ordinary Writer), which we can use to "write" something directly into the HTML page itself. The statement out.println("Hello, World!") is very similar to System.out.println("Hello, World!"), but don't confuse them!
  • out.println() "writes" to an HTML page, while System.out.println writes to the system output stream. If you call System.out.println() within a JSP section with Java code, you'll see the results in the Tomcat console, but not on the page.
You can look for other objects available within a JSP here. We can use the request object to get the list of names passed from the servlet (we attached the corresponding attribute to this object), and we get use the out object to display these names. Let's display them (for the time being, as a simple HTML list):
<ul>
    <%
        List<String> names = (List<String>) request.getAttribute("userNames");

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
If we need to display the list only if there are users, and otherwise display a warning that there are no users yet, then we can rewrite this section a little:
<%
    List<String> names = (List<String>) request.getAttribute("userNames");

    if (names != null && !names.isEmpty()) {
        out.println("<ui>");
        for (String s : names) {
            out.println("<li>" + s + "</li>");
        }
        out.println("</ui>");
    } else out.println("<p>There are no users yet!</p>");
%>
Now that we know how to pass data from servlets to views, we can improve our AddServlet so that it displays a notification about the successful addition of a user. To do this, in the doPost() method, after adding a new user to the model, we can add this username to the req object's attributes and pass control back to a view (add.jsp). And now we'll add a section with Java code to it, where we'll check whether the request has such an attribute, and if it does — then we'll display a message that the user was successfully added. After these changes, AddServlet's full code will look something like this:
package app.servlets;

import app.entities.User;
import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
        requestDispatcher.forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String password = req.getParameter("pass");
        User user = new User(name, password);
        Model model = Model.getInstance();
        model.add(user);

        req.setAttribute("userName", name);
        doGet(req, resp);
    }
}
Here, at the end of the doPost() method we create an attribute with the name of the user who was added to the model, and then call the doGet() method, to which we pass the current request and response. The doGet() method now transfers control to the view, which also receives the request object with the name of the added user attached as an attribute. What remains for us to do is to fix add.jsp so that it displays the notification if there is no such attribute. Here's the final version of add.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<p>User '" + request.getAttribute("userName") + "' added!</p>");
                }
            %>
            <div>
                <div>
                    <h2>Add user</h2>
                </div>

                <form method="post">
                    <label>Name:
                        <input type="text" name="name"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass"><br />
                    </label>
                    <button type="submit">Submit</button>
                </form>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
The page body consists of the following:
  • a div with a header;
  • a div container for content, which includes a check whether an attribute with a username exists;
  • a div with the add-user form;
  • and at the bottom, a footer with a button to return to the home page.
This may seem like too many divs, but we'll use them later when we add styles. Here's the final version of list.jsp:
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <div>
                <div>
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ui>");
                        for (String s : names) {
                            out.println("<li>" + s + "</li>");
                        }
                        out.println("</ui>");
                    } else out.println("<p>There are no users yet!</p>");
                %>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Thus, we have a fully working web application that can save and add users, and also display a list of their names. Now we just need to make it pretty… :)

Adding styles. We'll use the W3.CSS framework

At the moment, our application works, but it looks absolutely outrageous. So, let's add a background, color the text and buttons, add style to the lists, align elements, add indents, and so on. Writing styles manually can take a lot of time and tax our nerves. So I propose using the W3.CSS framework. It already has ready-to-use classes with styles. We just need to arrange the CSS classes we want to use in the right places. To add them to our pages, we first connect the style file. There are two ways to do this:
  1. go through our pages and insert the following a direct link to the style file in the head section

    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

    This option is suitable if you have a permanent Internet connection. When you open your pages on the local server, the styles will be pulled from the Internet.

  2. But if you want to have all the styles locally and not depend on an Internet connection, download the style file and place it somewhere inside the web folder (e.g. web/styles/w3.css). Then go through all our pages (index.html, add.jsp, list.jsp) and add the following link to the style file inside the head section:

    <link rel="stylesheet" href="styles/w3.css">

    After that, just go through the tags and add the styles you like. I won't dwell on this in detail. Instead, I'll just provide ready-to-use versions of three of my files with raster-style classes.

index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Super app!</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center">
            <div class="w3-bar w3-padding-large w3-padding-24">
                <button class="w3-btn w3-hover-light-blue w3-round-large" onclick="location.href='/list'">List users</button>
                <button class="w3-btn w3-hover-green w3-round-large" onclick="location.href='/add'">Add user</button>
            </div>
        </div>
    </body>
</html>
add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-padding">
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<div class=\"w3-panel w3-green w3-display-container w3-card-4 w3-round\">\n" +
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-green w3-border w3-border-green w3-hover-border-grey\">×</span>\n" +
                            "   <h5>User '" + request.getAttribute("userName") + "' added!</h5>\n" +
                            "</div>");
                }
            %>
            <div class="w3-card-4">
                <div class="w3-container w3-center w3-green">
                    <h2>Add user</h2>
                </div>
                <form method="post" class="w3-selection w3-light-grey w3-padding">
                    <label>Name:
                        <input type="text" name="name" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <button type="submit" class="w3-btn w3-green w3-round-large w3-margin-bottom">Submit</button>
                </form>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
list.jsp
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users list</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center w3-margin-bottom w3-padding">
            <div class="w3-card-4">
                <div class="w3-container w3-light-blue">
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ul class=\"w3-ul\">");
                        for (String s : names) {
                            out.println("<li class=\"w3-hover-sand\">" + s + "</li>");
                        }
                        out.println("</ul>");

                    } else out.println("<div class=\"w3-panel w3-red w3-display-container w3-card-4 w3-round\">\n"
+
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-red w3-border w3-border-red w3-hover-border-grey\">×</span>\n" +
                            "   <h5>There are no users yet!</h5>\n" +
                            "</div>");
                %>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
And that's it. :) If you still have any questions or comments, or if something doesn't work out, please leave a comment. And I'll attach a couple of screenshots of how it all turned out.
And finally, if you want to practice with this project, you can try the following:
  • make a servlet and JSP to delete a user, and add another pair to edit an existing user. The result will be a genuine CRUD web application built using servlets. ;)
  • replace the List with a database, so that the added users don't disappear after the server is restarted. :)
Good luck!