1
1
/*
2
- * Copyright 2012-2018 the original author or authors.
2
+ * Copyright 2012-2019 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package org .springframework .boot .actuate .health ;
18
18
19
19
import java .util .Arrays ;
20
+ import java .util .Collections ;
20
21
import java .util .HashSet ;
21
22
import java .util .Map ;
23
+ import java .util .concurrent .Callable ;
24
+ import java .util .function .Consumer ;
22
25
23
26
import org .junit .Test ;
24
27
import org .junit .runner .RunWith ;
28
+ import reactor .core .publisher .Mono ;
25
29
30
+ import org .springframework .beans .factory .NoSuchBeanDefinitionException ;
26
31
import org .springframework .boot .actuate .endpoint .web .test .WebEndpointRunners ;
32
+ import org .springframework .boot .autoconfigure .condition .ConditionalOnWebApplication ;
33
+ import org .springframework .boot .autoconfigure .condition .ConditionalOnWebApplication .Type ;
27
34
import org .springframework .context .ConfigurableApplicationContext ;
28
35
import org .springframework .context .annotation .Bean ;
29
36
import org .springframework .context .annotation .Configuration ;
@@ -51,23 +58,87 @@ public void whenHealthIsUp200ResponseIsReturned() {
51
58
}
52
59
53
60
@ Test
54
- public void whenHealthIsDown503ResponseIsReturned () {
61
+ public void whenHealthIsDown503ResponseIsReturned () throws Exception {
62
+ withHealthIndicator ("charlie" , () -> Health .down ().build (),
63
+ () -> Mono .just (Health .down ().build ()), () -> {
64
+ client .get ().uri ("/actuator/health" ).exchange ().expectStatus ()
65
+ .isEqualTo (HttpStatus .SERVICE_UNAVAILABLE ).expectBody ()
66
+ .jsonPath ("status" ).isEqualTo ("DOWN" )
67
+ .jsonPath ("details.alpha.status" ).isEqualTo ("UP" )
68
+ .jsonPath ("details.bravo.status" ).isEqualTo ("UP" )
69
+ .jsonPath ("details.charlie.status" ).isEqualTo ("DOWN" );
70
+ return null ;
71
+ });
72
+ }
73
+
74
+ @ Test
75
+ public void whenComponentHealthIsDown503ResponseIsReturned () throws Exception {
76
+ withHealthIndicator ("charlie" , () -> Health .down ().build (),
77
+ () -> Mono .just (Health .down ().build ()), () -> {
78
+ client .get ().uri ("/actuator/health/charlie" ).exchange ().expectStatus ()
79
+ .isEqualTo (HttpStatus .SERVICE_UNAVAILABLE ).expectBody ()
80
+ .jsonPath ("status" ).isEqualTo ("DOWN" );
81
+ return null ;
82
+ });
83
+ }
84
+
85
+ @ Test
86
+ public void whenComponentInstanceHealthIsDown503ResponseIsReturned ()
87
+ throws Exception {
88
+ CompositeHealthIndicator composite = new CompositeHealthIndicator (
89
+ new OrderedHealthAggregator (),
90
+ Collections .singletonMap ("one" , () -> Health .down ().build ()));
91
+ CompositeReactiveHealthIndicator reactiveComposite = new CompositeReactiveHealthIndicator (
92
+ new OrderedHealthAggregator (),
93
+ new DefaultReactiveHealthIndicatorRegistry (Collections .singletonMap ("one" ,
94
+ () -> Mono .just (Health .down ().build ()))));
95
+ withHealthIndicator ("charlie" , composite , reactiveComposite , () -> {
96
+ client .get ().uri ("/actuator/health/charlie/one" ).exchange ().expectStatus ()
97
+ .isEqualTo (HttpStatus .SERVICE_UNAVAILABLE ).expectBody ()
98
+ .jsonPath ("status" ).isEqualTo ("DOWN" );
99
+ return null ;
100
+ });
101
+ }
102
+
103
+ private void withHealthIndicator (String name , HealthIndicator healthIndicator ,
104
+ ReactiveHealthIndicator reactiveHealthIndicator , Callable <Void > action )
105
+ throws Exception {
106
+ Consumer <String > unregister ;
107
+ Consumer <String > reactiveUnregister ;
108
+ try {
109
+ ReactiveHealthIndicatorRegistry registry = context
110
+ .getBean (ReactiveHealthIndicatorRegistry .class );
111
+ registry .register (name , reactiveHealthIndicator );
112
+ reactiveUnregister = registry ::unregister ;
113
+ }
114
+ catch (NoSuchBeanDefinitionException ex ) {
115
+ reactiveUnregister = (indicatorName ) -> {
116
+ };
117
+ // Continue
118
+ }
55
119
HealthIndicatorRegistry registry = context .getBean (HealthIndicatorRegistry .class );
56
- registry .register ("charlie" , () -> Health .down ().build ());
120
+ registry .register (name , healthIndicator );
121
+ unregister = reactiveUnregister .andThen (registry ::unregister );
57
122
try {
58
- client .get ().uri ("/actuator/health" ).exchange ().expectStatus ()
59
- .isEqualTo (HttpStatus .SERVICE_UNAVAILABLE ).expectBody ()
60
- .jsonPath ("status" ).isEqualTo ("DOWN" ).jsonPath ("details.alpha.status" )
61
- .isEqualTo ("UP" ).jsonPath ("details.bravo.status" ).isEqualTo ("UP" )
62
- .jsonPath ("details.charlie.status" ).isEqualTo ("DOWN" );
123
+ action .call ();
63
124
}
64
125
finally {
65
- registry . unregister ("charlie" );
126
+ unregister . accept ("charlie" );
66
127
}
67
128
}
68
129
69
130
@ Test
70
131
public void whenHealthIndicatorIsRemovedResponseIsAltered () {
132
+ Consumer <String > reactiveRegister = null ;
133
+ try {
134
+ ReactiveHealthIndicatorRegistry registry = context
135
+ .getBean (ReactiveHealthIndicatorRegistry .class );
136
+ ReactiveHealthIndicator unregistered = registry .unregister ("bravo" );
137
+ reactiveRegister = (name ) -> registry .register (name , unregistered );
138
+ }
139
+ catch (NoSuchBeanDefinitionException ex ) {
140
+ // Continue
141
+ }
71
142
HealthIndicatorRegistry registry = context .getBean (HealthIndicatorRegistry .class );
72
143
HealthIndicator bravo = registry .unregister ("bravo" );
73
144
try {
@@ -78,6 +149,9 @@ public void whenHealthIndicatorIsRemovedResponseIsAltered() {
78
149
}
79
150
finally {
80
151
registry .register ("bravo" , bravo );
152
+ if (reactiveRegister != null ) {
153
+ reactiveRegister .accept ("bravo" );
154
+ }
81
155
}
82
156
}
83
157
@@ -91,13 +165,24 @@ public HealthIndicatorRegistry healthIndicatorFactory(
91
165
.createHealthIndicatorRegistry (healthIndicators );
92
166
}
93
167
168
+ @ Bean
169
+ @ ConditionalOnWebApplication (type = Type .REACTIVE )
170
+ public ReactiveHealthIndicatorRegistry reactiveHealthIndicatorRegistry (
171
+ Map <String , ReactiveHealthIndicator > reactiveHealthIndicators ,
172
+ Map <String , HealthIndicator > healthIndicators ) {
173
+ return new ReactiveHealthIndicatorRegistryFactory ()
174
+ .createReactiveHealthIndicatorRegistry (reactiveHealthIndicators ,
175
+ healthIndicators );
176
+ }
177
+
94
178
@ Bean
95
179
public HealthEndpoint healthEndpoint (HealthIndicatorRegistry registry ) {
96
180
return new HealthEndpoint (new CompositeHealthIndicator (
97
181
new OrderedHealthAggregator (), registry ));
98
182
}
99
183
100
184
@ Bean
185
+ @ ConditionalOnWebApplication (type = Type .SERVLET )
101
186
public HealthEndpointWebExtension healthWebEndpointExtension (
102
187
HealthEndpoint healthEndpoint ) {
103
188
return new HealthEndpointWebExtension (healthEndpoint ,
@@ -106,6 +191,18 @@ public HealthEndpointWebExtension healthWebEndpointExtension(
106
191
new HashSet <>(Arrays .asList ("ACTUATOR" ))));
107
192
}
108
193
194
+ @ Bean
195
+ @ ConditionalOnWebApplication (type = Type .REACTIVE )
196
+ public ReactiveHealthEndpointWebExtension reactiveHealthWebEndpointExtension (
197
+ ReactiveHealthIndicatorRegistry registry , HealthEndpoint healthEndpoint ) {
198
+ return new ReactiveHealthEndpointWebExtension (
199
+ new CompositeReactiveHealthIndicator (new OrderedHealthAggregator (),
200
+ registry ),
201
+ new HealthWebEndpointResponseMapper (new HealthStatusHttpMapper (),
202
+ ShowDetails .ALWAYS ,
203
+ new HashSet <>(Arrays .asList ("ACTUATOR" ))));
204
+ }
205
+
109
206
@ Bean
110
207
public HealthIndicator alphaHealthIndicator () {
111
208
return () -> Health .up ().build ();
0 commit comments