Spring boot project failing with NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String
I was able to resolve the issue by changing Java Runtime Environment. I was using jdk1.8 which had some javaee.jar
file fetching servlet-api
. When I switched JRE to jdk1.7, it started working.
Getting NoSuchMethodError: javax.servlet.ServletContext.addServlet in Spring Boot while running a Spring MVC application
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!/]
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String when deploying to Tomcat in cargo
The first answer to the question bound the build to a concrete setup on a local machine. One may be able to replicate that on a build server but it will be clumsy and error prone. I personally prefer to configure build so it works without any external dependency. I also had to compromise on that when we needed to run database migration or when we wanted to test RabbitMQ and there was no embedded broker available but at least the app run was self-contained.
Hence, if I were you I would dig deeper and make a configuration that is able to handle your use case without such a local folder. I cannot provide working answer for you since I lack information (your cargo configuration). But I would point you to the org.apache.tomcat.maven.tomcat7-maven-plugin
. It worked very well for us. I used Cargo on another project and I find the tomcat7 plugin easier to use.
You can provide your own server.xml
: Run Tomcat and deploy project with own server.xml
You can specify (add/override) dependencies in the <dependencies>
section - which should solve your servlet-api version problem.
You can add a custom configuration (say some properties files which we put in the lib folder to get them on classpath) by adding them as a dependency in a jar.
It's quite versatile and simple way to get embedded Tomcat up and running. Hope that can help you.
Maybe to give you some primer on the tomcat7 plugin config:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>tomcat-run</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-war-only</goal>
</goals>
<configuration>
<webapps>
<webapp>
<groupId>${project.groupId}</groupId>
<artifactId>project-web</artifactId>
<version>${project.version}</version>
<type>war</type>
<asWebapp>true</asWebapp>
<contextPath>/project-path</contextPath>
</webapp>
</webapps>
<protocol>org.apache.coyote.http11.Http11NioProtocol</protocol>
<port>${app.port}</port>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>tomcat-shutdown</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-test-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<version>${jacoco.version}</version>
<classifier>runtime</classifier>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
To explain the above a bit. We used JaCoCo to collect integration test coverage for Sonar. We needed a specific Tomcat version (to test it works on the version provided by operations) and we have overridden some of the server.xml configuration directly by <port>
and <protocol>
directives.
Related Topics
Explanation of Generic <T Extends Comparable<? Super T>> in Collection.Sort/ Comparable Code
How to Run MySQL In-Memory for Junit Test Cases
Printing Message on Console Without Using Main() Method
Stream Filter of 1 List Based on Another List
Extract Integer Part in String
Count Int Occurrences with Java8
Spring Security's Securitycontextholder: Session or Request Bound
Why Does Java Code with an Inner Class Generates a Third Someclass$1.Class File
How to Determine the Primitive Type of a Primitive Variable
How to Clear Permgen Space Error in Tomcat
Java List Sorting: How to Keep a List Permantly Sorted Automatically Like Treemap
How to Disable 'X-Frame-Options' Response Header in Spring Security
Centering Text in a Jtextarea or Jtextpane - Horizontal Text Alignment
What Does Maven Update Project Do in Eclipse