When starting a Java web application on Apache Tomcat, you might encounter an intimidating message like this:
SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.filterStart
Exception starting filter [monitoringFilter]
java.lang.AbstractMethodError
This type of error can prevent your application from starting altogether — but the good news is that it’s almost always caused by a simple library incompatibility.
Let’s explore what this error means, why it happens, and how to resolve it properly.
🧩 What Is java.lang.AbstractMethodError?
The java.lang.AbstractMethodError occurs when a class tries to call an abstract method that it doesn’t actually implement. In most cases, this happens due to version mismatches between compiled code and runtime libraries.
Example:
Imagine you compiled your project against version 1.2 of a library that defines an interface like this:
public interface MyFilter {
void init(FilterConfig config);
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);
}
Later, you upgraded the dependency on your server to version 1.3, where a new abstract method was added:
public interface MyFilter {
void init(FilterConfig config);
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);
void destroy(); // newly added
}
Your old compiled filter class doesn’t implement destroy(), so at runtime, Tomcat throws:
java.lang.AbstractMethodError
⚙️ Common Scenarios That Trigger This Error
1️⃣ Outdated or Conflicting JAR Files
If your project has multiple versions of the same library (for example, servlet-api.jar in both Tomcat and WEB-INF/lib), one version might shadow another.
Example:
- Tomcat already provides
servlet-api.jar. - Your app’s
WEB-INF/libfolder also contains a differentservlet-api.jar. - During startup, Tomcat loads the wrong version, leading to
AbstractMethodError.
✅ Fix:
Remove servlet-api.jar (and similar container-provided libraries) from your WEB-INF/lib.
Let Tomcat use its own provided version.
2️⃣ Filter or Listener Compiled Against a Different Servlet Version
Suppose you have a MonitoringFilter implemented like this:
public class MonitoringFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) { /* ... */ }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
}
// Missing destroy() method
}
When deployed on a newer Tomcat version that expects destroy() to exist, startup fails with AbstractMethodError.
✅ Fix:
Always implement all methods required by the interface:
@Override
public void destroy() {
// cleanup logic
}
3️⃣ Dependency Version Conflict in Maven or Gradle
If you use Maven or Gradle, dependency conflicts can be silent killers. For example, two dependencies might pull in different versions of the same library.
You can check for conflicts with:
mvn dependency:tree
or in Gradle:
gradle dependencies
Look for libraries like javax.servlet, jakarta.servlet, or spring-web appearing multiple times with different versions.
✅ Fix:
Force the correct version in your build file.
For example, in Maven:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
</dependencyManagement>
4️⃣ Mixing javax.* and jakarta.* Packages
With the transition from Java EE to Jakarta EE, the package names changed from javax.servlet.* to jakarta.servlet.*. Mixing them in the same project can cause runtime incompatibility.
✅ Fix:
Make sure your dependencies and Tomcat version align:
- Tomcat 9 or older →
javax.* - Tomcat 10 or newer →
jakarta.*
If you migrate from Tomcat 9 → 10, use the Eclipse Transformer Tool to automatically rename packages.
🔍 Step-by-Step Troubleshooting Guide
- Check Tomcat Version
$CATALINA_HOME/bin/version.sh - Inspect Your Classpath
- Check
/WEB-INF/libfor duplicates. - Remove libraries already provided by Tomcat.
- Check
- Review Dependencies
- Run
mvn dependency:treeorgradle dependencies. - Align all servlet-related versions.
- Run
- Clean and Rebuild
mvn clean packageor
gradle clean build - Check Interface Changes
- Open your filter class (like
MonitoringFilter) and make sure it implements all interface methods.
- Open your filter class (like
- Review
web.xml- Ensure the filter class name is correct and refers to the right package.
Example:
<filter> <filter-name>monitoringFilter</filter-name> <filter-class>com.example.filters.MonitoringFilter</filter-class> </filter>
🧠 Example of a Clean Filter Implementation
Here’s a working example compatible with Tomcat 9+:
package com.example.filters;
import javax.servlet.*;
import java.io.IOException;
public class MonitoringFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MonitoringFilter initialized.");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
long start = System.currentTimeMillis();
chain.doFilter(request, response);
long end = System.currentTimeMillis();
System.out.println("Request processed in " + (end - start) + " ms");
}
@Override
public void destroy() {
System.out.println("MonitoringFilter destroyed.");
}
}
This version properly implements all required methods and avoids the AbstractMethodError.
🧰 Quick Recap
| Root Cause | Typical Fix |
|---|---|
| Old or duplicate JARs | Remove duplicates and use Tomcat’s libraries |
| Missing method in interface | Rebuild code to include new interface methods |
| Dependency mismatch | Align versions in pom.xml or build.gradle |
| Migration to Jakarta EE | Use consistent package naming |
🏁 Conclusion
java.lang.AbstractMethodError may look scary, but it’s almost always caused by a version mismatch between what your code expects and what’s available at runtime.
By aligning dependencies, cleaning your classpath, and ensuring consistent library versions, you can fix the issue quickly and keep your Tomcat applications stable and reliable.
