Fix Maven-built native images with Docker Compose dependency

Previously, we tried to prevent spring-boot-docker-compose from
causing problems with AOT and native images by excluding it from
the AOT processing classpath. This allowed AOT processing to
succeed. We cannot apply the same exclusion to the native image
classpath so spring-boot-docker-compose was still included in the
native image. This results in a failure at runtime due to missing
reflection hints.

This commit reverts that changes that excluded
spring-boot-docker-compose from the AOT processing classpath. This
allows AOT processing to generate reflection hints but reintroduces
the failure caused by the connection details bean definitions using
an instance supplier callback. To overcome this problem we disable
DockerComposeLifecycleManager during AOT processing and in a native
image. This ensures that no attempt is made to call docker compose up
and no connection details beans are defined.

Fixes gh-35676
This commit is contained in:
Andy Wilkinson
2023-06-21 11:33:15 +01:00
parent 06604ef5ed
commit 660dbb9afd
6 changed files with 47 additions and 96 deletions

View File

@@ -24,6 +24,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aot.AotDetector;
import org.springframework.boot.SpringApplicationShutdownHandlers;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.docker.compose.core.DockerCompose;
@@ -92,6 +93,10 @@ class DockerComposeLifecycleManager {
}
void start() {
if (Boolean.getBoolean("spring.aot.processing") || AotDetector.useGeneratedArtifacts()) {
logger.trace("Docker Compose support disabled with AOT and native images");
return;
}
if (!this.properties.isEnabled()) {
logger.trace("Docker Compose support not enabled");
return;

View File

@@ -31,6 +31,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.aot.AotDetector;
import org.springframework.boot.SpringApplicationShutdownHandlers;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.docker.compose.core.DockerCompose;
@@ -116,6 +117,30 @@ class DockerComposeLifecycleManagerTests {
then(this.dockerCompose).should(never()).hasDefinedServices();
}
@Test
void startWhenAotProcessingDoesNotStart() {
withSystemProperty("spring.aot.processing", "true", () -> {
EventCapturingListener listener = new EventCapturingListener();
this.eventListeners.add(listener);
setUpRunningServices();
this.lifecycleManager.start();
assertThat(listener.getEvent()).isNull();
then(this.dockerCompose).should(never()).hasDefinedServices();
});
}
@Test
void startWhenUsingAotArtifactsDoesNotStart() {
withSystemProperty(AotDetector.AOT_ENABLED, "true", () -> {
EventCapturingListener listener = new EventCapturingListener();
this.eventListeners.add(listener);
setUpRunningServices();
this.lifecycleManager.start();
assertThat(listener.getEvent()).isNull();
then(this.dockerCompose).should(never()).hasDefinedServices();
});
}
@Test
void startWhenComposeFileNotFoundThrowsException() {
DockerComposeLifecycleManager manager = new DockerComposeLifecycleManager(new File("."),
@@ -362,6 +387,22 @@ class DockerComposeLifecycleManagerTests {
}
}
private void withSystemProperty(String key, String value, Runnable action) {
String previous = System.getProperty(key);
try {
System.setProperty(key, value);
action.run();
}
finally {
if (previous == null) {
System.clearProperty(key);
}
else {
System.setProperty(key, previous);
}
}
}
/**
* Testable {@link SpringApplicationShutdownHandlers}.
*/