Получение NoSuchMethodError: javax.servlet.ServletContext.addServlet в Spring Загрузка при запуске приложения Spring MVC
Я получаю ниже исключения, когда пытаюсь запустить приложение Spring MVC с помощью Spring загрузки...
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
Ответы
Ответ 1
Я решил его исключить транзитивную зависимость сервлета-api.
В моем случае это было 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>
Ответ 2
Если вы хотите узнать, откуда загружается класс, попробуйте
java -verbose:class -jar foo.jar | grep javax.servlet.ServletContext
где foo.jar
- это толстый JAR, вырабатываемый Gradle или Maven. Например, класс ServletContext
может получать чтение из более раннего servlet-api
JAR в каталоге расширений JDK вместо зависимостей Maven или Gradle.
Результат команды выглядит примерно так:
$ 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!/]
Ответ 3
gradle.
У меня была аналогичная проблема в моем java-банке, который по какой-то причине привел с собой старую версию javax.servlet.ServletContext, которая позже была загружена моим модулем spring -boot, а не его собственным поставляемым классом, тем самым a NoSuchMethodError
Я исправил его, отредактировав build.gradle моего модуля lib:
configurations {
provided.all*.exclude group: 'javax.servlet'
}
Ответ 4
У меня это было в spring -boot webapp, только на сервере развертывания (отлично работало на моей локальной машине). Я решаю это, добавляя:
<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
Ответ 5
Для всех, кто не смог решить это, исключив servlet-api
, вот альтернатива:
Оказывается, Spring Boot по умолчанию для Tomcat 8. Если вы используете другую версию Tomcat и хотите исправить эту ошибку, просто добавьте свою версию tomcat в свойства pom:
<properties>
<tomcat.version>7.0.63</tomcat.version>
</properties>
Ответ 6
У меня возникла эта проблема при попытке запустить загрузочный сервер spring во время тестов (используя gradle + spock). Я проследил эту проблему в библиотеке wiremock.
Это зафиксировало это:
testCompile('com.github.tomakehurst:wiremock:1.58') {
exclude module: 'servlet-api' // this exclude fixed it
}
FYI
gradle dependencies
показывает (сокращенно):
\--- 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
Древняя (2008) org.mortbay.jetty:servlet-api
jar содержит версию ServletContext
, которая несовместима с версией 1.3.2 загрузки spring (работала нормально, по крайней мере, до 1.2.6).
Ответ 7
Я использовал Gradle и то, что сработало для меня:
configurations {
all*.exclude group: '', module: 'servlet-api'
}
Он обрезает дерево зависимостей желаемым образом.
Ответ 8
Я работал с Hadoop 2.7.2 с помощью Spring -boot, следующие зависимости Hadoop используют javax.servlet, что предотвращает запуск встроенной версии tomcat. Ниже исключений в моем POM исправлена проблема.
<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>
Ответ 9
В соответствии с этим решением:
https://stevewall123.wordpress.com/2015/04/17/spring-boot-application-and-tomcat-error-a-child-container-failed-during-start/
Вы можете изменить версию Tomcat, установив свойство "tomcat.version":
ext['tomcat.version'] = '7.0.63' //my version of Tomcat
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
}
он работает для меня, благодаря автору этой статьи.
Приветствия:)
Ответ 10
Если вы используете STS, и вы добавили библиотеку Groovy в свой проект (Project Properties → Java Build Path → Libraries), убедитесь, что вы выбрали "No, only include groovy -all". Другой вариант "Да, включить groovy -all и bsf.jar..., servlet-2.4.jar" добавляет сервлет-2.4.jar, который конфликтует со встроенными классами tomcat8, что приводит к этой проблеме.
Ответ 11
Я использую Jetty в своем проекте и получил ту же ошибку. Моим быстрым решением было исключить встроенный Tomcat из зависимости от Maven:
<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>
Ответ 12
Я не мог отследить проблематичную ссылку, за исключением того, что знал, что это как-то попадает в мой класс-путь, поэтому вот мои 2 цента для ленивых разработчиков, использующих eclipse:
Прокрутите список зависимостей maven в дереве проектов (обычно в разделе Ресурсы Java → Библиотеки → Зависимости Maven), отследите проблемную добавленную банку, которую вы хотите исключить из вашего упакованного JAR, щелкните правой кнопкой мыши по ней → выберите Maven → Исключить артефакт Maven!
Voila - автоматически исключение будет добавлено к вашему pom прямо под зависимостью, которая ссылается на него.
Шахта BTW была 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>
Удачи!
Ответ 13
mvn dependency:tree
не обнаружил servlet-api.jar
в моем пути к классам, но щелкнув правой кнопкой мыши проект (в Eclipse) и перейдя в "Путь сборки/Настройка пути сборки", было показано, что мое рабочее пространство JRE, JDK 1.7.0_51 по умолчанию, jar в каталоге jre/lib/ext
(по крайней мере, в моей установке). Я попробовал и не смог удалить его из своего класса. @Pedro решение для принудительной обработки версии tomcat до 7. Так же была установлена последняя версия Java 7: JDK 1.7.0_79.
Ответ 14
Я также столкнулся с этой ошибкой. У меня есть проект Maven/ Spring MVC/Spring Boot. Я использую IntelliJ как IDE, и всякий раз, когда я добавляю новые зависимости к POM.xml, среда IDE изменяет файл .iml(как и ожидалось), но что странно, что он перемещает следующую строку в начало файла:
<orderEntry type="library" name="Java EE 6-Java EE 6" level="project" />
как только это произойдет, мой проект не будет компилироваться, и я получаю ту же ошибку:
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName() Ljava/lang/String;
просто переместив orderEntry для Java EE назад, ошибка исчезнет, и я могу скомпилировать еще раз.
Ответ 15
Для быстрого решения я удалил servlet-api.jar вручную из библиотеки lib, а затем создаю приложение, и оно работает. Однако, в идеале, как было предложено Kumetix, нужно тщательно изучить до тех пор, пока зависимость, вызывающая ее загрузку в classpath.