java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath () Ljava / lang / String при развертывании на Tomcat в Cargo

У меня возникают проблемы с развертыванием веб-приложения на встроенном Tomcat 7 с помощью maven-cargo-plugin. Я создал новый профиль maven в pom webapps, который создает контейнер Tomcat с помощью maven-cargo-plugin, а затем выполняет тестовый пример soapui с помощью soapui-maven-plugin.

Веб-приложение подключается к некоторым IBM WebSphere MQ, поэтому я перезаписал некоторые файлы конфигурации контейнеров:

  • добавлены MQ в качестве ресурсов в server.xml для поиска JNDI
  • добавил мой пользовательский applicationContext.xml в путь к классам, переопределив web.xml
  • добавлены необходимые ресурсы в context.xml, необходимые для подключения к MQ
  • добавлен путь к каталогу lib локально установленного IBM Websphere MQClient в контейнеры common.loader, чтобы его библиотеки могли использоваться контейнером

Кроме того, я скопировал необходимые файлы websphere.mq. *. Jar и j2ee-1.4.jar из локальной установки WebsSphere Server в каталог lib контейнеров Tomcat, добавив их с помощью тега cargos <file>.

Теперь, когда я запускаю Maven с помощью этой команды (где runITs активирует созданный профиль):

clean verify -U -Dhttps.protocols=TLSv1,SSLv3 -DrunITs -X

Развертывание завершается ошибкой:

INFO] [talledLocalContainer] org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/cargocpc]]
[INFO] [talledLocalContainer]   at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
[INFO] [talledLocalContainer]   at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
[INFO] [talledLocalContainer]   at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
[INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1081)
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1877)
[INFO] [talledLocalContainer]   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
[INFO] [talledLocalContainer]   at java.util.concurrent.FutureTask.run(FutureTask.java:262)
[INFO] [talledLocalContainer]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
[INFO] [talledLocalContainer]   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
[INFO] [talledLocalContainer]   at java.lang.Thread.run(Thread.java:745)
[INFO] [talledLocalContainer] Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getClassLoader()Ljava/lang/ClassLoader;
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.WebappServiceLoader.load(WebappServiceLoader.java:90)
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.ContextConfig.processServletContainerInitializers(ContextConfig.java:1577)
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1281)
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:889)
[INFO] [talledLocalContainer]   at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:386)
[INFO] [talledLocalContainer]   at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
[INFO] [talledLocalContainer]   at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
[INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5412)
[INFO] [talledLocalContainer]   at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
[INFO] [talledLocalContainer]   ... 10 more

Я уже пробовал искать возможные решения и ф. е. попробовал решение, представленное здесь: java.lang.NoSuchMethodError: javax.textservlet.ServletContext. getContextPath () Ljava / lang / String;

но я мог исключить возможные причины, потому что:

  • мой контейнер - Tomcat 7 и поэтому поддерживает Servlet API 2.5
  • web.xml соответствует Servlet API 2.5
  • В WEB-INF/lib или JRE/lib нет файлов j2ee.jar или servlet-api.jar

Убедившись, что моя установка соответствует этим трем пунктам, я все равно получаю указанную выше ошибку.

Кто-нибудь знает, что еще могло вызвать это?


person Fabian Brandes    schedule 08.09.2016    source источник
comment
Я предполагаю, что j2ee-1.4.jar, который вы копируете, содержит класс ServletContext, который несовместим с Tomcat7. Можете ли вы заменить его какой-нибудь другой зависимостью, которая будет содержать только нужные вам классы?   -  person Karel Suta    schedule 14.09.2016
comment
Спасибо, что направили меня в правильное русло. Похоже, Tomcat пытается использовать этот метод, который существует только в servlert-api-3.0 или выше. Я придумал обходной путь   -  person Fabian Brandes    schedule 15.09.2016


Ответы (2)


Первый ответ на вопрос привязывает сборку к конкретной настройке на локальном компьютере. Можно воспроизвести это на сервере сборки, но это будет неуклюже и подвержено ошибкам. Лично я предпочитаю настраивать сборку так, чтобы она работала без какой-либо внешней зависимости. Мне также пришлось пойти на компромисс, когда нам нужно было запустить миграцию базы данных или когда мы хотели протестировать RabbitMQ, и не было встроенного брокера, но, по крайней мере, запуск приложения был автономным.

Следовательно, на вашем месте я бы копнул глубже и создал конфигурацию, которая способна обрабатывать ваш вариант использования без такой локальной папки. Я не могу дать вам рабочий ответ, так как мне не хватает информации (конфигурации вашего груза). Но я хотел бы указать вам на org.apache.tomcat.maven.tomcat7-maven-plugin. У нас это сработало очень хорошо. Я использовал Cargo в другом проекте и считаю, что плагин tomcat7 проще в использовании.

Вы можете предоставить свой собственный server.xml: Запустить Tomcat и развернуть проект с собственным server.xml

Вы можете указать (добавить / переопределить) зависимости в разделе <dependencies>, что должно решить вашу проблему с версией сервлета-api.

Вы можете добавить настраиваемую конфигурацию (скажем, некоторые файлы свойств, которые мы помещаем в папку lib, чтобы получить их в пути к классам), добавляя их как зависимость в jar.

Это довольно универсальный и простой способ запустить и запустить встроенный Tomcat. Надеюсь, это поможет вам.

Возможно, чтобы дать вам некоторое представление о конфигурации плагина tomcat7:

<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>

Немного поясню сказанное. Мы использовали JaCoCo для сбора интеграционных тестов для Sonar. Нам нужна была конкретная версия Tomcat (чтобы протестировать ее работу с версией, предоставляемой операциями), и мы переопределили часть конфигурации server.xml непосредственно директивами <port> и <protocol>.

person Ondrej Burkert    schedule 16.09.2016

Похоже, Tomcat пытается вызвать этот метод, который существует только в servlet-api-3.0 или новее. Поскольку я не мог точно понять, откуда контейнер получает эту неправильную зависимость, я решил свою проблему, используя другой подход.

Вместо того, чтобы создавать базовый Tomcat через maven-cargo-plugin и переопределить файлы конфигурации, я скопировал уже работающую локальную конфигурацию и сказал Cargo использовать эту конфигурацию, добавив

<configuration>
    <type>existing</type>
    <home>C:\path\to\tomcat\home</home>
</configuration>

к конфигурации плагина

person Fabian Brandes    schedule 15.09.2016