From 25e3291d86f77fcc7a3fbc34f116a0d1c2ab41bd Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 1 May 2023 17:35:42 -0700 Subject: [PATCH] Broaden exceptions that include ServiceConnection name hint See gh-35168 --- .../ConnectionDetailsRegistrar.java | 24 +++++++++++++------ .../ConnectionDetailsRegistrarTests.java | 12 ++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrar.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrar.java index 54ac81550e..90c0580926 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrar.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrar.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.function.BiFunction; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -32,6 +33,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactoryNotFoundException; +import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsNotFoundException; import org.springframework.core.log.LogMessage; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -69,14 +71,22 @@ class ConnectionDetailsRegistrar { connectionDetailsType, connectionDetails)); } catch (ConnectionDetailsFactoryNotFoundException ex) { - if (!StringUtils.hasText(source.getConnectionName())) { - StringBuilder message = new StringBuilder(ex.getMessage()); - message.append((!message.toString().endsWith(".")) ? "." : ""); - message.append(" You may need to add a 'name' to your @ServiceConnection annotation"); - throw new ConnectionDetailsFactoryNotFoundException(message.toString(), ex.getCause()); - } - throw ex; + rethrowConnectionDetails(source, ex, ConnectionDetailsFactoryNotFoundException::new); } + catch (ConnectionDetailsNotFoundException ex) { + rethrowConnectionDetails(source, ex, ConnectionDetailsNotFoundException::new); + } + } + + private void rethrowConnectionDetails(ContainerConnectionSource source, RuntimeException ex, + BiFunction exceptionFactory) { + if (!StringUtils.hasText(source.getConnectionName())) { + StringBuilder message = new StringBuilder(ex.getMessage()); + message.append((!message.toString().endsWith(".")) ? "." : ""); + message.append(" You may need to add a 'name' to your @ServiceConnection annotation"); + throw exceptionFactory.apply(message.toString(), ex.getCause()); + } + throw ex; } @SuppressWarnings("unchecked") diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrarTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrarTests.java index 321bb13cd9..d40ce9664c 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrarTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/ConnectionDetailsRegistrarTests.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactoryNotFoundException; +import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsNotFoundException; import org.springframework.boot.origin.Origin; import org.springframework.core.annotation.MergedAnnotation; @@ -73,6 +74,17 @@ class ConnectionDetailsRegistrarTests { .withMessage("fail. You may need to add a 'name' to your @ServiceConnection annotation"); } + @Test + void registerBeanDefinitionsWhenConnectionDetailsNotFoundExceptionAndNoConnectionNameThrowsExceptionWithBetterMessage() { + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + ConnectionDetailsRegistrar registrar = new ConnectionDetailsRegistrar(beanFactory, this.factories); + given(this.factories.getConnectionDetails(this.source, true)) + .willThrow(new ConnectionDetailsNotFoundException("fail")); + assertThatExceptionOfType(ConnectionDetailsNotFoundException.class) + .isThrownBy(() -> registrar.registerBeanDefinitions(beanFactory, this.source)) + .withMessage("fail. You may need to add a 'name' to your @ServiceConnection annotation"); + } + @Test void registerBeanDefinitionsWhenExistingBeanSkipsRegistration() { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();