41

I am facing an issue during deployment of a service in Tomcat 8. Getting following error :

Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String; at org.apache.tomcat.websocket.server.WsServerContainer.(WsServerContainer.java:149) at org.apache.tomcat.websocket.server.WsSci.init(WsSci.java:131) at org.apache.tomcat.websocket.server.WsSci.onStartup(WsSci.java:47) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5244) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 10 more

Method getVirtualServerName was introduced in Servlet 3.1 and after extracting MANIFEST.MF from my servlet-api jar I got following details :

Specification-Title: Java API for Servlets 
Specification-Version: 3.1 
Specification-Vendor: Sun Microsystems, Inc. 
Implementation-Title: javax.servlet 

Which says that its having 3.1. So is there any other reason for this error? Please help

Rahman
  • 3,755
  • 3
  • 26
  • 43

10 Answers10

27

Check all your Maven (or equivalent) dependencies and make sure that you - or most likely another dependency - are not pulling in a pre-3.1 version of the javax.servlet / servlet-api that may be taking precedence over what's in your Tomcat 8. If you've manually deployed, make sure you haven't manually copied any servlet-api JARs into Tomcat itself.

See: https://stackoverflow.com/a/26232535/954442

Community
  • 1
  • 1
Andrew Regan
  • 5,087
  • 6
  • 37
  • 73
  • 6
    Locate the offending dependency which is bringing in the servlet-api jar in maven with the command mvn dependency:tree from the command line in the root of your project, search the output for the servlet-api its most likely 2.? version , exclude it from the dependency with the following in your pom. { servlet-api javax.servlet } – user1412523 Aug 21 '17 at 09:48
  • @user1412523 Thanks! This solved it for me. My dependency was `google-oauth-client-jetty` I removed it as I did not need it anyway and it's working again. – A.W. Sep 08 '18 at 12:26
  • my dependency was hadoop-common (2.9.2) – Fabich Jun 04 '19 at 13:16
  • `mvn dependency:tree | grep servlet-api` – kinjelom Mar 30 '20 at 14:37
  • Thanks @user1412523, that was a really useful comment. I could finally get my apache fop-transcoder-allinone 2.4 dependency fixed and can move on now. – Sir Beethoven May 03 '20 at 20:50
  • Here's another way to try to locate where the offending collision arises... run your build and either expand the war or find the folder that this was built in (target/xx in maven maybe) then locate the WEB-INF/lib folder and use this unix script to locate the jar files that contain classes with the name `ServletContext`. You may get false positives, but it'll lead you in the right direction: `find . -name "*.jar" -exec grep -l ServletContext {} \;` – AndrewL Jul 03 '20 at 00:02
22

The method getVirtualServerName has been added in ServletContext in Servlet 3.1. See the java doc's method getVirtualServerName.

This problem has 3 primary causes:

  1. Your servlet version is older than 3.1.

  2. Some other jar has the servlet with a version older than 3.1.

  3. Your tomcat version is older than 8

to solve it, you can try the below way.

I. Check your pom.xml for the code below.

  <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>javax.servlet-api</artifactId>
       <version>3.1.0</version>
    </dependency>

if your pom.xml has the above code, it would still has that problem. you can do the second way.

II. to check your other jar has refer to the javax.servlet-api jar. for example, the org.apache.santuario has refer to the javax.servlet-api jar. the pom.xml:

<dependency>  
    <groupId>org.apache.santuario</groupId>  
    <artifactId>xmlsec</artifactId>  
    <version>1.4.3</version>   
</dependency> 

but when you look at the maven dependencies, it refer to the javax.servlet-api jar whose version is 2.3 older than 3.1.

enter image description here

so you should exclude the 2.3 version. pom.xml:

<!-- exclude servlet-api 2.3 jar-->  
<dependency>  
    <groupId>org.apache.santuario</groupId>  
    <artifactId>xmlsec</artifactId>  
    <version>1.4.3</version>  
    <exclusions>  
        <exclusion>  
            <groupId>javax.servlet</groupId>  
            <artifactId>servlet-api</artifactId>  
        </exclusion>  
    </exclusions>  
</dependency>  

<!-- servlet-api 3.1 version has getVirtualServerName() -->  
<dependency>  
    <groupId>javax.servlet</groupId>  
    <artifactId>javax.servlet-api</artifactId>  
    <version>3.1.0</version>  
</dependency> 

III. spring boot run the default tomcat 7. so define your tomcat version 8 instead of tomcat 7. so add the code your pom.xml:

   <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <tomcat.version>8.5.5</tomcat.version>
    </properties>
Luke Bickell
  • 103
  • 1
  • 3
Python Basketball
  • 2,320
  • 3
  • 24
  • 47
  • It is ok not to exclude transitive dependency, but just include the correct version. Maven takes the one which is closer in graph. – senyor Sep 03 '19 at 16:54
10

I had this error on IntelliJ with maven after updating IntelliJ.

I could run the tests with maven but not from my IDE.

I solved the problem by removing the ./idea and project.iml files and reloading the project.

zlandorf
  • 1,100
  • 11
  • 15
5

If you have used this dependency:

<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client-jetty</artifactId>
    <version>1.23.0</version>
</dependency>

Then please exclude as below:

<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client-jetty</artifactId>
    <version>1.23.0</version>
    <exclusions>
        <exclusion>
            <artifactId>servlet-api</artifactId>
            <groupId>org.mortbay.jetty</groupId>
        </exclusion>
    </exclusions>
</dependency>
yuen26
  • 871
  • 11
  • 12
4

Spring boot will run tomcat 7 per default, you have to override maven build tomcat.version in your pom.xml. See below to run tomcat 8.0.30

<properties>
  <tomcat.version>8.0.30</tomcat.version>
</properties>

Should fix your problem.

MrSimpleMind
  • 7,890
  • 3
  • 40
  • 45
2

Solved On my mac with java 8 was facing issue with downloaded tomcat from site and unzip.

My issue got solved because there was a extra servlet-api.jar file which was getting picked up. It was coming from /Library/Java/Extensions/servlet-api.jar

For finding it in your system you can use sudo find / -name servlet-api.jar

Removed it by backing it up somewhere else.

I was following this for intallation https://gist.github.com/ddanailov-nmdp/c97aba2ca926b9627f6b4f7174083a32

Ankur
  • 788
  • 6
  • 13
1

Assuming this problem appears when you ran the application in Eclipse. Use Dependency Hierarchy view to search for servlet-api in pom.xm

Max Wang
  • 23
  • 6
0

After a huge pain & sifting through all these stackoverflow answers the only thing that ended up working for me was downgrading from tomcat8 to tomcat7. I know this isn't an ideal solution, and perhaps it was just a fresh install of tomcat that solved my problem. If all else fails give that a shot.

user2008914
  • 33
  • 1
  • 9
0

I attach gradle style dependencies code.

dependencies {
    compileOnly("javax.servlet:javax.servlet-api:3.1.0")
seunggabi
  • 1,699
  • 12
  • 12
  • 1
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel May 06 '22 at 16:06
-1

This surely has something to do with the version of javax.servlet and version of Tomcat.

In my case, it went away when I declared javax.servlet dependency in gradle with no version. Like this -

compile('javax.servlet:servlet-api')
Do Will
  • 711
  • 1
  • 9
  • 18