如何为underwow禁用自动配置

时间:2018-12-17 19:10:10

标签: java spring spring-boot

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

现在,我用于测试的一个库附带了undertow作为依赖项(因为它本身正在启动嵌入式Web服务器来模拟外部依赖项),并且这似乎可以通过spring-boot自动配置来尝试配置用作嵌入式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

1 个答案:

答案 0 :(得分:2)

从项目的依赖关系中删除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);
  }

}