java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String when deploying to Tomcat in cargo

java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String when deploying to Tomcat in cargo

我在使用 maven-cargo-plugin 在嵌入式 Tomcat 7 上部署 Web 应用程序时遇到问题。我在 webapps pom 中创建了一个新的 maven 配置文件,它通过 maven-cargo-plugin 创建了一个 Tomcat 容器,然后通过 soapui-maven-plugin 执行了一个 soapui 测试用例。

webapp 连接到一些 IBM WebSphere MQ,因此我覆盖了一些容器配置文件:

此外,我将所需的 websphere.mq.*.jar 文件和 j2ee-1.4.jar 从本地 WebsSphere Server 安装复制到 Tomcat 容器 lib 目录,方法是通过以下方式添加它们货物 <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

我已经尝试寻找可能的解决方案,f. e.尝试了此处提供的解决方案:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String;

但我可以排除可能的原因,因为:

确保我的设置符合这三点后,我仍然得到上述错误。

有谁知道还有什么可能导致这种情况?

似乎 Tomcat 试图调用此方法,该方法仅存在于 servlet-api-3.0 或更高版本中。由于我无法确切地弄清楚容器从哪里得到这种错误的依赖关系,所以我使用不同的方法解决了我的问题。

我没有通过 maven-cargo-plugin 创建基本的 Tomcat 并覆盖配置文件,而是复制了一个已经工作的本地配置并通过添加

告诉 cargo 使用此配置
<configuration>
    <type>existing</type>
    <home>C:\path\to\tomcat\home</home>
</configuration>

到插件配置

问题的第一个答案将构建绑定到本地计算机上的具体设置。人们也许能够在构建服务器上复制它,但它会很笨拙且容易出错。我个人更喜欢配置构建,这样它就可以在没有任何外部依赖的情况下工作。当我们需要 运行 数据库迁移或者当我们想测试 RabbitMQ 并且没有可用的嵌入式代理但至少应用程序 运行 是独立的时,我也不得不妥协。

因此,如果我是你,我会更深入地研究并进行配置,以便能够在没有这样的本地文件夹的情况下处理你的用例。由于缺少信息(您的货物配置),我无法为您提供有效的答案。但我会向您指出 org.apache.tomcat.maven.tomcat7-maven-plugin。它对我们非常有效。我在另一个项目中使用了 Cargo,我发现 tomcat7 插件更容易使用。

您可以提供自己的server.xmlRun Tomcat and deploy project with own server.xml

您可以在 <dependencies> 部分指定 (add/override) 依赖项 - 这应该可以解决您的 servlet-api 版本问题。

您可以通过将它们添加为 jar 中的依赖项来添加自定义配置(比如我们放入 lib 文件夹中的一些属性文件,以便将它们放在类路径中)。

这是嵌入 Tomcat up 和 运行ning 的一种非常通用且简单的方法。希望能帮到你。

也许可以给你一些关于 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 版本(以测试它是否适用于操作提供的版本)并且我们已经通过 <port><protocol> 指令直接覆盖了一些 server.xml 配置。