【问题标题】:How to make Spring boot webflux to start on default Netty rather than Jetty while testing如何在测试时使 Spring boot webflux 在默认 Netty 而不是 Jetty 上启动
【发布时间】:2019-11-09 00:11:39
【问题描述】:

我有一个有点相似的 gradle 和 spring webflux 配置,如Why spring webflux is choosing jetty by default and then failing?中所述

但我们的目标是在内存中使用 Amazon dynamo db + spring webflux on netty(而不是 jetty)用于我们的单元测试(我们已经在 netty 上拥有带有 spring webfux 的生产 dynamo db)。我可以使用内存中的 dynamo db 运行单元测试,但是一旦我启用 springboot webflux,它就会开始抱怨:

   Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/servlet/ServletHolder
    at org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory.createJettyServer(JettyReactiveWebServerFactory.java:176) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory.getWebServer(JettyReactiveWebServerFactory.java:106) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext$ServerManager.<init>(ReactiveWebServerApplicationContext.java:202) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext$ServerManager.get(ReactiveWebServerApplicationContext.java:221) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.createWebServer(ReactiveWebServerApplicationContext.java:90) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.onRefresh(ReactiveWebServerApplicationContext.java:79) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    ... 62 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.servlet.ServletHolder

我已经尝试在我的 build.gradle 中进行以下操作:

 configurations {
    // exclude Reactor Jetty /Tomcat 
    compile.exclude  group: 'org.springframework.boot',module: 'spring-boot-starter-jetty'
    testcompile.exclude  group: 'org.springframework.boot',module: 'spring-boot-starter-jetty'
    //compile.exclude group: 'javax.servlet' , module: 'servlet-api' //<--tried servlet jar exclusion also
}

.....
testCompile ('com.amazonaws:DynamoDBLocal:1.11.477')
....//event tried this ( and is probably wrong)
testCompile("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
        exclude  group: 'org.springframework.boot', module: 'spring-boot-starter-jetty' //by both name and group
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'

    }

我检查了依赖图:

\--- com.amazonaws:DynamoDBLocal:1.11.477
    +--- org.antlr:antlr4-runtime:4.7.2
    +--- commons-cli:commons-cli:1.2
    +--- org.apache.commons:commons-lang3:3.8.1
    +--- com.almworks.sqlite4java:libsqlite4java-linux-i386:1.0.392
    |    \--- com.almworks.sqlite4java:sqlite4java:1.0.392
    +--- com.almworks.sqlite4java:libsqlite4java-linux-amd64:1.0.392
    |    \--- com.almworks.sqlite4java:sqlite4java:1.0.392
    +--- com.almworks.sqlite4java:sqlite4java-win32-x64:1.0.392
    |    \--- com.almworks.sqlite4java:sqlite4java:1.0.392
    +--- com.almworks.sqlite4java:sqlite4java-win32-x86:1.0.392
    |    \--- com.almworks.sqlite4java:sqlite4java:1.0.392
    +--- com.almworks.sqlite4java:libsqlite4java-osx:1.0.392
    |    \--- com.almworks.sqlite4java:sqlite4java:1.0.392
    +--- com.amazonaws:aws-java-sdk-core:1.11.477 (*)
    +--- com.amazonaws:aws-java-sdk-dynamodb:1.11.477 (*)
    +--- org.apache.logging.log4j:log4j-api:2.6.2 -> 2.11.2
    +--- org.apache.logging.log4j:log4j-core:2.6.2 -> 2.11.2
    |    \--- org.apache.logging.log4j:log4j-api:2.11.2
      +--- org.eclipse.jetty:jetty-client:8.1.12.v20130726 -> 9.4.18.v20190429
    |    +--- org.eclipse.jetty:jetty-http:9.4.18.v20190429
    |    |    +--- org.eclipse.jetty:jetty-util:9.4.18.v20190429
    |    |    \--- org.eclipse.jetty:jetty-io:9.4.18.v20190429
    |    |         \--- org.eclipse.jetty:jetty-util:9.4.18.v20190429
    |    \--- org.eclipse.jetty:jetty-io:9.4.18.v20190429 (*)
    +--- org.eclipse.jetty:jetty-server:8.1.12.v20130726 -> 9.4.18.v20190429
    |    +--- javax.servlet:javax.servlet-api:3.1.0 -> 4.0.1
    |    +--- org.eclipse.jetty:jetty-http:9.4.18.v20190429 (*)
    |    \--- org.eclipse.jetty:jetty-io:9.4.18.v20190429 (*)
    +--- org.mockito:mockito-core:1.10.19 -> 2.23.4
    |    +--- net.bytebuddy:byte-buddy:1.9.3 -> 1.9.12

所以我需要强制 webflux 将 Netty 作为服务器。我认为它被 dynamodb 依赖或一些 jar 传递性所覆盖。

【问题讨论】:

    标签: unit-testing spring-boot amazon-dynamodb spring-webflux


    【解决方案1】:

    我遇到了同样的问题。问题是DynamoDBLocal 库会传递引用 Jetty。由于 Jetty 和 Netty 在类路径中,Webflux 认为它应该使用 Jetty 而不是 Netty 启动。我可以按照这里的 Spring Boot 文档中的详细说明来解决这个问题:https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html#howto-configure-webserver

    具体这部分:

    作为最后的手段,您还可以声明自己的 WebServerFactory 组件,该组件将覆盖 Spring Boot 提供的组件。

    更具体地说,您可以将其添加到您的测试配置中(如果您想明确告诉一切始终使用 Netty,则可以将其添加到您的整个应用程序配置中):

    @Bean
    public ReactiveWebServerFactory reactiveWebServerFactory() {
        return new NettyReactiveWebServerFactory();
    }
    

    【讨论】:

    • 我在发布问题后忘记回来查看(因为我找到了解决方案)。但是,是的,你是对的。我做了同样的事情 。您需要为您的单元测试配置进行配置。
    【解决方案2】:

    同样的问题。我怀疑某些内部条件迫使 Tomcat 而不是 Netty,但我想不通。

    我结合这三个变化解决了这个问题:

    1. 添加了org.springframework.boot:spring-boot-starter-reactory-nettydependecy
    2. 添加了 NettyReactiveWebServerFactory bean(感谢 Evan Lennick!)
    3. spring.main.web-appplication-type=reactive 添加到application.properties

    我希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      这个问题已经在 Spring Boot 2.2.9 版本中解决了:

      https://github.com/spring-projects/spring-boot/issues/22275

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-22
        • 1970-01-01
        • 2020-11-20
        • 1970-01-01
        • 1970-01-01
        • 2018-07-26
        • 2020-09-29
        • 2019-05-25
        相关资源
        最近更新 更多