我有一个使用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);
}
}
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
答案 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);
}
}