Hello, everyone! You will become familiar with servlets as a basic concept of web development, and you will be able to write a simple application that uses them. Your first application using Java servlets - 1 To avoid unnecessary actions, we won't start from scratch. We'll continue working on our application from my previous article about Hibernate. But since we're just starting to get acquainted with servlets, I've removed everything related to the Auto class from the application and left only the User class and actions involving it. The project will be structured like this: Your first application using Java servlets - 2So, servlets! Wikipedia states: "A Java servlet is a Java software component that extends the capabilities of a server. Although servlets can respond to many types of requests, they most commonly implement web containers for hosting web applications on web servers and thus qualify as a server-side servlet web API." This is exactly true. Here, for the first time, we are coming across the concept of a "client-server application architecture." It is quite simple at its core. The client accesses the server by sending an HTTP request. The server generates the necessary data (for example, fetches it from a database) and returns it to the client. The simplest example is when you click the "Friends" button on a certain social network, thereby sending a request to the server. The server updates the list of your friends in the database and returns it to you (the client). The list of HTTP requests is quite large, so if you've never encountered them before, then it would be best for you to read about them elsewhere, for example, here. Our objective is to: Create a CRUD application using servlets. The application must be able to create, read, update, and delete users from the database using a servlet that processes HTTP requests. Our application from the Hibernate article could already do this, but it was controlled directly from Java code, more precisely, from the main() method. This time, it is the client who will send the requests, i.e. you :) The first thing we need to do is add new dependencies to our pom.xml file.

 <xml version="1.0" encoding="UTF-8"?>
 <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>com.itis4</groupId>
     <artifactId>UsersDaoProject</artifactId>
     <version>1.0-SNAPSHOT</version>
 
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-war-plugin</artifactId>
                 <version>2.6</version>
             </plugin>
         </plugins>
     </build>
 
     <dependencies>
         <!-- PostgreSQL  -->
         <dependency>
             <groupId>org.postgresql</groupId>
             <artifactId>postgresql</artifactId>
             <version>9.4.1212.jre7</version>
         </dependency>
 
         <!-- Hibernate 5.2.6 Final -->
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-core</artifactId>
             <version>5.2.6.Final</version>
         </dependency>
 
         <dependency>
             <groupId>jstl</groupId>
             <artifactId>jstl</artifactId>
             <version>1.2</version>
         </dependency>
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
             <version>3.1.0</version>
         </dependency>
 
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-webmvc</artifactId>
             <version>4.3.4.RELEASE</version>
         </dependency>
 
     </dependencies>
 
 </project>
 
We added 3 dependencies:
  1. The javax.servlet-api library itself
  2. The JSTL tag library. It will be needed to create the client side, namely the JSP pages
  3. Spring-WebMVC. We will need one Spring class, which we will talk about a little later.
Servlet management is handled by the servlet container. In our case, we will use Apache Tomcat. It's pretty popular — you've probably already heard about it :) The servlet life cycle consists of the following steps:
  1. If there is no servlet in the container:
    • The servlet class is loaded by the container.
    • The container creates an instance of the servlet class.
    • The container calls the init() method. This method initializes the servlet and is called first, before the servlet can serve requests. Over the entire life cycle, the init() method is called only once.
  2. Service the client request. Each request is processed on its own separate thread. The container calls the service() method for each request. This method determines the type of incoming request and sends it to the appropriate method for processing. The servlet developer must provide implementations for these methods. If a request arrives for a handler that is not implemented, the parent class's method is called and usually ends up returning an error to the requestor.

  3. If the container needs to remove the servlet, it calls the destroy() method, which takes the servlet out of operation. Like the init() method, this method is also called once during the entire servlet cycle.
Our servlet looks quite simple:

 package servlets;
 
 import models.User;
 import services.UserService;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletConfig;
 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 UserSimpleServlet extends HttpServlet {
 
     private UserService service = new UserService();
 
     public void init(ServletConfig servletConfig) {
         try {
             super.init(servletConfig);
         } catch (ServletException e) {
             e.printStackTrace();
         }
     }
 
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
         List<User> users = service.findAllUsers();
         req.setAttribute("users", users);
         RequestDispatcher dispatcher = req.getRequestDispatcher("/showUsers.jsp");
         dispatcher.forward(req, resp);
 
     }
 
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
 
         String name = req.getParameter("name");
         int age = Integer.parseInt(req.getParameter("age"));
         User user = new User(name, age);
         service.saveUser(user);
         resp.sendRedirect("/users");
 
     }
 
     @Override
     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         int id = Integer.parseInt(req.getParameter("id"));
         User user = service.findUser(id);
         user.setName(req.getParameter("name"));
         user.setAge(Integer.parseInt(req.getParameter("age")));
         service.updateUser(user);
         resp.sendRedirect("/users");
     }
 
     @Override
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
         int id = Integer.parseInt(req.getParameter("id"));
         service.deleteUser(service.findUser(id));
         resp.sendRedirect("/users");
     }
 }
 
