16
16
17
17
package org .springframework .test .context .observation ;
18
18
19
- import java .lang .reflect .Method ;
20
-
21
19
import io .micrometer .observation .ObservationRegistry ;
22
20
import io .micrometer .observation .contextpropagation .ObservationThreadLocalAccessor ;
23
21
import org .apache .commons .logging .Log ;
27
25
import org .springframework .core .Conventions ;
28
26
import org .springframework .test .context .TestContext ;
29
27
import org .springframework .test .context .support .AbstractTestExecutionListener ;
30
- import org .springframework .util .ReflectionUtils ;
31
28
32
29
/**
33
30
* {@code TestExecutionListener} which provides support for Micrometer's
@@ -45,11 +42,6 @@ class MicrometerObservationRegistryTestExecutionListener extends AbstractTestExe
45
42
46
43
private static final Log logger = LogFactory .getLog (MicrometerObservationRegistryTestExecutionListener .class );
47
44
48
- private static final String THREAD_LOCAL_ACCESSOR_CLASS_NAME = "io.micrometer.context.ThreadLocalAccessor" ;
49
-
50
- private static final String OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME =
51
- "io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor" ;
52
-
53
45
/**
54
46
* Attribute name for a {@link TestContext} attribute which contains the
55
47
* {@link ObservationRegistry} that was previously stored in the
@@ -62,41 +54,46 @@ class MicrometerObservationRegistryTestExecutionListener extends AbstractTestExe
62
54
private static final String PREVIOUS_OBSERVATION_REGISTRY = Conventions .getQualifiedAttributeName (
63
55
MicrometerObservationRegistryTestExecutionListener .class , "previousObservationRegistry" );
64
56
57
+ static final String DEPENDENCIES_ERROR_MESSAGE = """
58
+ MicrometerObservationRegistryTestExecutionListener requires \
59
+ io.micrometer:micrometer-observation:1.10.8 or higher and \
60
+ io.micrometer:context-propagation:1.0.3 or higher.""" ;
65
61
66
- public MicrometerObservationRegistryTestExecutionListener () {
62
+ static final String THREAD_LOCAL_ACCESSOR_CLASS_NAME = "io.micrometer.context.ThreadLocalAccessor" ;
63
+
64
+ static final String OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME =
65
+ "io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor" ;
66
+
67
+ private static final String ERROR_MESSAGE ;
68
+
69
+ static {
67
70
// Trigger eager resolution of Micrometer Observation types to ensure that
68
71
// this listener can be properly skipped when SpringFactoriesLoader attempts
69
72
// to load it -- for example, if context-propagation and micrometer-observation
70
73
// are not in the classpath or if the version of ObservationThreadLocalAccessor
71
74
// present does not include the getObservationRegistry() method.
72
- ClassLoader classLoader = getClass ().getClassLoader ();
73
- String errorMessage = """
74
- MicrometerObservationRegistryTestExecutionListener requires \
75
- io.micrometer:micrometer-observation:1.10.8 or higher and \
76
- io.micrometer:context-propagation:1.0.3 or higher.""" ;
77
75
76
+ String errorMessage = null ;
77
+ ClassLoader classLoader = MicrometerObservationRegistryTestExecutionListener .class .getClassLoader ();
78
+ String classToCheck = THREAD_LOCAL_ACCESSOR_CLASS_NAME ;
78
79
try {
79
- Class .forName (THREAD_LOCAL_ACCESSOR_CLASS_NAME , false , classLoader );
80
- Class <?> clazz = Class .forName (OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME , false , classLoader );
81
- Method method = ReflectionUtils .findMethod (clazz , "getObservationRegistry" );
82
- if (method == null ) {
83
- // We simulate "class not found" even though it's "method not found", since
84
- // the ClassNotFoundException will be processed in the subsequent catch-block.
85
- throw new ClassNotFoundException (OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME );
86
- }
80
+ Class .forName (classToCheck , false , classLoader );
81
+ classToCheck = OBSERVATION_THREAD_LOCAL_ACCESSOR_CLASS_NAME ;
82
+ Class <?> clazz = Class .forName (classToCheck , false , classLoader );
83
+ clazz .getMethod ("getObservationRegistry" );
87
84
}
88
85
catch (Throwable ex ) {
89
- // Ensure that we throw a NoClassDefFoundError so that the exception will be properly
90
- // handled in TestContextFailureHandler.
91
- // If the original exception was a ClassNotFoundException or NoClassDefFoundError,
92
- // we throw a NoClassDefFoundError with an augmented error message and omit the cause.
93
- if ( ex instanceof ClassNotFoundException || ex instanceof NoClassDefFoundError ) {
94
- throw new NoClassDefFoundError ( ex . getMessage () + ". " + errorMessage );
95
- }
96
- // Otherwise, we throw a NoClassDefFoundError with the cause initialized.
97
- Error error = new NoClassDefFoundError ( errorMessage );
98
- error . initCause ( ex );
99
- throw error ;
86
+ errorMessage = classToCheck + ". " + DEPENDENCIES_ERROR_MESSAGE ;
87
+ }
88
+ ERROR_MESSAGE = errorMessage ;
89
+ }
90
+
91
+
92
+ public MicrometerObservationRegistryTestExecutionListener () {
93
+ // If required dependencies are missing, throw a NoClassDefFoundError so
94
+ // that this listener will be properly skipped in TestContextFailureHandler.
95
+ if ( ERROR_MESSAGE != null ) {
96
+ throw new NoClassDefFoundError ( ERROR_MESSAGE ) ;
100
97
}
101
98
}
102
99
0 commit comments