Skip to content

Commit d15078d

Browse files
committed
Polish 'Allow ConnectionDetailsFactories to use context class loader'
Refine the submitted pull-request to remove the configuration property with the assumption that the context classloader will work for all cases. See gh-45014
1 parent cc1e1cc commit d15078d

File tree

6 files changed

+28
-61
lines changed

6 files changed

+28
-61
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/ConnectionDetailsFactories.java

+12-32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
3939
* @author Moritz Halbritter
4040
* @author Andy Wilkinson
4141
* @author Phillip Webb
42+
* @author Pedro Xavier Leite Cavadas
4243
* @since 3.1.0
4344
*/
4445
public class ConnectionDetailsFactories {
@@ -48,25 +49,22 @@ public class ConnectionDetailsFactories {
4849
private final List<Registration<?, ?>> registrations = new ArrayList<>();
4950

5051
/**
51-
* Create a new {@link ConnectionDetailsFactories} instance. This constructor uses the
52-
* class loader of {@link ConnectionDetailsFactory} class to load the factories.
52+
* Create a new {@link ConnectionDetailsFactories} instance.
53+
* @deprecated since 3.5.0 for removal in 4.0.0 in favor of
54+
* {@link #ConnectionDetailsFactories(ClassLoader)}
5355
*/
56+
@Deprecated(since = "3.5.0", forRemoval = true)
5457
public ConnectionDetailsFactories() {
55-
this(false);
58+
this((ClassLoader) null);
5659
}
5760

5861
/**
59-
* Create a new {@link ConnectionDetailsFactories} instance. This constructor takes a
60-
* boolean argument to determine whether the context class loader should be used to
61-
* load the factories. If {@code true} and the context class loader is available it
62-
* will be used otherwise the class loader of {@link ConnectionDetailsFactory} class
63-
* will be used.
64-
* @param useContextClassLoader if {@code true} and the context class loader is
65-
* available it will be used otherwise the class loader of
66-
* {@link ConnectionDetailsFactory} class will be used.
62+
* Create a new {@link ConnectionDetailsFactories} instance.
63+
* @param classLoader the class loader used to load factories
64+
* @since 3.5.0
6765
*/
68-
public ConnectionDetailsFactories(boolean useContextClassLoader) {
69-
this(SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader(useContextClassLoader)));
66+
public ConnectionDetailsFactories(ClassLoader classLoader) {
67+
this(SpringFactoriesLoader.forDefaultResourceLocation(classLoader));
7068
}
7169

7270
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -125,24 +123,6 @@ public <S> Map<Class<?>, ConnectionDetails> getConnectionDetails(S source, boole
125123
return List.copyOf(result);
126124
}
127125

128-
/**
129-
* Return the {@link ClassLoader} to use for loading factories.
130-
* <p>
131-
* The default implementation returns the context class loader of the current thread
132-
* or the class loader of this class if the context class loader is {@code null}.
133-
* @param useContextClassLoader if {@code true} and the context class loader is
134-
* available it will be used otherwise the class loader of
135-
* {@link ConnectionDetailsFactory} class will be used
136-
* @return the class loader to use for loading factories
137-
*/
138-
private static ClassLoader getClassLoader(boolean useContextClassLoader) {
139-
if (!useContextClassLoader) {
140-
return ConnectionDetailsFactory.class.getClassLoader();
141-
}
142-
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
143-
return (classLoader != null) ? classLoader : getClassLoader(false);
144-
}
145-
146126
/**
147127
* A {@link ConnectionDetailsFactory} registration.
148128
*

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/lifecycle/DockerComposeProperties.java

+1-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,11 +46,6 @@ public class DockerComposeProperties {
4646
*/
4747
private boolean enabled = true;
4848

49-
/**
50-
* Whether to try to use the context class loader for connection details factories.
51-
*/
52-
private boolean useContextClassLoader = false;
53-
5449
/**
5550
* Arguments to pass to the Docker Compose command.
5651
*/
@@ -94,18 +89,10 @@ public boolean isEnabled() {
9489
return this.enabled;
9590
}
9691

97-
public boolean isUseContextClassLoader() {
98-
return this.useContextClassLoader;
99-
}
100-
10192
public void setEnabled(boolean enabled) {
10293
this.enabled = enabled;
10394
}
10495

105-
public void setUseContextClassLoader(boolean useContextClassLoader) {
106-
this.useContextClassLoader = useContextClassLoader;
107-
}
108-
10996
public List<String> getArguments() {
11097
return this.arguments;
11198
}

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/DockerComposeServiceConnectionsApplicationListener.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@
2727
import org.springframework.boot.autoconfigure.container.ContainerImageMetadata;
2828
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
2929
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories;
30-
import org.springframework.boot.context.properties.bind.Binder;
3130
import org.springframework.boot.docker.compose.core.RunningService;
32-
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties;
3331
import org.springframework.boot.docker.compose.lifecycle.DockerComposeServicesReadyEvent;
3432
import org.springframework.context.ApplicationContext;
3533
import org.springframework.context.ApplicationListener;
@@ -48,30 +46,32 @@
4846
class DockerComposeServiceConnectionsApplicationListener
4947
implements ApplicationListener<DockerComposeServicesReadyEvent> {
5048

49+
private final ConnectionDetailsFactories factories;
50+
5151
DockerComposeServiceConnectionsApplicationListener() {
52+
this(new ConnectionDetailsFactories(null));
53+
}
5254

55+
DockerComposeServiceConnectionsApplicationListener(ConnectionDetailsFactories factories) {
56+
this.factories = factories;
5357
}
5458

5559
@Override
5660
public void onApplicationEvent(DockerComposeServicesReadyEvent event) {
5761
ApplicationContext applicationContext = event.getSource();
5862
if (applicationContext instanceof BeanDefinitionRegistry registry) {
59-
Binder binder = Binder.get(applicationContext.getEnvironment());
60-
DockerComposeProperties properties = DockerComposeProperties.get(binder);
61-
boolean useContextClassLoader = properties.isUseContextClassLoader();
62-
ConnectionDetailsFactories factories = new ConnectionDetailsFactories(useContextClassLoader);
6363
Environment environment = applicationContext.getEnvironment();
64-
registerConnectionDetails(registry, environment, event.getRunningServices(), factories);
64+
registerConnectionDetails(registry, environment, event.getRunningServices());
6565
}
6666
}
6767

6868
private void registerConnectionDetails(BeanDefinitionRegistry registry, Environment environment,
69-
List<RunningService> runningServices, ConnectionDetailsFactories factories) {
69+
List<RunningService> runningServices) {
7070
for (RunningService runningService : runningServices) {
7171
DockerComposeConnectionSource source = new DockerComposeConnectionSource(runningService, environment);
72-
factories.getConnectionDetails(source, false).forEach((connectionDetailsType, connectionDetails) -> {
72+
this.factories.getConnectionDetails(source, false).forEach((connectionDetailsType, connectionDetails) -> {
7373
register(registry, runningService, connectionDetailsType, connectionDetails);
74-
factories.getConnectionDetails(connectionDetails, false)
74+
this.factories.getConnectionDetails(connectionDetails, false)
7575
.forEach((adaptedType, adaptedDetails) -> register(registry, runningService, adaptedType,
7676
adaptedDetails));
7777
});

spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/redis/CustomRedisContainerConnectionDetailsFactoryTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ class CustomRedisContainerConnectionDetailsFactoryTests {
4242

4343
@Test
4444
void getConnectionDetailsWhenRedisContainerWithCustomName() {
45-
ConnectionDetailsFactories factories = new ConnectionDetailsFactories();
45+
ConnectionDetailsFactories factories = new ConnectionDetailsFactories(null);
4646
MergedAnnotation<ServiceConnection> annotation = MergedAnnotation.of(ServiceConnection.class,
4747
Map.of("value", ""));
4848
ContainerConnectionSource<RedisContainer> source = TestContainerConnectionSource.create("test", null,
@@ -53,7 +53,7 @@ void getConnectionDetailsWhenRedisContainerWithCustomName() {
5353

5454
@Test
5555
void getConnectionDetailsWhenRedisStackContainerWithCustomName() {
56-
ConnectionDetailsFactories factories = new ConnectionDetailsFactories();
56+
ConnectionDetailsFactories factories = new ConnectionDetailsFactories(null);
5757
MergedAnnotation<ServiceConnection> annotation = MergedAnnotation.of(ServiceConnection.class,
5858
Map.of("value", ""));
5959
ContainerConnectionSource<RedisStackContainer> source = TestContainerConnectionSource.create("test", null,

spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionAutoConfigurationRegistrar.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
5757

5858
private void registerBeanDefinitions(ConfigurableListableBeanFactory beanFactory, BeanDefinitionRegistry registry) {
5959
ConnectionDetailsRegistrar registrar = new ConnectionDetailsRegistrar(beanFactory,
60-
new ConnectionDetailsFactories());
60+
new ConnectionDetailsFactories(null));
6161
for (String beanName : beanFactory.getBeanNamesForType(Container.class)) {
6262
BeanDefinition beanDefinition = getBeanDefinition(beanFactory, beanName);
6363
MergedAnnotations annotations = (beanDefinition instanceof TestcontainerBeanDefinition testcontainerBeanDefinition)

spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ServiceConnectionContextCustomizer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class ServiceConnectionContextCustomizer implements ContextCustomizer {
4747
private final ConnectionDetailsFactories connectionDetailsFactories;
4848

4949
ServiceConnectionContextCustomizer(List<ContainerConnectionSource<?>> sources) {
50-
this(sources, new ConnectionDetailsFactories());
50+
this(sources, new ConnectionDetailsFactories(null));
5151
}
5252

5353
ServiceConnectionContextCustomizer(List<ContainerConnectionSource<?>> sources,

0 commit comments

Comments
 (0)