Java Module 21 – Jakarta EE web: Servlets and Tomcat
Jakarta EE, servlet containers and Tomcat 11
What Jakarta EE 11 specifies and which part Tomcat implements, how to choose Tomcat 11, 10.1 or 9, and a checked local Tomcat 11 install on JDK 25.
What you will learn
- Explain what Jakarta EE 11 specifies and which of those APIs Tomcat implements
- Choose Tomcat 11, 10.1 or 9 from the Servlet version and the jakarta or javax namespace
- Install Tomcat 11 on JDK 25, bind it to localhost and remove the sample apps
Before you start
What you’ll learn · Before you start
What you will learn
- Explain what Jakarta EE 11 specifies and which of those APIs Tomcat implements
- Choose Tomcat 11, 10.1 or 9 from the Servlet version and the jakarta or javax namespace
- Install Tomcat 11 on JDK 25, bind it to localhost and remove the sample apps
Before you start
On this page
Jakarta EE is a set of specifications for server-side Java, published by the Eclipse Foundation. Each specification defines an API, such as Jakarta Servlet for answering HTTP requests, the rules that an implementation must follow, and a test kit that proves it follows them. A servlet container implements the web part of those specifications: it listens for HTTP requests, finds the web application and the servlet that each URL belongs to, and calls that servlet on one of its threads. Apache Tomcat is the open-source servlet container of the Apache Software Foundation. Tomcat 11 implements the Jakarta EE 11 versions of Servlet (6.1), Pages, Expression Language, WebSocket and Authentication on Java 17 or later. It is not a full application server, so an application that needs CDI or Persistence carries those libraries itself. This lesson places Tomcat among the Jakarta EE products, helps you choose between Tomcat 11, 10.1 and 9, and installs Tomcat 11 on JDK 25 for safe local work.
What Jakarta EE specifies
Jakarta EE comes in three sizes, the Core Profile, the Web Profile and the full Platform, each containing the one before it:
- Core Profile for small services: RESTful Web Services, JSON Processing and Binding, CDI Lite and a few more.
- Web Profile for web applications. In Jakarta EE 11 it adds, among others, Servlet 6.1, Pages 4.0, Expression Language 6.0, Standard Tag Libraries 3.0, WebSocket 2.2, Faces 4.1, CDI 4.1, Persistence 3.2, Validation 3.1, Security 4.0, Authentication 3.1 and the new Data 1.0.
- Platform, the whole set, which adds Messaging, Batch, Mail, Connectors, Enterprise Beans and others.
Jakarta EE 11 needs Java 17 or later. Its successor, Jakarta EE 12, is still under development, with Servlet 6.2, CDI 5.0, Persistence 4.0 and Faces 5.0 among its planned versions. Products that pass the test kits of a whole profile or of the platform appear on the Eclipse Foundation’s list of compatible products: Eclipse GlassFish, WildFly, Open Liberty, Payara and Apache TomEE are some of them.
One change from the history of these APIs still catches people out. Up to Java EE 8, and in Jakarta EE 8 as well,
the packages were named javax.servlet, javax.servlet.jsp and so on. Jakarta EE 9 renamed them to jakarta.servlet, jakarta.servlet.jsp
and the like, and Tomcat’s migration guide puts the consequence plainly: such applications have to be recompiled against
the new APIs. Here is a servlet written for Java EE 8 next to the same servlet for Jakarta EE, both compiled against the
servlet-api.jar that Tomcat 11 ships:
Java (OldHello.java) · namespace/OldHello.java
// A servlet written for Java EE 8 and Tomcat 9: every servlet type is in the javax.servlet packages.
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class OldHello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Hello from a servlet");
}
} Java (Hello.java) · namespace/Hello.java
// The same servlet for Jakarta EE 9 and later (Tomcat 10.1 and 11): only the package names changed.
import java.io.IOException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class Hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Hello from a servlet");
}
} from session import run
# Compiles a javax servlet, then the same servlet with jakarta imports, against the Servlet 6.1 API that Tomcat 11
# ships in lib/servlet-api.jar.
run(
"""
jar tf "$CATALINA_HOME/lib/servlet-api.jar" | grep "/HttpServlet.class"
javac -cp "$CATALINA_HOME/lib/servlet-api.jar" -d classes OldHello.java
javac -cp "$CATALINA_HOME/lib/servlet-api.jar" -d classes Hello.java
ls classes
""",
fails=('javac -cp "$CATALINA_HOME/lib/servlet-api.jar" -d classes OldHello.java',),
folder="namespace",
) Output
# openjdk version "25.0.4.1" LTS · Apache Tomcat 11.0.26
$ jar tf "$CATALINA_HOME/lib/servlet-api.jar" | grep "/HttpServlet.class"
jakarta/servlet/http/HttpServlet.class
$ javac -cp "$CATALINA_HOME/lib/servlet-api.jar" -d classes OldHello.java
OldHello.java:3: error: package javax.servlet.http does not exist
import javax.servlet.http.HttpServlet;
^
OldHello.java:4: error: package javax.servlet.http does not exist
import javax.servlet.http.HttpServletRequest;
^
OldHello.java:5: error: package javax.servlet.http does not exist
import javax.servlet.http.HttpServletResponse;
^
OldHello.java:7: error: cannot find symbol
public class OldHello extends HttpServlet {
^
symbol: class HttpServlet
OldHello.java:9: error: cannot find symbol
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
^
symbol: class HttpServletRequest
location: class OldHello
OldHello.java:9: error: cannot find symbol
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
^
symbol: class HttpServletResponse
location: class OldHello
OldHello.java:8: error: method does not override or implement a method from a supertype
@Override
^
7 errors
[exit status 1]
$ javac -cp "$CATALINA_HOME/lib/servlet-api.jar" -d classes Hello.java
$ ls classes
Hello.class
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 namespace_session.py
The JAR holds jakarta/servlet/http/HttpServlet.class and no javax package at all, so the old servlet fails with
seven errors while the new one compiles. Only the imports differ.
Servlet containers and application servers
The parts of Tomcat a request passes through, as conf/server.xml and an application name them
Text description of the diagram
The diagram shows a request going from the outside of Tomcat to a servlet, from top to bottom.
- A browser or curl sends GET /clock/now over a TCP connection.
- The connection reaches the Connector, which listens for HTTP on 127.0.0.1, port 28461, and reads the request.
- A thread from the connector's pool carries the request into the Engine named Catalina.
- The engine passes it to the Host named localhost, whose applications live in the webapps folder.
- The host chooses the Context /clock, the application deployed from clock.war.
- The context chooses the servlet mapped to /now, and that servlet's doGet method writes the response.
The Server box around the connector and the engine stands for the one JVM that runs Tomcat. The Server, Connector, Engine and Host are elements of conf/server.xml; the context and the servlet come from the deployed application.
Each box in the diagram is a part of Tomcat that you will meet again. The connector owns the network side: it
listens on an address and a port, parses HTTP and hands each request to a thread from its pool. The engine and its
host pick the web application from the first part of the path (/clock), and the application’s context picks
the servlet from the rest (/now). Everything up to the host is configured in conf/server.xml; the context and the
servlet come from the application you deploy.
Tomcat ships the Servlet, Pages, Expression Language, WebSocket, Authentication and Annotations APIs with their
implementations. It does not ship Faces, CDI, Persistence, Validation or the standard tag library, so an application
that uses them puts an implementation, such as Hibernate ORM for Persistence, in its own WEB-INF/lib folder. A full
application server from the compatible products list builds those in, configures them centrally and also runs the
servlets that Tomcat runs.
Spring applications sit on the same foundation. Spring Boot 4.1 embeds Tomcat 11.0 or Jetty 12.1, both Servlet 6.1
containers, and can also be deployed to any Servlet 6.1 container. Spring MVC’s DispatcherServlet is itself a servlet,
the single front controller that receives every request and passes it to your controllers. What this module shows
about servlets, their threads and their scopes therefore still holds when a framework hides them.
Tomcat 11, 10.1 or 9
Tomcat’s “Which version” page maps each supported line to the specifications it implements:
| Tomcat line | Servlet | Pages | Expression Language | WebSocket | API packages | Java needed |
|---|---|---|---|---|---|---|
| 11.0 (Jakarta EE 11) | 6.1 | 4.0 | 6.0 | 2.2 | jakarta.* |
17 or later |
| 10.1 (Jakarta EE 10) | 6.0 | 3.1 | 5.0 | 2.1 | jakarta.* |
11 or later |
| 9.0 (Java EE 8) | 4.0 | 2.3 | 3.0 | 1.1 | javax.* |
8 or later |
Three rules follow from the table:
- New work goes on Tomcat 11. It implements the current Jakarta EE release and runs on JDK 25, the JDK of this track.
- Tomcat 10.1 suits a stack that is fixed at Jakarta EE 10. Its applications use the same
jakartapackages, so moving them to 11 usually means testing, not rewriting. - Tomcat 9 is for
javaxapplications that cannot be changed yet. Tomcat 11 can also convert such a WAR as it deploys: a WAR placed in the host’swebapps-javaeefolder is rewritten to thejakartapackages by the bundled migration tool. Treat that conversion as a bridge while the code is migrated. In the ordinarywebappsfolder, a WAR whosejavaxservlets are mapped with annotations deploys without an error, and its servlet URLs then answer 404, because Tomcat 11 looks only for thejakartaannotations.
Older lines, 10.0 and 8.5 among them, have reached their end of life and get no more fixes. Whichever line you choose, install its newest release from the download page; the examples in this module ran on Tomcat 11.0.26.
Installing Tomcat 11 on JDK 25
Tomcat runs from a folder: there is no installer to run on macOS or Linux, and Windows has an optional installer that sets Tomcat up as a service. The download page asks you to check every file you download, against its SHA-512 checksum or its OpenPGP signature. The session below downloads Tomcat 11.0.26, checks it, unpacks it, looks at what it contains, then makes three changes for local work and starts it:
from session import run
# Downloads Tomcat 11.0.26 from the Apache archive and checks it against its published SHA-512, looks at what it ships,
# then sets it up for local work: server.xml from this folder and no sample apps. The checker runs before and after the
# changes, and Tomcat is started, checked and stopped.
run(
"""
curl -sSfO https://archive.apache.org/dist/tomcat/tomcat-11/v11.0.26/bin/apache-tomcat-11.0.26.tar.gz
curl -sSfO https://archive.apache.org/dist/tomcat/tomcat-11/v11.0.26/bin/apache-tomcat-11.0.26.tar.gz.sha512
shasum -a 512 -c apache-tomcat-11.0.26.tar.gz.sha512
tar -xzf apache-tomcat-11.0.26.tar.gz
ls apache-tomcat-11.0.26/webapps
apache-tomcat-11.0.26/bin/version.sh | grep -E "^(Server version|Server number|JVM)"
java CheckInstall.java apache-tomcat-11.0.26 # as downloaded
cp server.xml apache-tomcat-11.0.26/conf/server.xml
rm -r apache-tomcat-11.0.26/webapps/*
apache-tomcat-11.0.26/bin/startup.sh
curl -s -o /dev/null -w "%{http_code}\\n" http://127.0.0.1:28461/
grep -E "Server version name|JVM Version|ProtocolHandler|Server startup" apache-tomcat-11.0.26/logs/catalina.out
java CheckInstall.java apache-tomcat-11.0.26 # after the changes, while Tomcat runs
apache-tomcat-11.0.26/bin/shutdown.sh
""",
fails=("java CheckInstall.java apache-tomcat-11.0.26 # as downloaded",),
port=28461,
base="apache-tomcat-11.0.26",
tomcat_env=False,
) Output
# openjdk version "25.0.4.1" LTS · Apache Tomcat 11.0.26
$ curl -sSfO https://archive.apache.org/dist/tomcat/tomcat-11/v11.0.26/bin/apache-tomcat-11.0.26.tar.gz
$ curl -sSfO https://archive.apache.org/dist/tomcat/tomcat-11/v11.0.26/bin/apache-tomcat-11.0.26.tar.gz.sha512
$ shasum -a 512 -c apache-tomcat-11.0.26.tar.gz.sha512
apache-tomcat-11.0.26.tar.gz: OK
$ tar -xzf apache-tomcat-11.0.26.tar.gz
$ ls apache-tomcat-11.0.26/webapps
docs
examples
host-manager
manager
ROOT
$ apache-tomcat-11.0.26/bin/version.sh | grep -E "^(Server version|Server number|JVM)"
Server version: Apache Tomcat/11.0.26
Server number: 11.0.26.0
JVM Version: 25.0.4.1+1-LTS
JVM Vendor: Eclipse Adoptium
$ java CheckInstall.java apache-tomcat-11.0.26 # as downloaded
FAIL shutdown port 8005 stops Tomcat for any program on this computer that sends "SHUTDOWN"
FAIL connector 8080 listens on every network address (no address attribute)
FAIL the HTTP port is still the default, 8080
FAIL webapps still holds ROOT, docs, examples, host-manager, manager
INFO logs/catalina.out: Tomcat has not started yet
INFO nothing answers on 127.0.0.1:8080
4 checks failed.
[exit status 1]
$ cp server.xml apache-tomcat-11.0.26/conf/server.xml
$ rm -r apache-tomcat-11.0.26/webapps/*
$ apache-tomcat-11.0.26/bin/startup.sh
Tomcat started.
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:28461/
404
$ grep -E "Server version name|JVM Version|ProtocolHandler|Server startup" apache-tomcat-11.0.26/logs/catalina.out
… INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/11.0.26
… INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 25.0.4.1+1-LTS
… INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-127.0.0.1-28461"]
… INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-127.0.0.1-28461"]
… INFO [main] org.apache.catalina.startup.Catalina.start Server startup in […] milliseconds
$ java CheckInstall.java apache-tomcat-11.0.26 # after the changes, while Tomcat runs
PASS shutdown port 28471 needs a 32-character command
PASS connector 28461 listens on 127.0.0.1 only
PASS the HTTP port is 28461
PASS webapps holds none of the sample apps
INFO logs/catalina.out: the last start was Apache Tomcat/11.0.26
INFO Tomcat answers on 127.0.0.1:28461
All checks passed.
$ apache-tomcat-11.0.26/bin/shutdown.sh
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 install_session.py
Reading it from the top:
shasum -a 512 -crecomputes the checksum of the archive and compares it with the published one:OK. On Linux the same check issha512sum -c; on Windows,certutil -hashfile <file> SHA512prints the value to compare.bin/version.shconfirms the Tomcat version and the JVM it will use: Eclipse Temurin 25.0.4.1, taken fromJAVA_HOME. Tomcat needsJAVA_HOME(orJRE_HOME) to point at a JDK; set it before you run any of its scripts.- The checker,
CheckInstall.javabelow, fails the download as it comes on four points. Each one is a default that suits a quick start but not a computer on a shared network. - After the changes, Tomcat starts, answers 404 on
/because no application is deployed yet, and logs its version, the JVM and the address it listens on:http-nio-127.0.0.1-28461.
Three changes for a safe local Tomcat
The edited conf/server.xml is Tomcat’s own file without its comments, which Tomcat’s security guide suggests for
readability, and with two changes marked:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tomcat 11.0.26's conf/server.xml without its comments, with two changes, marked CHANGED. -->
<!-- CHANGED: shutdown.sh stops Tomcat by sending this command to port 28471 on this computer. The default command,
SHUTDOWN, lets any program on the computer stop Tomcat; use a long random string of your own instead. -->
<Server port="28471" shutdown="nppoc2r6x2tt7etz8rq87koackcj1yc7">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<!-- CHANGED: address="127.0.0.1" accepts connections from this computer only, on port 28461 instead of 8080. -->
<Connector address="127.0.0.1" port="28461" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server> Bind the connector to 127.0.0.1. Without an address attribute, the HTTP connector listens on every network
address of the computer, so anyone on the same Wi-Fi or office network can reach your applications unless a firewall
stops them. With address="127.0.0.1" only programs on your own computer can. The port is yours to choose; this module
uses 28461 and other ports in that range, so that it never collides with another program that took 8080.
Protect the shutdown port. Tomcat listens on port 8005 of localhost for the word SHUTDOWN, and stops when any
program on the computer sends it. The security guide gives two answers: switch the port off with port="-1", which
the Server reference recommends only when Tomcat runs as a service, or keep it and replace the word with a long random
command, which the startup.sh and shutdown.sh scripts used here need. The value in this file is an example:
generate your own.
Remove the sample applications. The download deploys five applications: ROOT, a welcome page that shows the
Tomcat version; docs, the documentation; examples, servlet and JSP demonstrations; and manager and
host-manager, which deploy applications and add virtual hosts through a browser. The security guide says the
examples application “should always be removed from any security sensitive installation”. The two managers refuse
everyone until a user is added to conf/tomcat-users.xml, and the next lessons deploy by copying files instead. A
local Tomcat needs none of the five, so all of them go.
Two more facts help when you run several instances. CATALINA_HOME is the folder you unpacked; CATALINA_BASE, if
you set it, is a second folder with its own conf, logs, webapps, temp and work, so one download can serve
several instances while staying exactly as Apache shipped it. The later lessons of this module use one base folder
per lesson in that way.
Your turn: a checked local install
Install Tomcat 11 on your own computer by following the session above, with a port of your choice and a shutdown command of your own, then run the checker against your Tomcat folder while Tomcat runs:
// Checks a Tomcat folder against the local setup of this lesson: java CheckInstall.java <tomcat folder>
// It reads conf/server.xml, webapps/ and logs/catalina.out, then tries the HTTP port. Exit status 1 if a check fails.
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Element;
int failed = 0;
void check(boolean ok, String pass, String fail) {
IO.println((ok ? "PASS " : "FAIL ") + (ok ? pass : fail));
if (!ok) failed++;
}
void main(String[] args) throws Exception {
Path tomcat = Path.of(args.length > 0 ? args[0] : ".");
var factory = DocumentBuilderFactory.newInstance();
// server.xml needs no DOCTYPE; refusing one keeps the parser from reading other files.
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
Element server = factory.newDocumentBuilder().parse(tomcat.resolve("conf/server.xml").toFile()).getDocumentElement();
String shutdownPort = server.getAttribute("port");
String command = server.getAttribute("shutdown");
check(shutdownPort.equals("-1") || (!command.equals("SHUTDOWN") && command.length() >= 16),
shutdownPort.equals("-1") ? "the shutdown port is switched off"
: "shutdown port " + shutdownPort + " needs a " + command.length() + "-character command",
"shutdown port " + shutdownPort + " stops Tomcat for any program on this computer that sends \"" + command + "\"");
int httpPort = -1;
var connectors = server.getElementsByTagName("Connector");
for (int i = 0; i < connectors.getLength(); i++) {
var connector = (Element) connectors.item(i);
String port = connector.getAttribute("port");
String address = connector.getAttribute("address");
check(Set.of("127.0.0.1", "localhost", "::1").contains(address), "connector " + port + " listens on " + address + " only",
"connector " + port + " listens on every network address (no address attribute)");
if (connector.getAttribute("protocol").startsWith("HTTP/1.1")) httpPort = Integer.parseInt(port);
}
check(httpPort != 8080, "the HTTP port is " + httpPort, "the HTTP port is still the default, 8080");
Path webapps = tomcat.resolve("webapps");
List<String> samples = Stream.of("ROOT", "docs", "examples", "host-manager", "manager")
.filter(name -> Files.exists(webapps.resolve(name)))
.toList();
check(samples.isEmpty(), "webapps holds none of the sample apps", "webapps still holds " + String.join(", ", samples));
Path log = tomcat.resolve("logs/catalina.out");
String marker = "Server version name:";
Optional<String> version = Files.exists(log)
? Files.readAllLines(log).stream().filter(line -> line.contains(marker))
.map(line -> line.substring(line.indexOf(marker) + marker.length()).strip()).reduce((first, last) -> last)
: Optional.empty();
IO.println("INFO logs/catalina.out: " + version.map(v -> "the last start was " + v).orElse("Tomcat has not started yet"));
try (var socket = new Socket()) {
socket.connect(new InetSocketAddress("127.0.0.1", httpPort), 1000);
IO.println("INFO Tomcat answers on 127.0.0.1:" + httpPort);
} catch (IOException e) {
IO.println("INFO nothing answers on 127.0.0.1:" + httpPort);
}
IO.println(failed == 0 ? "All checks passed." : failed + (failed == 1 ? " check failed." : " checks failed."));
if (failed > 0) System.exit(1);
} It reads conf/server.xml, the webapps folder and logs/catalina.out, and tries the HTTP port. All four checks
must pass, and the two INFO lines must name the version that your Tomcat logged and confirm that it answers. Then
stop Tomcat with bin/shutdown.sh (bin\shutdown.bat on Windows) and run the checker once more: the checks still
pass, and the second INFO line now says that nothing answers.
Check yourself
4 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
Interview questions
Fresher · What is the difference between a servlet container such as Tomcat and a Jakarta EE application server?
A servlet container implements the web tier of Jakarta EE: it accepts HTTP connections, maps each URL to a web
application and a servlet, manages the servlets’ life cycle and runs them on its threads. Tomcat 11 does that for
Servlet 6.1 and also implements Pages, Expression Language, WebSocket and Authentication. A Jakarta EE application
server, such as GlassFish, WildFly or Open Liberty, implements a whole profile or the full platform, so CDI,
Persistence, Faces, Validation and transactions are built in and configured by the server. On Tomcat, an application
that needs those APIs packs an implementation, such as Hibernate ORM for Persistence, in its own WEB-INF/lib folder.
Both run the same servlets, so code written against the Servlet API moves between them.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
A team copies a WAR that ran on Tomcat 9 into the webapps folder of Tomcat 11. Tomcat logs no error, but every servlet URL of the application answers 404. What happened, and what are the two ways to fix it?
-
Fresher to mid
A scan of a shared test server finds Tomcat 11 answering on port 8080 on every network address, the examples and docs applications deployed, and port 8005 open on localhost with the default command. Rank these risks and say exactly what you change.
Key takeaways
- Jakarta EE is a family of specifications in three sizes, from the Core Profile to the full Platform; Tomcat 11 implements its web container part, Servlet 6.1 first, and leaves CDI, Persistence and Faces to the application or to a full application server.
- Tomcat 11 and 10.1 use the
jakartapackages and Tomcat 9 the oldjavaxones; ajavaxservlet does not even compile against Tomcat 11’s API. - Check every download against its published SHA-512 or signature, and set
JAVA_HOMEbefore you run Tomcat’s scripts. - For local work, bind the connector to 127.0.0.1, protect or switch off the shutdown port, and remove the five sample applications.
References
- Jakarta EE 11 release (Eclipse Foundation)
- Jakarta EE 12 (under development) (Eclipse Foundation)
- Jakarta Servlet 6.1 (Eclipse Foundation)
- Jakarta EE compatible products (Eclipse Foundation)
- Apache Tomcat versions (which version do I want?) (The Apache Software Foundation)
- Apache Tomcat 11 software downloads (The Apache Software Foundation)
- Apache Tomcat 11: Tomcat Setup (The Apache Software Foundation)
- Apache Tomcat 11: RUNNING.txt (The Apache Software Foundation)
- Apache Tomcat 11: Security Considerations (The Apache Software Foundation)
- Apache Tomcat 11 Configuration Reference: The HTTP Connector (The Apache Software Foundation)
- Apache Tomcat 11 Configuration Reference: The Server Component (The Apache Software Foundation)
- Migrating from Apache Tomcat 9.0.x to 10.0.x (The Apache Software Foundation)
- Spring Boot: System Requirements (Broadcom (Spring))
- Spring Framework: DispatcherServlet (Broadcom (Spring))
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress