【问题标题】:How to disable autoconfiguration for undertow如何禁用 undertow 的自动配置
【发布时间】:2019-05-18 04:43:34
【问题描述】:

我有一个使用 spring-boot-starter-web 的普通 spring-boot Web 应用程序,即嵌入式 tomcat。

现在我用于测试的库之一带有 undertow 作为依赖项(因为它本身正在启动一个嵌入式 Web 服务器来模拟外部依赖项),这似乎让 spring-boot 自动配置尝试配置undertow 作为嵌入式 Web 服务器(它似乎由于版本不匹配而中断,而且也不是我想要的 - 我可以使用 tomcat 作为我的服务器)。

这里是our test class

package org.zalando.nakadiproducer.tests;

[... imports skipped ...]

import static io.restassured.RestAssured.given;

@RunWith(SpringRunner.class)
@SpringBootTest(
        // This line looks like that by intention: We want to test that the MockNakadiPublishingClient will be picked up
        // by our starter *even if* it has been defined *after* the application itself. This has been a problem until
        // this commit.
        classes = { Application.class, MockNakadiConfig.class  },
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
//@EnableAutoConfiguration(exclude=EmbeddedWebServerFactoryCustomizerAutoConfiguration.class)
public class ApplicationIT {
    @LocalManagementPort
    private int localManagementPort;

    @ClassRule
    public static final EnvironmentVariables environmentVariables
            = new EnvironmentVariables();

    @BeforeClass
    public static void fakeCredentialsDir() {
        environmentVariables.set("CREDENTIALS_DIR", new File("src/main/test/tokens").getAbsolutePath());
    }

    @Test
    public void shouldSuccessfullyStartAndSnapshotCanBeTriggered() {
        given().baseUri("http://localhost:" + localManagementPort).contentType("application/json")
        .when().post("/actuator/snapshot-event-creation/eventtype")
        .then().statusCode(204);
    }
}

main application class

package org.zalando.nakadiproducer.tests;

[imports skipped]

@EnableAutoConfiguration
@EnableNakadiProducer
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    @Primary
    public DataSource dataSource() throws IOException {
        return embeddedPostgres().getPostgresDatabase();
    }

    @Bean
    public EmbeddedPostgres embeddedPostgres() throws IOException {
        return EmbeddedPostgres.start();
    }

    @Bean
    public SnapshotEventGenerator snapshotEventGenerator() {
        return new SimpleSnapshotEventGenerator("eventtype", (withIdGreaterThan, filter) -> {
            if (withIdGreaterThan == null) {
                return Collections.singletonList(new Snapshot("1", "foo", filter));
            } else if (withIdGreaterThan.equals("1")) {
                return Collections.singletonList(new Snapshot("2", "foo", filter));
            } else {
                return new ArrayList<>();
            }
        });

        // Todo: Test that some events arrive at a local nakadi mock
    }
}

这是错误信息:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'undertowWebServerFactoryCustomizer' defined in class path resource [org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$UndertowWebServerFactoryCustomizerConfiguration.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.autoconfigure.web.embedded.UndertowWebServerFactoryCustomizer] from ClassLoader [sun.misc.Launcher$AppClassLoader@378fd1ac]

上面提到的定义类在spring-boot-autoconfigure 2.0.3.RELEASE中,看起来像这样:

@Configuration
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {

    @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
    public static class TomcatWebServerFactoryCustomizerConfiguration {

 // tomcat, jetty

    /**
     * Nested configuration if Undertow is being used.
     */
    @Configuration
    @ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
    public static class UndertowWebServerFactoryCustomizerConfiguration {

        @Bean
        public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(
                Environment environment, ServerProperties serverProperties) {
            return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
        }
    }
}

如何让 spring-boot 不配置 Undertow?

我在我的测试课上尝试了@EnableAutoConfiguration(exclude=EmbeddedWebServerFactoryCustomizerAutoConfiguration.class)(在@SpringBootTest 旁边),但没有效果。

如果我尝试@EnableAutoConfiguration(exclude=EmbeddedWebServerFactoryCustomizerAutoConfiguration.UndertowWebServerFactoryCustomizerConfiguration.class),我会收到此错误:

Caused by: java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
    - org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$UndertowWebServerFactoryCustomizerConfiguration

【问题讨论】:

  • 能否请您添加正在使用 undertown 的依赖项?
  • 我是nakadi-mock,我正在研究图书馆。我可以更改它,但这意味着更改该库的完整概念,我想避免这种情况。

标签: java spring spring-boot


【解决方案1】:

从项目的依赖项中删除 Undertow 是最安全的方法。 Spring Boot 基于类路径扫描,因此一旦 Undertow 从类路径中消失,它的自动配置将不会被处理。

EmbeddedWebServerFactoryCustomizerAutoConfiguration 的问题在于它不提供属性开关。它纯粹基于 servlet 容器类的存在。要摆脱它,您必须排除整个EmbeddedWebServerFactoryCustomizerAutoConfiguration

@EnableAutoConfiguration(exclude=EmbeddedWebServerFactoryCustomizerAutoConfiguration.class)
public MyTest {

}

在您的测试配置中只定义用于启动 Tomcat 的 bean:

@TestConfiguraton
@EnableConfigurationProperties(ServerProperties.class)
public MyTestConfig {

  @Bean
  public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
    return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
  }

}

【讨论】:

  • 从依赖项中删除它不是一个选项,因为它实际上是使用的(只是不通过 spring-boot,而不是作为主服务器)。我想我尝试排除整个 AutoConfiguration 类,但没有任何效果——可能是因为 @SpringBootTest 包括一个应用程序类?我明天再试一次。
  • 所以在我的测试类中添加@EnableAutoConfiguration(exclude=EmbeddedWebServerFactoryCustomizerAutoConfiguration.class) 似乎没有任何效果,但是在主类中添加排除项是有效的。 (奇怪的是我似乎根本不需要添加tomcat bean,不知道为什么。)
猜你喜欢
  • 2011-02-25
  • 2017-05-12
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
  • 2016-02-12
相关资源
最近更新 更多