spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.23k stars 40.7k forks source link

Allow `org.testcontainers.containers.DockerComposeContainer` as a source for `ContainerConnectionDetailsFactory` #43174

Open reda-alaoui opened 3 hours ago

reda-alaoui commented 3 hours ago

I'd like to define a new ConnectionDetails type for https://github.com/eclipse/kapua . Eclipse Kapua can only be run via Docker compose. To achieve that, I run it successfully via org.testcontainers.containers.DockerComposeContainer.

I added a KapuaConnectionDetails:

public interface KapuaConnectionDetails extends ConnectionDetails {

  String baseHttpUrl();
}

I would have expected to be able to plug DockerComposeContainer as source of ContainerConnectionDetailsFactory.

But the current signature of ContainerConnectionDetailsFactory is:

public abstract class ContainerConnectionDetailsFactory<C extends Container<?>, D extends ConnectionDetails>
        implements ConnectionDetailsFactory<ContainerConnectionSource<C>, D> {}

Because of that, C excludes org.testcontainers.containers.DockerComposeContainer.

By looking at ContainerConnectionDetailsFactory, I didn't find a good reason for why C is restricted to Container<?>. ContainerConnectionDetailsFactory and its dependencies do not use Container<?>'s method. The only used method is from Startable, and it is only used after a cast check:

https://github.com/spring-projects/spring-boot/blob/c6619dd306b844ad7f876a9a7abc3661cc343dd1/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java#L190-L192

Could we relax C restriction to allow DockerComposeContainer usage?

reda-alaoui commented 3 hours ago

With the following patch, Spring Boot project still compiles:

Index: spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizer.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizer.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizer.java
--- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizer.java   (revision f77c3bbd6bddfb09041a63470a10974e09ebf424)
+++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizer.java   (date 1731667616310)
@@ -20,8 +20,6 @@
 import java.util.Set;
 import java.util.stream.Collectors;

-import org.testcontainers.containers.Container;
-
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
@@ -91,7 +89,7 @@
     * Relevant details from {@link ContainerConnectionSource} used as a
     * MergedContextConfiguration cache key.
     */
-   private record CacheKey(String connectionName, Set<Class<?>> connectionDetailsTypes, Container<?> container) {
+   private record CacheKey(String connectionName, Set<Class<?>> connectionDetailsTypes, Object container) {

        CacheKey(ContainerConnectionSource<?> source) {
            this(source.getConnectionName(), source.getConnectionDetailsTypes(), source.getContainerSupplier().get());
Index: spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionSource.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionSource.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionSource.java
--- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionSource.java    (revision f77c3bbd6bddfb09041a63470a10974e09ebf424)
+++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionSource.java    (date 1731667535088)
@@ -42,7 +42,7 @@
  * @since 3.1.0
  * @see ContainerConnectionDetailsFactory
  */
-public final class ContainerConnectionSource<C extends Container<?>> implements OriginProvider {
+public final class ContainerConnectionSource<C> implements OriginProvider {

    private static final Log logger = LogFactory.getLog(ContainerConnectionSource.class);

Index: spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java
--- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java    (revision f77c3bbd6bddfb09041a63470a10974e09ebf424)
+++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java    (date 1731667526709)
@@ -53,7 +53,7 @@
  * @author Phillip Webb
  * @since 3.1.0
  */
-public abstract class ContainerConnectionDetailsFactory<C extends Container<?>, D extends ConnectionDetails>
+public abstract class ContainerConnectionDetailsFactory<C, D extends ConnectionDetails>
        implements ConnectionDetailsFactory<ContainerConnectionSource<C>, D> {

    /**