Skip to content

Commit

Permalink
Fix Maven-built native images with Docker Compose dependency
Browse files Browse the repository at this point in the history
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
  • Loading branch information
wilkinsona committed Jun 21, 2023
1 parent 06604ef commit 660dbb9
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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;
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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;
Expand Down Expand Up @@ -116,6 +117,30 @@ void startWhenEnabledFalseDoesNotStart() {
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("."),
Expand Down Expand Up @@ -362,6 +387,22 @@ private void setUpRunningServices(boolean started, Map<String, String> labels) {
}
}

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}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,6 @@ void whenAotTestRunsSourcesAndResourcesAreGenerated(MavenBuild mavenBuild) {
});
}

@TestTemplate
void whenAotWithDevelopmentOnlyExclusions(MavenBuild mavenBuild) {
mavenBuild.project("aot-development-only-exclusions").goals("package").execute((project) -> {
Path aotDirectory = project.toPath().resolve("target/spring-aot/main");
assertThat(collectRelativePaths(aotDirectory.resolve("sources")))
.contains(Path.of("org", "test", "SampleApplication__ApplicationContextInitializer.java"));
});
}

List<Path> collectRelativePaths(Path sourceDirectory) {
try (Stream<Path> pathStream = Files.walk(sourceDirectory)) {
return pathStream.filter(Files::isRegularFile)
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ private String[] getAotArguments(String applicationClass) {

private URL[] getClassPath() throws Exception {
File[] directories = new File[] { this.classesDirectory, this.generatedClasses };
return getClassPath(directories, new ExcludeTestScopeArtifactFilter(), DOCKER_COMPOSE_EXCLUDE_FILTER);
return getClassPath(directories, new ExcludeTestScopeArtifactFilter());
}

private RunArguments resolveArguments() {
Expand Down

0 comments on commit 660dbb9

Please sign in to comment.