As you can see, it contains the init() method, which was described above, and implements 4 methods that coincide with four HTTP requests: doPost(), doGet(), doPut() and doDelete(). They let us create, read, update and delete users. The methods accept instances of the javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse classes as input, i.e. requests sent to the server and responses received by the client. Internally, the methods call the relevant methods of the UserService class, and a response for the client is generated and redirected to the /users URL. For example, in the doGet() method, we get a list of all users. Next, we create a RequestDispatcher object, which lets us include objects in an HTTP request and redirect it to a specific resource (for example, to a client JSP page). In the doPut() method (which updates user data), we process an HTTP request, extract the id, name, and age parameters, find the user with the specified id, assign it the name and age that in the request, and return to the /users page. But for all these methods to work correctly, we need to configure the servlet. To do this, we use the web.xml file in the WEB-INF folder.

 <?xml version="1.0" encoding="UTF-8"?>
 <web-app version="3.1"
          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">
 
     <welcome-file-list>
         <welcome-file>index.jsp</welcome-file>
     </welcome-file-list>
 
     <servlet>
         <servlet-name>UserSimpleServlet</servlet-name>
         <servlet-class>servlets.UserSimpleServlet</servlet-class>
     </servlet>
 
     <servlet-mapping>
         <servlet-name>UserSimpleServlet</servlet-name>
         <url-pattern>/</url-pattern>
     </servlet-mapping>
 
     <filter>
         <filter-name>hiddenHttpMethodFilter</filter-name>
         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
     </filter>
 
     <filter-mapping>
         <filter-name>hiddenHttpMethodFilter</filter-name>
         <servlet-name>UserSimpleServlet</servlet-name>
     </filter-mapping>
 
 </web-app>
 
All the tags in this file are fairly intuitive, but let's go through them in order. <welcome-file-list> - The JSP start page is indicated, which will be opened first when the application starts. In our case, this is index.jsp. <servlet> - Registration of our UserSimpleServlet class as a servlet. <servlet-mapping> - a very important tag. It defines the URLs that will be processed by the servlet. In our case, it's all URLs, so we simply indicate "/". But if we had an application involving users and their cars (autos), then we could create a second servlet (SimpleAutoServlet). Then the user servlet's mapping would be "/users" (i.e. requests about users), and the auto servlet's mapping would be "/autos". And finally, <filter>. Internally, it defines an instance of the org.springframework.web.filter.HiddenHttpMethodFilter class. This article isn't about Spring, so I won't describe it in detail. I'll only say that it is bolted onto our application only as an additional feature. The thing is that we're going to use JSP pages to create the client side. Our data will be displayed on the page as a table with a list of users. Inside the JSP pages, <form/> HTML tags will be used. But only HTTP GET and POST requests can be used for sending data from a <form/>. In other words, for all three operations — updating, deleting, and creating a user — we would have to use only POST requests. Using PUT and DELETE requests would not be an option for us. In principle, this is quite normal and easy to implement, but the HiddenHttpMethodFilter class lets us use them. In this way, the reader will more clearly see the difference between operations in the application. Finally, let's proceed to the client side. It is represented by five JSP pages. index.jsp.

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Hello!</title>
 </head>
 <body>
 If you want to start working with the user database,<br>
 click the button below:
 
 <form action = "users" method="get">
     <input type="submit" value="Start working with database">
 </form>
 </body>
 </html>
 
addUser.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Add new user</title>
 </head>
 <body>
 <form action = "/users" method="post">
     <input required type="text" name="name" placeholder="Name">
     <input required type="text" name="age" placeholder="Age">
     <input type="submit" value="Save">
 </form>
 </body>
 </html>
 
 
deleteUser.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Delete user</title>
 </head>
 <body>
 
 Are you sure you want to delete the user ${param.id}?
 
 &lform action="/users/${param.id}" method="post">
     <input type="hidden" name="id" value="${param.id}">
     <input type="hidden" name="_method" value="delete">
     <input type="submit" value="Delete">
 </form>
 
 </body>
 </html>
 
 
