Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
eb8b77e3
Commit
eb8b77e3
authored
Apr 15, 2016
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve analysis of failures due to NoUniqueBeanDefinitionException
Closes gh-5683
parent
2e81f87f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
120 additions
and
24 deletions
+120
-24
pom.xml
spring-boot-dependencies/pom.xml
+1
-1
NoUniqueBeanDefinitionFailureAnalyzer.java
...stics/analyzer/NoUniqueBeanDefinitionFailureAnalyzer.java
+47
-10
spring.factories
spring-boot/src/main/resources/META-INF/spring.factories
+3
-1
NoUniqueBeanDefinitionFailureAnalyzerTests.java
.../analyzer/NoUniqueBeanDefinitionFailureAnalyzerTests.java
+69
-12
No files found.
spring-boot-dependencies/pom.xml
View file @
eb8b77e3
...
...
@@ -139,7 +139,7 @@
<snakeyaml.version>
1.17
</snakeyaml.version>
<solr.version>
5.5.0
</solr.version>
<spock.version>
1.0-groovy-2.4
</spock.version>
<spring.version>
4.3.0.
RC1
</spring.version>
<spring.version>
4.3.0.
BUILD-SNAPSHOT
</spring.version>
<spring-amqp.version>
1.6.0.M2
</spring-amqp.version>
<spring-cloud-connectors.version>
1.2.2.RELEASE
</spring-cloud-connectors.version>
<spring-batch.version>
3.0.6.RELEASE
</spring-batch.version>
...
...
spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/NoUniqueBeanDefinition
Exception
FailureAnalyzer.java
→
spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/NoUniqueBeanDefinitionFailureAnalyzer.java
View file @
eb8b77e3
...
...
@@ -16,6 +16,7 @@
package
org
.
springframework
.
boot
.
diagnostics
.
analyzer
;
import
org.springframework.beans.BeanInstantiationException
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.BeanFactoryAware
;
...
...
@@ -28,6 +29,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import
org.springframework.boot.diagnostics.AbstractFailureAnalyzer
;
import
org.springframework.boot.diagnostics.FailureAnalysis
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.StringUtils
;
/**
...
...
@@ -36,7 +38,7 @@ import org.springframework.util.StringUtils;
*
* @author Andy Wilkinson
*/
class
NoUniqueBeanDefinition
Exception
FailureAnalyzer
class
NoUniqueBeanDefinitionFailureAnalyzer
extends
AbstractFailureAnalyzer
<
NoUniqueBeanDefinitionException
>
implements
BeanFactoryAware
{
...
...
@@ -51,9 +53,8 @@ class NoUniqueBeanDefinitionExceptionFailureAnalyzer
@Override
protected
FailureAnalysis
analyze
(
Throwable
rootFailure
,
NoUniqueBeanDefinitionException
cause
)
{
UnsatisfiedDependencyException
unsatisfiedDependency
=
findUnsatisfiedDependencyException
(
rootFailure
);
if
(
unsatisfiedDependency
==
null
)
{
String
consumerDescription
=
getConsumerDescription
(
rootFailure
);
if
(
consumerDescription
==
null
)
{
return
null
;
}
String
[]
beanNames
=
extractBeanNames
(
cause
);
...
...
@@ -62,7 +63,7 @@ class NoUniqueBeanDefinitionExceptionFailureAnalyzer
}
StringBuilder
message
=
new
StringBuilder
();
message
.
append
(
String
.
format
(
"%s required a single bean, but %d were found:%n"
,
getConsumerDescription
(
unsatisfiedDependency
)
,
beanNames
.
length
));
consumerDescription
,
beanNames
.
length
));
for
(
String
beanName
:
beanNames
)
{
try
{
BeanDefinition
beanDefinition
=
this
.
beanFactory
...
...
@@ -90,13 +91,37 @@ class NoUniqueBeanDefinitionExceptionFailureAnalyzer
cause
);
}
private
String
getConsumerDescription
(
Throwable
ex
)
{
UnsatisfiedDependencyException
unsatisfiedDependency
=
findUnsatisfiedDependencyException
(
ex
);
if
(
unsatisfiedDependency
!=
null
)
{
return
getConsumerDescription
(
unsatisfiedDependency
);
}
BeanInstantiationException
beanInstantiationException
=
findBeanInstantiationException
(
ex
);
if
(
beanInstantiationException
!=
null
)
{
return
getConsumerDescription
(
beanInstantiationException
);
}
return
null
;
}
private
UnsatisfiedDependencyException
findUnsatisfiedDependencyException
(
Throwable
root
)
{
return
findMostNestedCause
(
root
,
UnsatisfiedDependencyException
.
class
);
}
private
BeanInstantiationException
findBeanInstantiationException
(
Throwable
root
)
{
return
findMostNestedCause
(
root
,
BeanInstantiationException
.
class
);
}
@SuppressWarnings
(
"unchecked"
)
private
<
T
extends
Exception
>
T
findMostNestedCause
(
Throwable
root
,
Class
<
T
>
causeType
)
{
Throwable
candidate
=
root
;
UnsatisfiedDependencyException
mostNestedMatch
=
null
;
T
mostNestedMatch
=
null
;
while
(
candidate
!=
null
)
{
if
(
ca
ndidate
instanceof
UnsatisfiedDependencyException
)
{
mostNestedMatch
=
(
UnsatisfiedDependencyException
)
candidate
;
if
(
ca
useType
.
isAssignableFrom
(
candidate
.
getClass
())
)
{
mostNestedMatch
=
(
T
)
candidate
;
}
candidate
=
candidate
.
getCause
();
}
...
...
@@ -107,7 +132,7 @@ class NoUniqueBeanDefinitionExceptionFailureAnalyzer
InjectionPoint
injectionPoint
=
ex
.
getInjectionPoint
();
if
(
injectionPoint
!=
null
)
{
if
(
injectionPoint
.
getField
()
!=
null
)
{
return
String
.
format
(
"Field
'%s'
in %s"
,
return
String
.
format
(
"Field
%s
in %s"
,
injectionPoint
.
getField
().
getName
(),
injectionPoint
.
getField
().
getDeclaringClass
().
getName
());
}
...
...
@@ -118,7 +143,7 @@ class NoUniqueBeanDefinitionExceptionFailureAnalyzer
injectionPoint
.
getMethodParameter
().
getDeclaringClass
()
.
getName
());
}
return
String
.
format
(
"Parameter %d of method
'%s'
in %s"
,
return
String
.
format
(
"Parameter %d of method
%s
in %s"
,
injectionPoint
.
getMethodParameter
().
getParameterIndex
(),
injectionPoint
.
getMethodParameter
().
getMethod
().
getName
(),
injectionPoint
.
getMethodParameter
().
getDeclaringClass
()
...
...
@@ -128,6 +153,18 @@ class NoUniqueBeanDefinitionExceptionFailureAnalyzer
return
ex
.
getResourceDescription
();
}
private
String
getConsumerDescription
(
BeanInstantiationException
ex
)
{
if
(
ex
.
getConstructingMethod
()
!=
null
)
{
return
String
.
format
(
"Method %s in %s"
,
ex
.
getConstructingMethod
().
getName
(),
ex
.
getConstructingMethod
().
getDeclaringClass
().
getName
());
}
if
(
ex
.
getConstructor
()
!=
null
)
{
return
String
.
format
(
"Constructor in %s"
,
ClassUtils
.
getUserClass
(
ex
.
getConstructor
().
getDeclaringClass
()).
getName
());
}
return
ex
.
getBeanClass
().
getName
();
}
private
String
[]
extractBeanNames
(
NoUniqueBeanDefinitionException
cause
)
{
if
(
cause
.
getMessage
().
indexOf
(
"but found"
)
>
-
1
)
{
return
StringUtils
.
commaDelimitedListToStringArray
(
cause
.
getMessage
()
...
...
spring-boot/src/main/resources/META-INF/spring.factories
View file @
eb8b77e3
...
...
@@ -33,8 +33,10 @@ org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.
BeanCurrentlyInCreationFailureAnalyzer
org.springframework.boot.diagnostics.analyzer.
ValidationExceptionFailureAnalyzer,
# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
...
...
spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/NoUniqueBeanDefinition
Exception
FailureAnalyzerTests.java
→
spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/NoUniqueBeanDefinitionFailureAnalyzerTests.java
View file @
eb8b77e3
...
...
@@ -18,7 +18,8 @@ package org.springframework.boot.diagnostics.analyzer;
import
org.junit.Test
;
import
org.springframework.beans.factory.UnsatisfiedDependencyException
;
import
org.springframework.beans.factory.BeanCreationException
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.diagnostics.FailureAnalysis
;
import
org.springframework.boot.diagnostics.analyzer.nounique.TestBean
;
...
...
@@ -32,21 +33,20 @@ import org.springframework.context.annotation.ImportResource;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Tests for {@link NoUniqueBeanDefinition
Exception
FailureAnalyzer}.
* Tests for {@link NoUniqueBeanDefinitionFailureAnalyzer}.
*
* @author Andy Wilkinson
*/
public
class
NoUniqueBeanDefinition
Exception
FailureAnalyzerTests
{
public
class
NoUniqueBeanDefinitionFailureAnalyzerTests
{
private
final
NoUniqueBeanDefinition
ExceptionFailureAnalyzer
analyzer
=
new
NoUniqueBeanDefinitionExcep
tionFailureAnalyzer
();
private
final
NoUniqueBeanDefinition
FailureAnalyzer
analyzer
=
new
NoUniqueBeanDefini
tionFailureAnalyzer
();
@Test
public
void
failureAnalysisForFieldConsumer
()
{
FailureAnalysis
failureAnalysis
=
analyzeFailure
(
createFailure
(
FieldConsumer
.
class
));
System
.
out
.
println
(
failureAnalysis
.
getDescription
());
assertThat
(
failureAnalysis
.
getDescription
())
.
startsWith
(
"Field
'testBean'
in "
+
FieldConsumer
.
class
.
getName
()
.
startsWith
(
"Field
testBean
in "
+
FieldConsumer
.
class
.
getName
()
+
" required a single bean, but 6 were found:"
);
assertFoundBeans
(
failureAnalysis
);
}
...
...
@@ -55,9 +55,28 @@ public class NoUniqueBeanDefinitionExceptionFailureAnalyzerTests {
public
void
failureAnalysisForMethodConsumer
()
{
FailureAnalysis
failureAnalysis
=
analyzeFailure
(
createFailure
(
MethodConsumer
.
class
));
System
.
out
.
println
(
failureAnalysis
.
getDescription
());
assertThat
(
failureAnalysis
.
getDescription
()).
startsWith
(
"Parameter 0 of method 'consumer' in "
+
MethodConsumer
.
class
.
getName
()
"Parameter 0 of method consumer in "
+
MethodConsumer
.
class
.
getName
()
+
" required a single bean, but 6 were found:"
);
assertFoundBeans
(
failureAnalysis
);
}
@Test
public
void
failureAnalysisForConstructorConsumer
()
{
FailureAnalysis
failureAnalysis
=
analyzeFailure
(
createFailure
(
ConstructorConsumer
.
class
));
assertThat
(
failureAnalysis
.
getDescription
()).
startsWith
(
"Parameter 0 of constructor in "
+
ConstructorConsumer
.
class
.
getName
()
+
" required a single bean, but 6 were found:"
);
assertFoundBeans
(
failureAnalysis
);
}
@Test
public
void
failureAnalysisForObjectProviderMethodConsumer
()
{
FailureAnalysis
failureAnalysis
=
analyzeFailure
(
createFailure
(
ObjectProviderMethodConsumer
.
class
));
assertThat
(
failureAnalysis
.
getDescription
()).
startsWith
(
"Method consumer in "
+
ObjectProviderMethodConsumer
.
class
.
getName
()
+
" required a single bean, but 6 were found:"
);
assertFoundBeans
(
failureAnalysis
);
}
...
...
@@ -66,14 +85,23 @@ public class NoUniqueBeanDefinitionExceptionFailureAnalyzerTests {
public
void
failureAnalysisForXmlConsumer
()
{
FailureAnalysis
failureAnalysis
=
analyzeFailure
(
createFailure
(
XmlConsumer
.
class
));
System
.
out
.
println
(
failureAnalysis
.
getDescription
());
assertThat
(
failureAnalysis
.
getDescription
()).
startsWith
(
"Parameter 0 of constructor in "
+
TestBeanConsumer
.
class
.
getName
()
+
" required a single bean, but 6 were found:"
);
assertFoundBeans
(
failureAnalysis
);
}
private
UnsatisfiedDependencyException
createFailure
(
Class
<?>
consumer
)
{
@Test
public
void
failureAnalysisForObjectProviderConstructorConsumer
()
{
FailureAnalysis
failureAnalysis
=
analyzeFailure
(
createFailure
(
ObjectProviderConstructorConsumer
.
class
));
assertThat
(
failureAnalysis
.
getDescription
()).
startsWith
(
"Constructor in "
+
ObjectProviderConstructorConsumer
.
class
.
getName
()
+
" required a single bean, but 6 were found:"
);
assertFoundBeans
(
failureAnalysis
);
}
private
BeanCreationException
createFailure
(
Class
<?>
consumer
)
{
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
();
context
.
register
(
DuplicateBeansProducer
.
class
,
consumer
);
context
.
setParent
(
new
AnnotationConfigApplicationContext
(
ParentProducer
.
class
));
...
...
@@ -81,7 +109,7 @@ public class NoUniqueBeanDefinitionExceptionFailureAnalyzerTests {
context
.
refresh
();
return
null
;
}
catch
(
UnsatisfiedDependency
Exception
ex
)
{
catch
(
BeanCreation
Exception
ex
)
{
this
.
analyzer
.
setBeanFactory
(
context
.
getBeanFactory
());
return
ex
;
}
...
...
@@ -90,7 +118,7 @@ public class NoUniqueBeanDefinitionExceptionFailureAnalyzerTests {
}
}
private
FailureAnalysis
analyzeFailure
(
UnsatisfiedDependency
Exception
failure
)
{
private
FailureAnalysis
analyzeFailure
(
BeanCreation
Exception
failure
)
{
return
this
.
analyzer
.
analyze
(
failure
);
}
...
...
@@ -144,6 +172,24 @@ public class NoUniqueBeanDefinitionExceptionFailureAnalyzerTests {
}
@Configuration
static
class
ObjectProviderConstructorConsumer
{
ObjectProviderConstructorConsumer
(
ObjectProvider
<
TestBean
>
objectProvider
)
{
objectProvider
.
getIfAvailable
();
}
}
@Configuration
static
class
ConstructorConsumer
{
ConstructorConsumer
(
TestBean
testBean
)
{
}
}
@Configuration
static
class
MethodConsumer
{
...
...
@@ -154,6 +200,17 @@ public class NoUniqueBeanDefinitionExceptionFailureAnalyzerTests {
}
@Configuration
static
class
ObjectProviderMethodConsumer
{
@Bean
String
consumer
(
ObjectProvider
<
TestBean
>
testBeanProvider
)
{
testBeanProvider
.
getIfAvailable
();
return
"foo"
;
}
}
@Configuration
@ImportResource
(
"/org/springframework/boot/diagnostics/analyzer/nounique/consumer.xml"
)
static
class
XmlConsumer
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment