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

16

40

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
Cagle answered 6/6, 2014 at 11:16 Comment(6)
Can You post code snippet please ?Hackamore
What dependencies are you using?Betrothal
Check your servlet version that web server support, and servlet version that you implement in your application(it can be found in web.xml). The method addServlet() is supported only in servlet 3.0.Uncovered
Looks like you have an older version of tomcat or of the servlet API on the classpath. Use one of the available tools to look at your classpath (mvn dependency:tree, gradle dependencies, etc.).Botanist
Yeah I can see servlet Api 2.5 in my classpath but I did not mention any such dependency in my pom..So how come this is coming in my classpath any what to do to make sure that servlet api 3.0 is used in my projectCagle
@Dave Syer.....I have now javax.servlet-api-3.1.0.jar in my classpath..but still I get the above exceptionCagle
E
31

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!/]
Empressement answered 19/2, 2015 at 18:41 Comment(2)
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.Digger
mvn dependency:tree | grep servlet-apiGodolphin
B
28

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>
Bowls answered 7/10, 2014 at 9:12 Comment(4)
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.Effeminate
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?Congeneric
@Congeneric 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>Fortepiano
I solved it by excluding javax.servlet dependency from google-cloud dependencyIng
C
23

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'
}
Congeneric answered 12/4, 2015 at 12:22 Comment(0)
T
9

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> 
Tedric answered 19/8, 2015 at 17:33 Comment(1)
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.Counterfactual
F
8

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

Flux answered 28/5, 2015 at 9:17 Comment(0)
I
7

I had this problem when trying to start my spring boot server during tests (using gradle + spock). I traced the problem to the wiremock library.

This fixed it:

testCompile('com.github.tomakehurst:wiremock:1.58') {
    exclude module: 'servlet-api' // this exclude fixed it
}

FYI

gradle dependencies

shows (abridged):

\--- com.github.tomakehurst:wiremock:1.58
     +--- org.mortbay.jetty:jetty:6.1.26
          +--- org.mortbay.jetty:jetty-util:6.1.26
          \--- org.mortbay.jetty:servlet-api:2.5-20081211

The ancient (2008) org.mortbay.jetty:servlet-api jar contains a version of ServletContext that is incompatible with version 1.3.2 of spring boot (worked OK at least up to 1.2.6).

Inkberry answered 23/2, 2016 at 1:1 Comment(0)
G
6

I was using Gradle and what worked for me:

configurations {
    all*.exclude group: '', module: 'servlet-api'
}

It trimmed dependency tree in desired way.

Givens answered 16/4, 2015 at 13:11 Comment(1)
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 methodTreharne
A
6

I was running with Hadoop 2.7.2 using Spring-boot, the following Hadoop dependencies uses javax.servlet which prevented the embedded tomcat version to start. Below exclusions in my POM fixed the issue.

                                    <dependency>
                                    <groupId>org.apache.hadoop</groupId>
                                    <artifactId>hadoop-hdfs</artifactId>
                                    <version>2.7.2</version>
                                    <exclusions>
                                        <exclusion>
                                            <artifactId>servlet-api</artifactId>
                                            <groupId>javax.servlet</groupId>
                                        </exclusion>
                                    </exclusions>
                                </dependency>
                                <dependency>
                                    <groupId>org.springframework.data</groupId>
                                    <artifactId>spring-data-hadoop-boot</artifactId>
                                    <version>2.3.0.RELEASE-hadoop26</version>
                                    <exclusions>
                                        <exclusion>
                                            <artifactId>servlet-api</artifactId>
                                            <groupId>javax.servlet</groupId>
                                        </exclusion>
                                    </exclusions>
                                </dependency>

                                <dependency>
                                    <groupId>org.apache.hadoop</groupId>
                                    <artifactId>hadoop-common</artifactId>
                                    <version>2.7.2</version>
                                    <exclusions>
                                        <exclusion>
                                            <artifactId>slf4j-log4j12</artifactId>
                                            <groupId>org.slf4j</groupId>
                                        </exclusion>
                                        <exclusion>
                                            <artifactId>servlet-api</artifactId>
                                            <groupId>javax.servlet</groupId>
                                        </exclusion>
                                    </exclusions>
                                </dependency>