showUsers.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <html>
 <head>
     <title>User list</title>
 </head>
 <body>
 <table border="2">
     <tr>
         <td>ID</td>
         <td>Name</td>
         <td>Age</td>
         <td>Actions</td>
     </tr>
     <c:forEach items="${users}" var = "user">
         <tr>
             <td>${user.getId()}</td>
             <td>${user.getName()}</td>
             <td>${user.getAge()}</td>
             <td>
                 <form action = "updateUser.jsp" method="post">
                     <input type="hidden" name="id" value="${user.getId()}">
                     <input type="hidden" name="name" value="${user.getName()}">
                     <input type="hidden" name="age" value="${user.getAge()}">
                     <input type="submit" value="Modify" style="float:left">
                 </form>
                 <form action="deleteUser.jsp" method="post">
                     <input type="hidden" name="id" value="${user.getId()}">
                     <input type="submit" value="Delete" style="float:left">
                 </form></td>
         </tr>
     </c:forEach>
 </table>
 
 <form action = "addUser.jsp">
     <input type="submit" value="Add new user">
 </form>
 </body>
 </html>
updateUser.jsp

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>Modify user data</title>
 </head>
 <body>
 
 Edit user
 
 <form action="/users/${param.id}" method="post">
     <input type="hidden" name = "id" value="${param.id}">
     <input type="text" name="name" value="${param.name}" placeholder=${param.name}>
     <input type="text" name="age" value="${param.age}" placeholder=${param.age}>
     <input type="hidden" name="_method" value="put">
     <input type="submit" value="Update">
 </form>
 
 </body>
 </html>
 
A JSP (JavaServer Page) page contains two types of text: static source data that can be formatted as text (HTML, SVG, WML, or XML), and JSP elements used to construct dynamic content. To help you understand what a JSP page is, I've copied a passage from a very good article. "Basically, the first time a JSP is requested, it turns into a servlet and operates as a servlet. This is very important to understand. A JSP page IS NOT like an HTML page — a beginning programmer must clearly understand that this is another servlet — it's just that you don't write have to program how it is displayed. It can simply be drawn. And add data where necessary. But because a JSP page is reminiscent of HTML, a designer will obviously find it easier. And once again STRONGLY EMPHASIZE to beginners, a JSP page is a SERVLET. It is generated, including adding all the data, on the server. This is where all the data is inserted. And in the browser, the user gets the finished HTML page, which has not signs of Java." You can be sure that a JSP page is really a servlet, because each page has a method that needs to be executed. For example, index.jsp indicates that when you click on the "Start working with the database" button, the get method will be executed (method = "get"). The addUser.jsp page, which is responsible for creating new users, executes the post method (method = "post") when you click the save button. The rest of the JSP page is made up of regular static HTML markup, so we won't dwell on it. That's a topic for another article and there are plenty on this topic on the Internet. So, we've created our application! Now we need to test it in action! To do this, we need the Apache Tomcat servlet container mentioned above. You can download the container from the official website (I use version 8). Next, we need to create a configuration in IDEA to run our application through Tomcat. To do this, open the "Edit Configurations" tab, Your first application using Java servlets - 3create a new configuration, Your first application using Java servlets - 4and select "Tomcat Server Local". On the "Application Server" tab, specify the path to the Tomcat folder Your first application using Java servlets - 5Next, go to the "Deployment" tab. Your first application using Java servlets - 6Here, we configure the deployment of our application on the local server. Press "+", select "Artifact" -> YourProjectName:war (we'll build the application to a war file). Your first application using Java servlets - 7And that about sums it up! On the "Server" page, you can see that our application will run at http://localhost:8080/. Save the configuration and give it a name (I call my config "Tommy"). Next, on the Maven tab in IDEA (on the right side), we will use the war plugin to build our project to a war file (Plugins -> war -> war: war). Your first application using Java servlets - 8After the build is complete, run the application and wait. Success! The start page was launched. Now we click the "Start working with the database" button. Our index.jsp will generate a GET request that will be processed by the server. The server will generate a response and return it to us in the form of a list of all existing users (assuming that there are users in the database, of course). And there they are! That there you have it! You wrote your first application using Java servlets. Your first application using Java servlets - 9That wasn't so bad, was it? :) For homework, you could restore the car functionality from the previous article. In other words, create a separate servlet and JSP pages for cars, and teach the application how to list a user's cars, add new cars to a user, and edit and delete them. P.S. Servlets and JavaServer Pages are rather ancient technologies. On the Internet, you can often find comments like "Who needs this old junk?" The answer is quite simple: mainly people who will work on real projects, where they may quite possibly encounter a lot of code that uses these technologies. And even without understanding how it works, it's still fun to cut up "old junk" into something new :) For a more thorough study of JSP and servlets, you can refer to the book "Head First Servlets and JSP". It was written by the same authors as the famous super book "Head First Java", which many will take as a guarantee of quality :) I hope this article has been helpful! Thanks for your attention, and good luck in learning!