- about networking
- about software architecture
- about HTTP/HTTPS
- about the basics of Maven
- about servlets (writing a simple web application)
Table of contents:
- What is a servlet container?
- How are servlet containers used?
- Installing and starting Tomcat
- Deploying an application in Tomcat
- Using HTTPS instead of HTTP
- Generating a certificate
- Configuring the server
- Dynamically generating HTML pages
- Alternatives to Tomcat
What is a servlet container?
It is a program that runs on a server and can interact with the servlets we created. In other words, if we want to run our web application on a server, we first deploy a servlet container and then put servlets in it. The workflow is simple: when the client accesses the server, the container processes its request, determining which servlet should process it, and then passes the request along.How are servlet containers used?
In addition to routing requests, a servlet container performs other functions:- It dynamically generates HTML pages from JSP files.
- It encrypts/decrypts HTTPS messages.
- It provides restricted access for servlet administration.
Installing and starting Tomcat
To install Tomcat, simply unzip the downloaded archive into the desired directory.
Please note that Tomcat requires Java version 8 or higher to start and run. Verify that the JAVA_HOME environment variable references the current version of the JDK.
Next, you need to configure user access to Tomcat. This is done in the tomcat-users.xml file, which is located in the conf folder.
There are four preset roles in Tomcat:
- manager-gui — Access to the graphical interface and status page
- manager-script — Access to the text interface and status page
- manager-jmx — Access to JMX and the status page
- manager-status — Access only to the status page
Inside the <tomcat-users> tag, we explicitly specify these roles and assign them to our user:
<role rolename="manager-gui"/> <role rolename="manager-script"/> <role rolename="manager-jmx"/> <role rolename="manager-status"/> <user username="user" password="password" roles="manager-gui, manager-script, manager-jmx, manager-status"/>
Now everything is ready to launch!
In the bin folder, run the startup.bat file (startup.sh on Linux).
After a few seconds, open the link http://localhost:8080/ in your browser. You will see a graphical dashboard:
If you see a menu like this, then Tomcat is running.
If it is not running, manually check the JAVA_HOME and CATALINA_HOME environment variables:
- JAVA_HOME — This must reference the current version of Java 8+.
- CATALINA_BASE — This must reference Tomcat or be absent (it should not reference another version of Tomcat).
Deploying an application in Tomcat
We managed to launch Tomcat, so it is now time to deploy some project in it. Let's use the servlets from the previous article. MainServlet:
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
HttpSession session = req.getSession();
Integer visitCounter = (Integer) session.getAttribute("visitCounter");
if (visitCounter == null) {
visitCounter = 1;
} else {
visitCounter++;
}
session.setAttribute("visitCounter", visitCounter);
String username = req.getParameter("username");
resp.setContentType("text/html");
PrintWriter printWriter = resp.getWriter();
if (username == null) {
printWriter.write("Hello, Anonymous" + "
");
} else {
printWriter.write("Hello, " + username + "
");
}
printWriter.write("Page was visited " + visitCounter + " times.");
printWriter.close();
}
}
IndexServlet:
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.sendRedirect(req.getContextPath() + "/hello");
}
}
Before deploying, we need to package our servlets in a WAR file.
Maven is usually used to do this, but in order to create a WAR file you need a web.xml file that has a mapping for all the servlets. We used the new @WebServlet annotation to write the servlets, so we don't have a web.xml file. Fortunately, IDEA can do the dirty work for us, wrapping our project in a WAR file.
To do this, open the project structure (Ctrl+Shift+Alt+S) -> Artifacts -> Select the desired WAR file -> Select the checkbox next to "Include in project build" -> Click "OK".
Let's build the project using the Ctrl+F9 key combination. Now our WAR file is in the target directory
The file can be renamed to something simpler, e.g. servlet.war, and moved to a more convenient place, e.g. C:\\my\\.
Once the WAR file is ready to use, we'll put it in a container. There are two ways to do this.
Using the graphical interface
To do this, follow this link: http://localhost:8080/manager/html. Tomcat should ask for a username and password.
If you followed along with me up to this point, then the username is "user", and the password is "password".
After successfully signing in, you will see the Tomcat Web Application Manager. The "Applications" section already contains 5 applications — these are Tomcat utilities, which make Tomcat easier to work with. They can be deleted in the future.
Below is the "Deploy" section. Here you can select the WAR archive to deploy. Let's enter the path and context manually:
Click "Deploy" and we see that our application has appeared in the "Applications" section:
Using Tomcat's graphical interface, we can stop, restart, and delete a session, as well as set the session length. When deploying, we specified the /demo context, which means that our application is accessed using http://localhost:8080/demo. Check it. Everything should work.Through the file system
To deploy the application in this way, you need to open the directory where Tomcat was unzipped. Then go to the "webapps" folder. Here you will find the utilities we have already encountered:
All that is required is for us to move our servlet.war file here.
We wait a few seconds and then see that a new "servlet" folder has appeared. This means that our application is deployed. Go to the Application Manager interface at http://localhost:8080/manager/. Here we see that our application is deployed in the /servlet context:
When deployed in this way, the context is assigned automatically based on the name of the deployed WAR file. To change the context, you can rename the newly created folder that contains the application, but before doing that you need to remove the WAR file. Otherwise, Tomcat will redeploy the application with the archive name.
As you can see, deploying applications in Tomcat is much easier than it might seem. But its other functions are also easy to use. Let's check.
Using HTTPS instead of HTTP
If you remember, we looked at the difference between HTTP and HTTPS in a separate article. HTTPS is the same protocol as HTTP, but it encrypts the data being transmitted. On the client side, the browser is responsible for encryption, but we must provide the encryption on the server side. Since Tomcat accepts and routes HTTP requests, it makes sense to delegate encryption to it. To do this, we must:- Generate a self-signed certificate
- Make additional server settings
Generating a certificate
Regardless of the version, the JDK includes a large number of utilities. One of them is keytool. This is a tool for generating and working with encryption keys. To use it, on the command line, go to the C:\\Program Files\\Java\\jdk1.8.0_181\\bin directory and run the command keytool -genkey -alias tomcat -keyalg RSA.- keytool — The name of the utility that we are running with command line options
- -genkey — Indicate that we want to generate a new key
- -alias tomcat — Create a key alias
- -keyalg RSA — Select RSA as the key generation algorithm
Configuring the server
Now that the certificate is ready, we need to adjust the server settings, namely, the SSL connector. This is done in the server.xml file, which is located in apache-tomcat-9.0.30/conf/. In it, we find blocks like this:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
and we put our configuration next to them:
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="C:\Users\user\.keystore" keystorePass="mypass"
clientAuth="false" sslProtocol="TLS"/>
We assign the latest values to the keystoreFile and keystorePass parameters, save the file, and then restart Tomcat using the shutdown.bat and startup.bat files.
Now the server is ready to process HTTPS requests. The address has changed just a little: https://localhost:8443/demo/hello.
When you click on the link you will receive a warning about trustworthiness of the certificate, which is not surprising. As we said a little earlier, you need to use the services of one of the certification authorities to obtain a normal certificate. But for now, we've achieved our goal: the application runs using the HTTPS protocol, and that's important!
Dynamically generating HTML pages
Now we'll continue our overview of servlet containers by considering another feature: dynamic generation of HTML pages. Imagine a perfect world where, instead of boring static HTML code, you could write Java code, using variables, loops, arrays and other language constructs. Were you able to imagine it? The good news is that something similar exists. The bad news is that it doesn't entirely achieve this fantasy. If you haven't guessed, we're talking about JavaServer Pages (JSP). In short, this is technology that lets you insert pieces of Java code into an HTML page. True, this Java code is still converted into HTML before it is sent to the client, but that HTML will be dynamically generated, taking into account various factors. For example, you can use conditional statements and return different content depending on some condition. Example JSP page:
<%@ page language="java"" %>
<html>
<head>
<title>JSP</title>
</head>
<body>
<%
String firstName="name";
String secondName="surname";
if (firstName.equals("name")){
out.print("Hello: "+firstName+"<br>");
}
if (firstName.equals("name") && secondName.equals("surname"))
{
out.print("Hello, my dear friend! <br>");
}
else
{
out.print("I don't know you. Go away! <br>");
}
%>
</body>
</html>
You can read more about JSP here.
At the end of the day, this article isn't about JSP — we're here to talk about servlet containers! So why did we mention JSP? It's simple: a servlet container is what converts Java code from JSP to HTML. When a servlet is going to return JSP content as a response, the container takes note and first converts it into a browser-friendly HTML page before sending such content to the client.
Today, there are many analogues to JSP technology — Thymeleaf, FreeMarket, Mustache, and others. They all work in a similar fashion. Which of them to choose for your work is a matter of taste.
This also applies to choosing a servlet container. In these examples, we used Tomcat, the most common container, but some projects use other containers. It's worthwhile to briefly review the most popular ones and consider how they differ from Tomcat.
Alternatives to Tomcat
GlassFish is an open source container whose development is supported by Oracle.
Unlike Tomcat, it is a full-fledged web server, which, in addition to servlets, can operate with other components from the JavaEE framework. That said, it uses a lot more RAM. There is greater flexibility when fine-tuning the server, which complicates its use. It should be used when developing applications on the JavaEE framework.
WildFly was previously known as JBoss. It is also open source. It is developed by Red Hat. The name was changed to avoid confusion with another one of the company's products — JBoss Enterprise Application Platform.
Like GlassFish, WildFly is a full-fledged web server. Incidentally, under the hood, WildFly uses Tomcat as a servlet container. Unlike GlassFish, WildFly is more lightweight and easy to configure.
Jetty, like the previous ones, is open source. It is developed by Eclipse.
Like Tomcat, it is a simple servlet container, without support for all the components of the JavaEE framework. At the same time, it is more lightweight and can even be run on a mobile phone. It starts and stops quickly and scales well. Unlike Tomcat, it has a smaller community and knowledge base.
WebLogic is licensed software that must be purchased before use. It belongs to Oracle.
It has slightly broader functionality than Tomcat. It can work with the FTP protocol. But it is not so flexible when developing and testing applications.
WebSphere (WebSphere Application Server, to be precise) is paid software. It is developed by IBM. Similar to WildFly and GlassFish, it is a complete application server. But it has a friendlier configuration interface, plus high reliability in operation.
Its shortcomings include the fact that it uses a lot of resources and takes a long time to start and stop, which is not very convenient when developing small projects.
GO TO FULL VERSION