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
38a42a86
Commit
38a42a86
authored
Jul 23, 2019
by
Stephane Nicoll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve NoSuchMethodError message parsing
Closes gh-17544
parent
26ee9150
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
112 additions
and
17 deletions
+112
-17
NoSuchMethodFailureAnalyzer.java
...oot/diagnostics/analyzer/NoSuchMethodFailureAnalyzer.java
+66
-15
NoSuchMethodFailureAnalyzerTests.java
...iagnostics/analyzer/NoSuchMethodFailureAnalyzerTests.java
+46
-2
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/NoSuchMethodFailureAnalyzer.java
View file @
38a42a86
...
...
@@ -37,6 +37,18 @@ class NoSuchMethodFailureAnalyzer extends AbstractFailureAnalyzer<NoSuchMethodEr
@Override
protected
FailureAnalysis
analyze
(
Throwable
rootFailure
,
NoSuchMethodError
cause
)
{
NoSuchMethodDescriptor
descriptor
=
getNoSuchMethodDescriptor
(
cause
.
getMessage
());
if
(
descriptor
==
null
)
{
return
null
;
}
String
description
=
getDescription
(
cause
,
descriptor
);
return
new
FailureAnalysis
(
description
,
"Correct the classpath of your application so that it contains a single, compatible version of "
+
descriptor
.
getClassName
(),
cause
);
}
protected
NoSuchMethodDescriptor
getNoSuchMethodDescriptor
(
String
cause
)
{
String
message
=
cleanMessage
(
cause
);
String
className
=
extractClassName
(
message
);
if
(
className
==
null
)
{
...
...
@@ -50,22 +62,25 @@ class NoSuchMethodFailureAnalyzer extends AbstractFailureAnalyzer<NoSuchMethodEr
if
(
actual
==
null
)
{
return
null
;
}
String
description
=
getDescription
(
cause
,
message
,
className
,
candidates
,
actual
);
return
new
FailureAnalysis
(
description
,
"Correct the classpath of your application so that it contains a single, compatible version of "
+
className
,
cause
);
return
new
NoSuchMethodDescriptor
(
message
,
className
,
candidates
,
actual
);
}
private
String
cleanMessage
(
NoSuchMethodError
error
)
{
int
loadedFromIndex
=
error
.
getMessage
()
.
indexOf
(
" (loaded from"
);
private
String
cleanMessage
(
String
message
)
{
int
loadedFromIndex
=
message
.
indexOf
(
" (loaded from"
);
if
(
loadedFromIndex
==
-
1
)
{
return
error
.
getMessage
()
;
return
message
;
}
return
error
.
getMessage
()
.
substring
(
0
,
loadedFromIndex
);
return
message
.
substring
(
0
,
loadedFromIndex
);
}
private
String
extractClassName
(
String
message
)
{
if
(
message
.
startsWith
(
"'"
)
&&
message
.
endsWith
(
"'"
))
{
int
splitIndex
=
message
.
indexOf
(
' '
);
if
(
splitIndex
==
-
1
)
{
return
null
;
}
message
=
message
.
substring
(
splitIndex
+
1
);
}
int
descriptorIndex
=
message
.
indexOf
(
'('
);
if
(
descriptorIndex
==
-
1
)
{
return
null
;
...
...
@@ -98,8 +113,7 @@ class NoSuchMethodFailureAnalyzer extends AbstractFailureAnalyzer<NoSuchMethodEr
}
}
private
String
getDescription
(
NoSuchMethodError
cause
,
String
message
,
String
className
,
List
<
URL
>
candidates
,
URL
actual
)
{
private
String
getDescription
(
NoSuchMethodError
cause
,
NoSuchMethodDescriptor
descriptor
)
{
StringWriter
description
=
new
StringWriter
();
PrintWriter
writer
=
new
PrintWriter
(
description
);
writer
.
println
(
"An attempt was made to call a method that does not"
...
...
@@ -111,11 +125,12 @@ class NoSuchMethodFailureAnalyzer extends AbstractFailureAnalyzer<NoSuchMethodEr
writer
.
println
(
"The following method did not exist:"
);
writer
.
println
();
writer
.
print
(
" "
);
writer
.
println
(
message
);
writer
.
println
(
descriptor
.
getErrorMessage
()
);
writer
.
println
();
writer
.
println
(
"The method's class, "
+
className
+
", is available from the following locations:"
);
writer
.
println
(
"The method's class, "
+
descriptor
.
getClassName
()
+
", is available from the following locations:"
);
writer
.
println
();
for
(
URL
candidate
:
candidates
)
{
for
(
URL
candidate
:
descriptor
.
getCandidateLocations
()
)
{
writer
.
print
(
" "
);
writer
.
println
(
candidate
);
}
...
...
@@ -123,8 +138,44 @@ class NoSuchMethodFailureAnalyzer extends AbstractFailureAnalyzer<NoSuchMethodEr
writer
.
println
(
"It was loaded from the following location:"
);
writer
.
println
();
writer
.
print
(
" "
);
writer
.
println
(
actual
);
writer
.
println
(
descriptor
.
getActualLocation
()
);
return
description
.
toString
();
}
protected
static
class
NoSuchMethodDescriptor
{
private
final
String
errorMessage
;
private
final
String
className
;
private
final
List
<
URL
>
candidateLocations
;
private
final
URL
actualLocation
;
public
NoSuchMethodDescriptor
(
String
errorMessage
,
String
className
,
List
<
URL
>
candidateLocations
,
URL
actualLocation
)
{
this
.
errorMessage
=
errorMessage
;
this
.
className
=
className
;
this
.
candidateLocations
=
candidateLocations
;
this
.
actualLocation
=
actualLocation
;
}
public
String
getErrorMessage
()
{
return
this
.
errorMessage
;
}
public
String
getClassName
()
{
return
this
.
className
;
}
public
List
<
URL
>
getCandidateLocations
()
{
return
this
.
candidateLocations
;
}
public
URL
getActualLocation
()
{
return
this
.
actualLocation
;
}
}
}
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/NoSuchMethodFailureAnalyzerTests.java
View file @
38a42a86
...
...
@@ -25,6 +25,7 @@ import org.junit.jupiter.api.condition.EnabledOnJre;
import
org.junit.jupiter.api.condition.JRE
;
import
org.springframework.boot.diagnostics.FailureAnalysis
;
import
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer.NoSuchMethodDescriptor
;
import
org.springframework.boot.testsupport.classpath.ClassPathOverrides
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
...
@@ -34,10 +35,53 @@ import static org.mockito.Mockito.mock;
* Tests for {@link NoSuchMethodFailureAnalyzer}.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
@ClassPathOverrides
(
"javax.servlet:servlet-api:2.5"
)
class
NoSuchMethodFailureAnalyzerTests
{
@Test
void
parseJava8ErrorMessage
()
{
NoSuchMethodDescriptor
descriptor
=
new
NoSuchMethodFailureAnalyzer
().
getNoSuchMethodDescriptor
(
"javax.servlet.ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)"
+
"Ljavax/servlet/ServletRegistration$Dynamic;"
);
assertThat
(
descriptor
).
isNotNull
();
assertThat
(
descriptor
.
getErrorMessage
())
.
isEqualTo
(
"javax.servlet.ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)"
+
"Ljavax/servlet/ServletRegistration$Dynamic;"
);
assertThat
(
descriptor
.
getClassName
()).
isEqualTo
(
"javax.servlet.ServletContext"
);
assertThat
(
descriptor
.
getCandidateLocations
()).
isNotEmpty
();
assertThat
(
descriptor
.
getActualLocation
()).
asString
().
contains
(
"servlet-api-2.5.jar"
);
}
@Test
void
parseJava13OpenJ9ErrorMessage
()
{
NoSuchMethodDescriptor
descriptor
=
new
NoSuchMethodFailureAnalyzer
().
getNoSuchMethodDescriptor
(
"javax/servlet/ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)"
+
"Ljavax/servlet/ServletRegistration$Dynamic; (loaded from file..."
);
assertThat
(
descriptor
).
isNotNull
();
assertThat
(
descriptor
.
getErrorMessage
())
.
isEqualTo
(
"javax/servlet/ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)"
+
"Ljavax/servlet/ServletRegistration$Dynamic;"
);
assertThat
(
descriptor
.
getClassName
()).
isEqualTo
(
"javax.servlet.ServletContext"
);
assertThat
(
descriptor
.
getCandidateLocations
()).
isNotEmpty
();
assertThat
(
descriptor
.
getActualLocation
()).
asString
().
contains
(
"servlet-api-2.5.jar"
);
}
@Test
void
parseJava13HotspotErrorMessage
()
{
NoSuchMethodDescriptor
descriptor
=
new
NoSuchMethodFailureAnalyzer
().
getNoSuchMethodDescriptor
(
"'javax.servlet.ServletRegistration$Dynamic javax.servlet.ServletContext.addServlet("
+
"java.lang.String, javax.servlet.Servlet)'"
);
assertThat
(
descriptor
).
isNotNull
();
assertThat
(
descriptor
.
getErrorMessage
())
.
isEqualTo
(
"'javax.servlet.ServletRegistration$Dynamic javax.servlet.ServletContext.addServlet("
+
"java.lang.String, javax.servlet.Servlet)'"
);
assertThat
(
descriptor
.
getClassName
()).
isEqualTo
(
"javax.servlet.ServletContext"
);
assertThat
(
descriptor
.
getCandidateLocations
()).
isNotEmpty
();
assertThat
(
descriptor
.
getActualLocation
()).
asString
().
contains
(
"servlet-api-2.5.jar"
);
}
@Test
@EnabledOnJre
({
JRE
.
JAVA_8
,
JRE
.
JAVA_11
,
JRE
.
JAVA_12
})
void
noSuchMethodErrorIsAnalyzedJava8To12
()
{
...
...
@@ -50,8 +94,8 @@ class NoSuchMethodFailureAnalyzerTests {
@DisabledOnJre
({
JRE
.
JAVA_8
,
JRE
.
JAVA_11
,
JRE
.
JAVA_12
})
void
noSuchMethodErrorIsAnalyzedJava13AndLater
()
{
testNoSuchMethodErrorFailureAnalysis
(
"
javax/servlet/ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)
"
+
"
Ljavax/servlet/ServletRegistration$Dynamic;
"
);
"
'javax.servlet.ServletRegistration$Dynamic javax.servlet.ServletContext.addServlet(
"
+
"
java.lang.String, javax.servlet.Servlet)'
"
);
}
private
void
testNoSuchMethodErrorFailureAnalysis
(
String
expectedMethodRepresentation
)
{
...
...
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