Archery answered 9/7, 2016 at 8:18 Comment(0)
O
4

According to this solution: https://stevewall123.wordpress.com/2015/04/17/spring-boot-application-and-tomcat-error-a-child-container-failed-during-start/

You can change the Tomcat version by setting the "tomcat.version" property:

ext['tomcat.version'] = '7.0.63' //my version of Tomcat

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
}

it works for me, thanks to the author of that article.

Cheers :)

Offertory answered 8/5, 2016 at 10:17 Comment(0)
G
4

I couldn't track down the problematic reference except for knowing it is somehow getting into my class-path so here is my 2 cents for lazy developers using eclipse:

Scroll down the list of maven dependencies under your project tree (usually under Java Resources -> Libraries -> Maven Dependencies), track the problematic added jar you wish to exclude from your packaged JAR, right click on it -> select Maven -> Exclude Maven Artifact ! Voila - automatically an exclusion will be added to your pom right under the dependency that refers it.

Mine BTW was jcifs...

        <dependency>
        <groupId>org.codelibs</groupId>
        <artifactId>jcifs</artifactId>
        <version>1.3.18.2</version>
        <exclusions>
            <exclusion>
                <artifactId>servlet-api</artifactId>
                <groupId>javax.servlet</groupId>
            </exclusion>
        </exclusions>
    </dependency>

Good luck!

Gabriellegabrielli answered 10/11, 2016 at 7:37 Comment(0)
D
3

If you are using STS and you have added the Groovy library to your project (Project Properties -> Java Build Path -> Libraries), then make sure that you select the "No, only include groovy-all" option. The other option of "Yes, include groovy-all and bsf.jar ..., servlet-2.4.jar" adds servlet-2.4.jar which conflicts with the embedded tomcat8 classes resulting in this problem.

Draught answered 24/3, 2016 at 7:32 Comment(1)
this is what happened to me as well!Precipitin
H
3

I am using Jetty in my project and got the same error. My quick solution was to exclude embedded Tomcat from the Maven dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-ws</artifactId>
    <version>1.2.0.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
Harvestman answered 20/4, 2016 at 14:54 Comment(0)
C
2

mvn dependency:tree did not reveal the servlet-api.jar on my classpath, but right-clicking the project (in Eclipse) and going to Build Path / Configure Build Path showed that my default workspace JRE, JDK 1.7.0_51, had that jar in its jre/lib/ext directory (at least in my installation). I tried and failed to remove it from my classpath. @Pedro's solution of forcing the tomcat version to 7 worked. So did installing the latest version of Java 7: JDK 1.7.0_79.

Counterfactual answered 3/1, 2016 at 16:6 Comment(0)
D
1

I also faced this error. I have a Maven/Spring MVC/Spring Boot project. I'm using IntelliJ as the IDE and whenever i add new dependancies to the POM.xml the IDE alters the .iml file (as expected) but what's weird is that it moves the following line to the top of the file:

<orderEntry type="library" name="Java EE 6-Java EE 6" level="project" />

once that happens my project will not compile and I get the same error:

java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String;

by simply moving the orderEntry for Java EE back to the bottom the error goes away and I can compile once more.

Dormant answered 18/4, 2016 at 17:16 Comment(0)
D
0

For quick solution, I have removed the servlet-api.jar manually from the lib and than build the application and it works.Though, ideally as suggested by Kumetix, one should needs to scrutinize till the dependency which causing it to load in classpath.

Delhi answered 20/8, 2015 at 10:34 Comment(0)
A
0

For me this was solution;

https://mkyong.com/java/servlet-api-2-5-jar-jar-not-loaded/

adding the dependency of the servlet-api to pom.xml

Alded answered 15/11, 2022 at 8:9 Comment(3)
Could have been a commentJesusitajet
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewImpost
It was my first answer. I tried to copy the essentials part indeed but I need to study the format. Next time :)Alded

© 2022 - 2024 — McMap. All rights reserved.