Getting NoSuchMethodError: javax.servlet.ServletContext.addServlet in Spring Boot while running a Spring MVC application

62,854

Solution 1

If you want to find out where the class is being loaded from, try

java -verbose:class -jar foo.jar | grep javax.servlet.ServletContext

where foo.jar is the fat JAR produced by Gradle or Maven. For example, the ServletContext class could be getting read from an older servlet-api JAR in a JDK extensions directory instead of your Maven or Gradle dependencies.

The output of the command looks something like this...

$ java -verbose:class -jar build/libs/foo-0.2.3.jar | grep javax.servlet.ServletContext
[Loaded javax.servlet.ServletContext from jar:file:.../build/libs/foo-0.2.3.jar!/lib/javax.servlet-api-3.1.0.jar!/]
[Loaded javax.servlet.ServletContextListener from jar:file:.../build/libs/foo-0.2.3.jar!/lib/javax.servlet-api-3.1.0.jar!/]
[Loaded javax.servlet.ServletContextAttributeListener from jar:file:.../build/libs/foo-0.2.3.jar!/lib/javax.servlet-api-3.1.0.jar!/]

Solution 2

I solved it excluding a transitive servlet-api dependency.

In my case, it was com.github.isrsal:spring-mvc-logger

<dependency>
    <groupId>com.github.isrsal</groupId>
    <artifactId>spring-mvc-logger</artifactId>
    <version>0.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Solution 3

gradle solution.

I had a similar problem in my lib jar which for some reason brought with it an old version of javax.servlet.ServletContext which was later loaded by my spring-boot module instead of its own supplied class, by that causing a NoSuchMethodError

I fixed it by editing the build.gradle of my lib module :

configurations {
    provided.all*.exclude group: 'javax.servlet'
}

Solution 4

For anyone else who couldn't solve it by excluding servlet-api , here is an alternative:

It turns out Spring Boot defaults to Tomcat 8. If you're running a different version of Tomcat and would like to fix this error, just add your tomcat version to the pom properties:

<properties>
    <tomcat.version>7.0.63</tomcat.version>
</properties> 

Solution 5

I had this in a spring-boot webapp, only in the deployment server (was running fine on my local machine). I solve it by adding:

<dependencies>
<!-- … -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<!-- … -->

http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html

Share:
62,854
Arghya Sadhu
Author by

Arghya Sadhu

Engineering Lead of a team working on all things cloud

Updated on November 10, 2020

Comments

  • Arghya Sadhu
    Arghya Sadhu over 3 years

    I am getting below exception when I am trying to run a Spring MVC application using Spring boot...

    ContainerBase: A child container failed during start
    java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:188)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:799)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
        ... 6 more
    Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)Ljavax/servlet/ServletRegistration$Dynamic;
        at org.springframework.boot.context.embedded.ServletRegistrationBean.onStartup(ServletRegistrationBean.java:166)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext$1.onStartup(EmbeddedWebApplicationContext.java:214)
        at org.springframework.boot.context.embedded.tomcat.ServletContextInitializerLifecycleListener.lifecycleEvent(ServletContextInitializerLifecycleListener.java:54)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5355)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        ... 6 more
    
  • randominstanceOfLivingThing
    randominstanceOfLivingThing over 9 years
    I had the same issue and for me the servlet 2.3 dependency came from telnetd-x:2.1.1 as part of spring-boot-starter-web artifact-id.
  • kumetix
    kumetix about 9 years
    Thanks! I have the identical problem, only that I have it happen in a jar I'm producing. so, I prefer to exclude javax.servlet once from the dependencies coming with my artifact, instead of manually excluding it from all my other modules which depend on it. Did you by any chance find a way to that?
  • Michal Moravcik
    Michal Moravcik over 8 years
    thanks, it helped to solve my problem. finally I searched for dependency which introduced the 'servlet-api' with gradle dependencies and then I used standard gradle exclude method
  • Grogi
    Grogi over 8 years
    @kumetix There is a hack to do it in Maven: Create your own artifact javax.serlet:servlet-api with version string 0.99-do-not-include. And define this exact version in <dependency-management>
  • whistling_marmot
    whistling_marmot over 8 years
    After hours of trying to run the basic project (github.com/spring-guides/tut-spring-security-and-angular-js‌​/…) from the Spring security and Angular tutorial (spring.io/guides/tutorials/spring-security-and-angular-js), on STS 3.7.2, this was the only solution that worked for me. It ran fine with mvn spring-boot:run, but not through the IDE with tomcat 8.
  • Sergey Shcherbakov
    Sergey Shcherbakov about 8 years
    this is what happened to me as well!
  • ETL
    ETL almost 8 years
    I prefer this answer because it gets you to the bottom of the problem. All the other ones are "me too I had this and I solved it by...". So if you have the same problem due to a different cause, you can't troubleshoot with the other answers. This is the best useful all-around answer.
  • Halil
    Halil over 7 years
    I solved it by excluding javax.servlet dependency from google-cloud dependency
  • kinjelom
    kinjelom about 4 years
    mvn dependency:tree | grep servlet-api