Harmonize NoUniqueBeanDefinitionException message

This commit makes sure that the programmatic exception that is thrown
by the cache abstraction uses the same message structure as a default
message produced by NoUniqueBeanDefinitionException.

Closes gh-33305
This commit is contained in:
Stéphane Nicoll 2024-08-02 16:24:43 +02:00
parent 29dce74fcd
commit 0a2611b22f
4 changed files with 40 additions and 14 deletions

View File

@ -95,7 +95,9 @@ class AspectJEnableCachingIsolatedTests {
} }
catch (NoUniqueBeanDefinitionException ex) { catch (NoUniqueBeanDefinitionException ex) {
assertThat(ex.getMessage()).contains( assertThat(ex.getMessage()).contains(
"no CacheResolver specified and expected a single CacheManager bean, but found 2: [cm1,cm2]"); "no CacheResolver specified and expected single matching CacheManager but found 2: cm1,cm2");
assertThat(ex.getNumberOfBeansFound()).isEqualTo(2);
assertThat(ex.getBeanNamesFound()).containsExactly("cm1", "cm2");
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,6 +29,7 @@ import org.springframework.util.StringUtils;
* multiple matching candidates have been found when only one matching bean was expected. * multiple matching candidates have been found when only one matching bean was expected.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.2.1 * @since 3.2.1
* @see BeanFactory#getBean(Class) * @see BeanFactory#getBean(Class)
*/ */
@ -41,6 +42,19 @@ public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionExcepti
private final Collection<String> beanNamesFound; private final Collection<String> beanNamesFound;
/**
* Create a new {@code NoUniqueBeanDefinitionException}.
* @param type required type of the non-unique bean
* @param beanNamesFound the names of all matching beans (as a Collection)
* @param message detailed message describing the problem
* @since 6.2
*/
public NoUniqueBeanDefinitionException(Class<?> type, Collection<String> beanNamesFound, String message) {
super(type, message);
this.numberOfBeansFound = beanNamesFound.size();
this.beanNamesFound = new ArrayList<>(beanNamesFound);
}
/** /**
* Create a new {@code NoUniqueBeanDefinitionException}. * Create a new {@code NoUniqueBeanDefinitionException}.
* @param type required type of the non-unique bean * @param type required type of the non-unique bean
@ -59,10 +73,8 @@ public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionExcepti
* @param beanNamesFound the names of all matching beans (as a Collection) * @param beanNamesFound the names of all matching beans (as a Collection)
*/ */
public NoUniqueBeanDefinitionException(Class<?> type, Collection<String> beanNamesFound) { public NoUniqueBeanDefinitionException(Class<?> type, Collection<String> beanNamesFound) {
super(type, "expected single matching bean but found " + beanNamesFound.size() + ": " + this(type, beanNamesFound, "expected single matching bean but found " + beanNamesFound.size() + ": " +
StringUtils.collectionToCommaDelimitedString(beanNamesFound)); StringUtils.collectionToCommaDelimitedString(beanNamesFound));
this.numberOfBeansFound = beanNamesFound.size();
this.beanNamesFound = new ArrayList<>(beanNamesFound);
} }
/** /**

View File

@ -270,13 +270,22 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
setCacheManager(this.beanFactory.getBean(CacheManager.class)); setCacheManager(this.beanFactory.getBean(CacheManager.class));
} }
catch (NoUniqueBeanDefinitionException ex) { catch (NoUniqueBeanDefinitionException ex) {
StringBuilder message = new StringBuilder("no CacheResolver specified and expected a single CacheManager bean, but found "); int numberOfBeansFound = ex.getNumberOfBeansFound();
message.append(ex.getNumberOfBeansFound()); Collection<String> beanNamesFound = ex.getBeanNamesFound();
if (ex.getBeanNamesFound() != null) {
message.append(": [").append(StringUtils.collectionToCommaDelimitedString(ex.getBeanNamesFound())).append("]"); StringBuilder message = new StringBuilder("no CacheResolver specified and expected single matching CacheManager but found ");
message.append(numberOfBeansFound);
if (beanNamesFound != null) {
message.append(": ").append(StringUtils.collectionToCommaDelimitedString(beanNamesFound));
}
String exceptionMessage = message.toString();
if (beanNamesFound != null) {
throw new NoUniqueBeanDefinitionException(CacheManager.class, beanNamesFound, exceptionMessage);
}
else {
throw new NoUniqueBeanDefinitionException(CacheManager.class, numberOfBeansFound, exceptionMessage);
} }
message.append(" - mark one as primary or declare a specific CacheManager to use.");
throw new NoUniqueBeanDefinitionException(CacheManager.class, ex.getNumberOfBeansFound(), message.toString());
} }
catch (NoSuchBeanDefinitionException ex) { catch (NoSuchBeanDefinitionException ex) {
throw new NoSuchBeanDefinitionException(CacheManager.class, "no CacheResolver specified - " throw new NoSuchBeanDefinitionException(CacheManager.class, "no CacheResolver specified - "

View File

@ -92,9 +92,12 @@ class EnableCachingTests extends AbstractCacheAnnotationTests {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(MultiCacheManagerConfig.class); ctx.register(MultiCacheManagerConfig.class);
assertThatThrownBy(ctx::refresh) assertThatThrownBy(ctx::refresh)
.isInstanceOf(NoUniqueBeanDefinitionException.class) .isInstanceOfSatisfying(NoUniqueBeanDefinitionException.class, ex -> {
.hasMessageContaining("no CacheResolver specified and expected a single CacheManager bean, but found 2: [cm1,cm2]") assertThat(ex.getMessage()).contains(
.hasNoCause(); "no CacheResolver specified and expected single matching CacheManager but found 2: cm1,cm2");
assertThat(ex.getNumberOfBeansFound()).isEqualTo(2);
assertThat(ex.getBeanNamesFound()).containsExactly("cm1", "cm2");
}).hasNoCause();
} }
@Test @Test