Skip to main content
Advertisement

web.xml and Context Configuration

web.xml is the deployment descriptor for Java web applications, defining servlet mappings, filters, listeners, session settings, and more. Tomcat has two types: a global web.xml and an application-specific web.xml.


web.xml Hierarchy

$CATALINA_HOME/conf/web.xml          ← Global defaults (provided by Tomcat)
↓ Override / merge
$APP/WEB-INF/web.xml ← Per-application configuration

The global web.xml is managed by Tomcat — avoid editing it directly. Most customization goes into the application's WEB-INF/web.xml.


Key Settings in Global web.xml

$CATALINA_HOME/conf/web.xml contains Tomcat's built-in servlets.

<!-- DefaultServlet — serves static files -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value> <!-- Disable directory listing -->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- JSP Servlet -->
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value> <!-- Hide X-Powered-By header -->
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>

Application web.xml Structure

<?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>My Application</display-name>

<!-- Global parameters -->
<context-param>
<param-name>applicationEnvironment</param-name>
<param-value>production</param-value>
</context-param>

</web-app>

Version note: From Tomcat 10, use the jakarta.ee namespace. Tomcat 9 and below use javax.servlet.


Servlet Registration and Mapping

<!-- Servlet definition -->
<servlet>
<servlet-name>ApiServlet</servlet-name>
<servlet-class>com.example.api.ApiServlet</servlet-class>
<init-param>
<param-name>maxRequestSize</param-name>
<param-value>10485760</param-value> <!-- 10MB -->
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>

<!-- URL mapping -->
<servlet-mapping>
<servlet-name>ApiServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>

<!-- Spring MVC DispatcherServlet example -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Filter Registration

<!-- Character encoding filter -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- CORS filter -->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://example.com,https://www.example.com</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>

Session Configuration

<session-config>
<session-timeout>30</session-timeout> <!-- minutes -->
<cookie-config>
<name>JSESSIONID</name>
<http-only>true</http-only> <!-- Block JavaScript access -->
<secure>true</secure> <!-- HTTPS only -->
<same-site>Strict</same-site> <!-- CSRF prevention (Servlet 6.0+) -->
</cookie-config>
<tracking-mode>COOKIE</tracking-mode> <!-- Disable URL session tracking -->
</session-config>

Security: Explicitly setting <tracking-mode>COOKIE</tracking-mode> prevents jsessionid=xxx from being exposed in URLs. URL-based session tracking is vulnerable to session fixation attacks.


JNDI Resource Reference

<!-- Declare JNDI resource reference -->
<resource-ref>
<description>Production Database</description>
<res-ref-name>jdbc/myDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

The actual DataSource is defined in context.xml or server.xml's GlobalNamingResources.

// JNDI lookup in application code
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/myDB");
Connection conn = ds.getConnection();

Error Page Configuration

<!-- Error pages by HTTP status code -->
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>

<!-- Error pages by exception type -->
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error/general.jsp</location>
</error-page>
<error-page>
<exception-type>java.sql.SQLException</exception-type>
<location>/error/db-error.jsp</location>
</error-page>

Security Constraints

<!-- Require authentication for specific URLs -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin Area</web-resource-name>
<url-pattern>/admin/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>

<security-role>
<role-name>admin</role-name>
</security-role>

context.xml — Context-Specific Settings

<!-- WEB-INF/context.xml -->
<Context>
<!-- Session persistence (maintain sessions across restarts) -->
<Manager className="org.apache.catalina.session.PersistentManager"
maxIdleBackup="1">
<Store className="org.apache.catalina.session.FileStore"
directory="/var/tomcat-sessions"/>
</Manager>

<!-- Resource cache settings -->
<Resources cachingAllowed="true"
cacheMaxSize="100000"/>
</Context>

Summary

FileLocationRole
Global web.xml$CATALINA_HOME/conf/web.xmlDefault servlets, default MIME types
App web.xml$APP/WEB-INF/web.xmlServlets, filters, sessions, security
Context XMLconf/Catalina/localhost/app.xmlApp-specific Tomcat settings, DataSource
context.xmlconf/context.xml or WEB-INF/context.xmlSession persistence, resource cache
Session security<tracking-mode>COOKIE</tracking-mode>Prevent URL session exposure
JNDI DataSourceContext XML + <resource-ref>Externalize DB connection pools
Advertisement