Configuring Servlets Using Annotations and Deployment Descriptors
Course: Advanced Java Training
Topic: Configuring Servlets Using Annotations and Deployment Descriptors
Course Link: Advanced Java Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy
1. Introduction
Servlet configuration is an essential part of Java web application development. It tells the servlet container how to identify a servlet, which URL patterns should route requests to it, what initialization parameters it needs, and how it should be deployed.
In Java web applications, servlets can be configured primarily using two approaches:
- Annotations: Configuration is declared directly in Java source code using annotations such as
@WebServlet.
- Deployment descriptors: Configuration is defined in an XML file named
web.xml, located inside the application's WEB-INF directory.
Annotations reduce the amount of XML configuration required, while deployment descriptors provide centralized configuration and can override supported annotation settings. Both approaches are supported by modern Jakarta Servlet containers.
2. Learning Objectives
- Understand servlet configuration and URL mapping.
- Learn how to configure servlets using
@WebServlet.
- Understand the structure and purpose of
web.xml.
- Configure servlet names, URL patterns, and initialization parameters.
- Learn how to use annotations and deployment descriptors together.
- Understand servlet loading and startup configuration.
- Explore common configuration errors and their solutions.
- Build and deploy a servlet application using both configuration methods.
3. What Is Servlet Configuration?
Servlet configuration is the process of defining how a servlet is registered and managed by a web container, such as Apache Tomcat.
For example, if a Java application contains a servlet named WelcomeServlet, the container needs to know which URL should invoke it. A mapping such as /welcome allows a client request to reach the servlet.
Important Configuration Elements
| Element |
Purpose |
| Servlet name |
Identifies a servlet within the web application configuration. |
| Servlet class |
Specifies the fully qualified Java class that implements the servlet. |
| URL pattern |
Defines the request path or paths mapped to the servlet. |
| Initialization parameter |
Provides configuration values to an individual servlet. |
| Load-on-startup |
Requests that the servlet be initialized during application startup. |
| Async support |
Indicates whether the servlet supports asynchronous request processing. |
| Welcome files and error pages |
Configure other web-application behaviors through the deployment descriptor. |
4. Configuring Servlets Using Annotations
Annotations are metadata declarations placed directly in Java source code. Servlet annotations allow developers to define configuration without writing a separate XML entry for every servlet.
The @WebServlet annotation, introduced in Servlet 3.0, is used to declare a servlet and its URL mapping.
Basic Syntax
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
@WebServlet("/welcome")
public class WelcomeServlet extends HttpServlet {
// Request-handling methods
}
In this example, @WebServlet("/welcome") registers the servlet with the URL pattern /welcome.
Example: Complete Servlet Using an Annotation
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("/welcome")
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println(
"<h1>Welcome to Advanced Java!</h1>"
);
}
}
How It Works
- The servlet container scans eligible application classes for servlet configuration annotations.
- It discovers the
@WebServlet declaration.
- The container registers the servlet with the specified URL pattern.
- When a GET request matches the mapping, the container invokes the servlet's HTTP request-handling method.
- The servlet generates a response that is returned to the client.
5. Important Attributes of @WebServlet
The @WebServlet annotation provides several optional attributes for configuring a servlet.
| Attribute |
Description |
Example |
name |
Defines the servlet's configured name. |
name="WelcomeServlet" |
value |
Specifies a URL pattern when used as the shorthand form. |
@WebServlet("/welcome") |
urlPatterns |
Specifies one or more URL patterns. |
urlPatterns={"/welcome","/hello"} |
loadOnStartup |
Requests eager initialization during startup. |
loadOnStartup=1 |
initParams |
Defines servlet-specific initialization parameters. |
@WebInitParam(...) |
asyncSupported |
Declares support for asynchronous processing. |
asyncSupported=true |
description |
Provides a description of the servlet. |
description="Welcome page" |
Note: Use either value or urlPatterns to specify the mapping, not both in the same annotation. When additional attributes are needed, urlPatterns is generally clearer.
6. Mapping Multiple URL Patterns
A single servlet can handle multiple URL patterns. This is useful when different URLs should share the same request-processing logic.
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(
name = "GreetingServlet",
urlPatterns = {"/greeting", "/hello", "/welcome-user"}
)
public class GreetingServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Hello! Welcome to our application.");
}
}
The same servlet handles requests matching any of the configured patterns, subject to the container's URL-mapping rules.
7. Configuring Initialization Parameters with Annotations
Initialization parameters allow configuration values to be supplied without hardcoding them directly into the request-processing logic.
The @WebInitParam annotation is used within @WebServlet to define a servlet-specific parameter.
Example
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(
name = "MessageServlet",
urlPatterns = "/message",
initParams = {
@WebInitParam(
name = "message",
value = "Servlet configured with annotations"
)
}
)
public class MessageServlet extends HttpServlet {
private String message;
@Override
public void init() throws ServletException {
message = getServletConfig().getInitParameter("message");
if (message == null) {
throw new ServletException("Message parameter is missing.");
}
}
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println(message);
}
}
Explanation
- The
initParams attribute defines a parameter named message.
- The container makes the parameter available through the servlet configuration.
- The servlet reads the parameter during initialization.
- The
doGet() method uses the stored value when responding to a request.
8. What Is a Deployment Descriptor?
A deployment descriptor is an XML configuration file that describes how a Java web application should be deployed. For a servlet-based web application, the standard deployment descriptor is web.xml.
It is normally located at:
src/main/webapp/WEB-INF/web.xml
After packaging a WAR file, the descriptor is available at:
WEB-INF/web.xml
The descriptor can define servlet registrations and mappings, initialization parameters, application-wide context parameters, filters, listeners, welcome files, error-page mappings, session configuration, and other supported deployment settings.
9. Structure of web.xml
The web.xml file uses XML elements to define configuration. The namespace and schema version should match the Jakarta Servlet version supported by the target container.
Example: Jakarta Servlet 6.0 Deployment Descriptor
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<display-name>AdvancedJavaApp</display-name>
</web-app>
This descriptor establishes the web application's deployment configuration. Servlet declarations and mappings can be added inside the web-app element.
Compatibility note: This example uses the Jakarta Servlet 6.0 descriptor. Use a compatible container, such as Apache Tomcat 10.1 for Servlet 6.0 applications. Older Java EE applications commonly use javax.servlet and older XML namespaces; do not mix the two API generations unintentionally.
10. Configuring a Servlet in web.xml
To register a servlet using XML, two important elements are used:
<servlet> declares the servlet name and its Java implementation class.
<servlet-mapping> associates the configured servlet name with one or more URL patterns.
Example: Servlet Declaration and Mapping
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<servlet>
<servlet-name>WelcomeServlet</servlet-name>
<servlet-class>com.example.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WelcomeServlet</servlet-name>
<url-pattern>/welcome</url-pattern>
</servlet-mapping>
</web-app>
Explanation
- The
<servlet> element registers a servlet under the name WelcomeServlet.
- The
<servlet-class> element specifies its fully qualified class name.
- The
<servlet-mapping> element connects the configured name to a URL pattern.
- The container routes matching requests to the servlet after successful initialization.
The servlet class must exist in the deployed application and must be compatible with the Servlet API provided by the container.
11. Configuring Initialization Parameters in web.xml
Initialization parameters can also be declared using the <init-param> element inside a servlet declaration.
<servlet>
<servlet-name>ConfigServlet</servlet-name>
<servlet-class>com.example.ConfigServlet</servlet-class>
<init-param>
<param-name>applicationMessage</param-name>
<param-value>Welcome from web.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ConfigServlet</servlet-name>
<url-pattern>/config</url-pattern>
</servlet-mapping>
Inside the servlet, the value can be retrieved using getServletConfig().getInitParameter().
Java Servlet Example
package com.example;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class ConfigServlet extends HttpServlet {
private String applicationMessage;
@Override
public void init() throws ServletException {
applicationMessage = getServletConfig()
.getInitParameter("applicationMessage");
if (applicationMessage == null) {
throw new ServletException(
"applicationMessage is not configured."
);
}
}
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println(applicationMessage);
}
}
12. Application-Wide Context Parameters
Servlet initialization parameters belong to a specific servlet. In contrast, context parameters are application-wide configuration values accessible through the ServletContext.
Example of a Context Parameter
<context-param>
<param-name>applicationName</param-name>
<param-value>Student Management System</param-value>
</context-param>
Reading the Parameter in Java
String applicationName = getServletContext()
.getInitParameter("applicationName");
| Feature |
Servlet Initialization Parameter |
Context Parameter |
| Configuration scope |
One servlet |
Entire web application |
| XML element |
<init-param> |
<context-param> |
| Access method |
getServletConfig().getInitParameter() |
getServletContext().getInitParameter() |
| Typical use |
Servlet-specific message or behavior |
Shared application name or general setting |
13. Configuring Servlet Startup with load-on-startup
By default, a servlet may be initialized when the container first needs it. The loadOnStartup annotation attribute or the <load-on-startup> XML element can request initialization during application startup.
Annotation Example
@WebServlet(
urlPatterns = "/reports",
loadOnStartup = 1
)
public class ReportServlet extends HttpServlet {
// Servlet implementation
}
Deployment Descriptor Example
<servlet>
<servlet-name>ReportServlet</servlet-name>
<servlet-class>com.example.ReportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ReportServlet</servlet-name>
<url-pattern>/reports</url-pattern>
</servlet-mapping>
A non-negative startup value requests eager loading. When multiple servlets have such values, the values help determine initialization order; lower values are initialized before higher values. Equal values do not guarantee a particular relative order.
Use eager initialization when a servlet must be initialized before the first request. Remember that expensive initialization can increase application startup time.
14. Annotation-Based Configuration vs web.xml
| Feature |
Annotations |
Deployment Descriptor |
| Configuration location |
Java source code |
XML file |
| Primary servlet declaration |
@WebServlet |
<servlet> |
| URL mapping |
value or urlPatterns |
<servlet-mapping> |
| Initialization parameters |
@WebInitParam |
<init-param> |
| Readability |
Convenient for small or self-contained configurations |
Centralizes configuration for larger deployments |
| Maintenance |
Configuration is close to the servlet class |
Configuration is separate from Java code |
| Overriding settings |
Provides default declarations |
Can override supported annotation metadata |
| Requirement |
Requires annotation processing by the container |
Requires valid XML and a compatible deployment descriptor version |
15. Can Annotations and web.xml Be Used Together?
Yes. Annotations and the deployment descriptor can be used in the same application. This is useful when developers prefer annotations for basic declarations but need centralized deployment settings.
For servlet configuration, the deployment descriptor can override supported annotation values when the servlet is matched by its configured name. The servlet name must match the annotation's explicit name or its default name for the override rules to apply.
Example: Servlet Declared with an Annotation
package com.example;
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(
name = "InfoServlet",
urlPatterns = "/info"
)
public class InfoServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Servlet configuration example.");
}
}
Example: Matching Entry in web.xml
<servlet>
<servlet-name>InfoServlet</servlet-name>
<servlet-class>com.example.InfoServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>InfoServlet</servlet-name>
<url-pattern>/application-info</url-pattern>
</servlet-mapping>
Because the XML servlet name matches the annotation name, the XML mapping can override the annotation's URL pattern, and the startup setting can be supplied centrally.
Important: Do not declare the same servlet under unrelated names unless you intentionally want separate servlet registrations. Different names can result in different servlet instances.
16. Understanding metadata-complete
The metadata-complete attribute on the <web-app> element controls whether annotation and web-fragment metadata is considered during deployment.
Example
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0"
metadata-complete="true">
<!-- Declare required deployment metadata here -->
</web-app>
When metadata-complete="true" is used, the container treats the deployment descriptor as complete and does not process component deployment annotations such as @WebServlet for that application. Required servlet registrations must therefore be declared in XML.
When the attribute is omitted or set to false, annotation processing can occur according to the Servlet specification and container behavior.
Use metadata-complete="true" only when the application is intentionally configured through the descriptor and you understand the effect on annotations and web fragments.
17. Common URL Mapping Patterns
Servlet mappings determine which servlet receives a request. Selecting appropriate URL patterns helps keep application routing clear and predictable.
| Pattern |
Meaning |
Example Request Path |
/welcome |
Exact path mapping |
/welcome |
/admin/* |
Path-prefix mapping |
/admin/users |
*.do |
Extension mapping |
/login.do |
/ |
Default servlet mapping, subject to container mapping rules |
Requests not matched by more specific mappings |
Mapping precedence follows Servlet specification rules. Exact mappings are more specific than path mappings, and path mappings are generally more specific than extension mappings. The default mapping is considered after more specific mappings. The container also provides its own handling for static resources.
18. Application Structure and Deployment
A typical Maven-based servlet application can use the following directory structure:
AdvancedJavaApp/
├── pom.xml
└── src/
└── main/
├── java/
│ └── com/
│ └── example/
│ ├── WelcomeServlet.java
│ └── ConfigServlet.java
└── webapp/
├── index.html
└── WEB-INF/
└── web.xml
The web.xml file is optional for applications that do not need a deployment descriptor and use annotations for their servlet declarations, provided the application and container support that configuration.
Basic Deployment Steps
- Create a web application project and select a compatible Servlet API version.
- Write the servlet class and configure it using annotations or
web.xml.
- Compile the application against the Servlet API provided by the container.
- Package the application as a WAR file.
- Deploy the WAR file to a compatible servlet container.
- Start the application and check the container logs for deployment errors.
- Open the correct context path and servlet URL in a browser.
For example, if the WAR is deployed with the context path /AdvancedJavaApp and the servlet mapping is /welcome, the URL is typically:
http://localhost:8080/AdvancedJavaApp/welcome
The context path depends on how the application is deployed, so replace it with the actual context path used by your server.
19. Common Errors and Troubleshooting
| Error or Problem |
Possible Cause |
Solution |
| HTTP 404 Not Found |
Incorrect URL pattern or context path. |
Verify the mapping and deployed application URL. |
| Servlet class not found |
Incorrect fully qualified class name or missing compiled class. |
Check the package declaration and build output. |
| Invalid web.xml |
Incorrect XML syntax, namespace, schema, or element placement. |
Validate the descriptor against the supported Servlet version. |
| Annotation is ignored |
Annotation scanning is disabled or the class is outside the scanned application locations. |
Check metadata-complete, packaging, and container support. |
| HTTP 405 Method Not Allowed |
The servlet does not support the requested HTTP method. |
Implement the correct handler and verify the client request. |
| Duplicate or unexpected servlet registration |
The same servlet class is declared with multiple names or conflicting mappings. |
Review annotations and XML registrations. |
| Servlet API class not found |
The application uses the wrong API namespace or incompatible server version. |
Align the Servlet API dependency with the target container. |
| Initialization parameter is null |
Incorrect parameter name or parameter declared in the wrong scope. |
Check the exact name and whether it is a servlet or context parameter. |
20. Best Practices
- Use annotations for straightforward, self-contained servlet configuration.
- Use
web.xml when centralized configuration, overrides, or other descriptor settings are required.
- Keep servlet names consistent when overriding annotation configuration through XML.
- Choose a Servlet API and container version that are compatible.
- Use
jakarta.servlet for modern Jakarta Servlet applications and javax.servlet only for compatible legacy applications.
- Validate XML syntax and use the correct namespace and schema version.
- Use clear, consistent URL patterns.
- Keep sensitive credentials out of source code and deployment descriptors committed to version control.
- Use initialization parameters for non-secret configuration values.
- Check container logs when deployment or initialization fails.
- Avoid unnecessary eager initialization if it significantly slows application startup.
- Do not declare duplicate servlet mappings unless the design intentionally requires them.
21. Practical Exercises
- Create a
WelcomeServlet using @WebServlet("/welcome").
- Configure the same servlet through
web.xml and test the URL mapping.
- Add two URL patterns to one servlet using
urlPatterns.
- Configure an initialization parameter using
@WebInitParam and read it in init().
- Move the initialization parameter into
web.xml and verify the value.
- Define a context parameter and access it using
ServletContext.
- Configure
load-on-startup and observe the servlet's initialization log.
- Set
metadata-complete="true" in a test application and observe the impact on annotation-based registration.
- Intentionally introduce an invalid URL mapping or class name and investigate the container logs.
22. Interview Questions and Answers
Q1. What is servlet configuration?
Answer: Servlet configuration defines how a servlet is registered, mapped to URL patterns, initialized, and managed by the servlet container.
Q2. What is the purpose of @WebServlet?
Answer: It declares a servlet and its deployment metadata, including one or more URL patterns.
Q3. What is web.xml?
Answer: It is the XML deployment descriptor used to define web-application configuration, including servlet declarations, mappings, initialization parameters, and other deployment settings.
Q4. Is web.xml mandatory for every servlet application?
Answer: No. In modern Servlet applications, annotations can provide servlet configuration without a deployment descriptor when no other configuration requirement makes it necessary.
Q5. What is the difference between @WebServlet and web.xml?
Answer: @WebServlet declares servlet configuration in Java code, while web.xml defines configuration in XML and can override supported annotation metadata.
Q6. What is the difference between init-param and context-param?
Answer: An init-param belongs to a specific servlet, while a context-param is available at the web-application level through ServletContext.
Q7. What does load-on-startup do?
Answer: It requests that the servlet be initialized during application startup instead of waiting until the servlet is first needed.
Q8. What is metadata-complete?
Answer: It indicates whether the deployment descriptor is complete. When set to true, the container ignores component deployment annotations and web-fragment metadata as specified by the Servlet rules.
Q9. Can annotations and web.xml be used together?
Answer: Yes. They can be combined, and supported descriptor entries can override annotation metadata when the configuration names and specification rules match.
Q10. What causes a servlet mapping to return 404?
Answer: Common causes include an incorrect context path, incorrect URL pattern, failed deployment, or missing servlet registration.
23. Quick Revision Checklist
@WebServlet registers a servlet using annotation metadata.
web.xml is the XML deployment descriptor.
<servlet> declares a servlet and its class.
<servlet-mapping> maps a servlet name to a URL pattern.
@WebInitParam and <init-param> configure servlet-specific parameters.
<context-param> defines application-wide initialization parameters.
loadOnStartup and <load-on-startup> request eager initialization.
- Annotations and XML can be combined when configuration rules are followed.
metadata-complete="true" disables processing of component deployment annotations and web fragments.
- Always match the Servlet API namespace and version to the target container.
24. Conclusion
Configuring servlets using annotations and deployment descriptors is a fundamental skill in Advanced Java web development. Annotations make common configuration concise and convenient, while web.xml offers centralized control over servlet mappings and application deployment settings.
Understanding how these approaches work independently and together helps developers build maintainable applications, avoid configuration conflicts, troubleshoot deployment issues, and deploy servlet applications successfully to a compatible web container.
25. Additional Learning Resources