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
13600c33
Commit
13600c33
authored
Mar 17, 2021
by
bono007
Committed by
Andy Wilkinson
Apr 10, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Provide health for an AbstractRoutingDataSource's resolved targets
See gh-25708
parent
710a9051
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
57 additions
and
18 deletions
+57
-18
DataSourceHealthContributorAutoConfiguration.java
...re/jdbc/DataSourceHealthContributorAutoConfiguration.java
+37
-14
DataSourceHealthContributorAutoConfigurationTests.java
...bc/DataSourceHealthContributorAutoConfigurationTests.java
+20
-4
No files found.
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfiguration.java
View file @
13600c33
...
...
@@ -17,19 +17,19 @@
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
jdbc
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
javax.sql.DataSource
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator
;
import
org.springframework.boot.actuate.health.AbstractHealthIndicator
;
import
org.springframework.boot.actuate.health.Health.Builder
;
import
org.springframework.boot.actuate.health.CompositeHealthContributor
;
import
org.springframework.boot.actuate.health.HealthContributor
;
import
org.springframework.boot.actuate.health.
HealthIndica
tor
;
import
org.springframework.boot.actuate.health.
NamedContribu
tor
;
import
org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator
;
import
org.springframework.boot.autoconfigure.AutoConfigureAfter
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
...
...
@@ -45,6 +45,7 @@ import org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.jdbc.core.JdbcTemplate
;
import
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
;
import
org.springframework.util.Assert
;
/**
* {@link EnableAutoConfiguration Auto-configuration} for
...
...
@@ -64,8 +65,7 @@ import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
@ConditionalOnEnabledHealthIndicator
(
"db"
)
@AutoConfigureAfter
(
DataSourceAutoConfiguration
.
class
)
@EnableConfigurationProperties
(
DataSourceHealthIndicatorProperties
.
class
)
public
class
DataSourceHealthContributorAutoConfiguration
extends
CompositeHealthContributorConfiguration
<
AbstractHealthIndicator
,
DataSource
>
implements
InitializingBean
{
public
class
DataSourceHealthContributorAutoConfiguration
implements
InitializingBean
{
private
final
Collection
<
DataSourcePoolMetadataProvider
>
metadataProviders
;
...
...
@@ -94,10 +94,18 @@ public class DataSourceHealthContributorAutoConfiguration extends
return
createContributor
(
dataSources
);
}
@Override
protected
AbstractHealthIndicator
createIndicator
(
DataSource
source
)
{
private
HealthContributor
createContributor
(
Map
<
String
,
DataSource
>
beans
)
{
Assert
.
notEmpty
(
beans
,
"Beans must not be empty"
);
if
(
beans
.
size
()
==
1
)
{
return
createIndicator
(
beans
.
values
().
iterator
().
next
());
}
return
CompositeHealthContributor
.
fromMap
(
beans
,
this
::
createIndicator
);
}
private
HealthContributor
createIndicator
(
DataSource
source
)
{
if
(
source
instanceof
AbstractRoutingDataSource
)
{
return
new
RoutingDataSourceHealthIndicator
();
AbstractRoutingDataSource
routingDataSource
=
(
AbstractRoutingDataSource
)
source
;
return
new
RoutingDataSourceHealthIndicator
(
routingDataSource
,
this
::
createIndicator
);
}
return
new
DataSourceHealthIndicator
(
source
,
getValidationQuery
(
source
));
}
...
...
@@ -108,14 +116,29 @@ public class DataSourceHealthContributorAutoConfiguration extends
}
/**
* {@link HealthIndicator} used for {@link AbstractRoutingDataSource} beans where we
* can't actually query for the status.
* {@link CompositeHealthContributor} used for {@link AbstractRoutingDataSource} beans
* where the overall health is composed of a {@link DataSourceHealthIndicator} for
* each routed datasource.
*/
static
class
RoutingDataSourceHealthIndicator
extends
AbstractHealthIndicator
{
static
class
RoutingDataSourceHealthIndicator
implements
CompositeHealthContributor
{
private
CompositeHealthContributor
delegate
;
RoutingDataSourceHealthIndicator
(
AbstractRoutingDataSource
routingDataSource
,
Function
<
DataSource
,
HealthContributor
>
indicatorFunction
)
{
Map
<
String
,
DataSource
>
routedDataSources
=
routingDataSource
.
getResolvedDataSources
().
entrySet
().
stream
()
.
collect
(
Collectors
.
toMap
((
e
)
->
e
.
getKey
().
toString
(),
Map
.
Entry
::
getValue
));
this
.
delegate
=
CompositeHealthContributor
.
fromMap
(
routedDataSources
,
indicatorFunction
);
}
@Override
public
HealthContributor
getContributor
(
String
name
)
{
return
this
.
delegate
.
getContributor
(
name
);
}
@Override
p
rotected
void
doHealthCheck
(
Builder
builder
)
throws
Exception
{
builder
.
unknown
().
withDetail
(
"routing"
,
true
);
p
ublic
Iterator
<
NamedContributor
<
HealthContributor
>>
iterator
()
{
return
this
.
delegate
.
iterator
(
);
}
}
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfigurationTests.java
View file @
13600c33
...
...
@@ -16,6 +16,9 @@
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
jdbc
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.sql.DataSource
;
import
org.junit.jupiter.api.Test
;
...
...
@@ -38,6 +41,7 @@ import org.springframework.context.annotation.Configuration;
import
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
...
...
@@ -93,9 +97,16 @@ class DataSourceHealthContributorAutoConfigurationTests {
}
@Test
void
runWithOnlyRoutingDataSourceShouldIncludeRoutingDataSource
()
{
this
.
contextRunner
.
withUserConfiguration
(
RoutingDataSourceConfig
.
class
)
.
run
((
context
)
->
assertThat
(
context
).
hasSingleBean
(
RoutingDataSourceHealthIndicator
.
class
));
void
runWithOnlyRoutingDataSourceShouldIncludeRoutingDataSourceWithComposedIndicators
()
{
this
.
contextRunner
.
withUserConfiguration
(
RoutingDataSourceConfig
.
class
).
run
((
context
)
->
{
assertThat
(
context
).
hasSingleBean
(
RoutingDataSourceHealthIndicator
.
class
);
RoutingDataSourceHealthIndicator
routingHealthContributor
=
context
.
getBean
(
RoutingDataSourceHealthIndicator
.
class
);
assertThat
(
routingHealthContributor
.
getContributor
(
"one"
)).
isInstanceOf
(
DataSourceHealthIndicator
.
class
);
assertThat
(
routingHealthContributor
.
getContributor
(
"two"
)).
isInstanceOf
(
DataSourceHealthIndicator
.
class
);
assertThat
(
routingHealthContributor
.
iterator
()).
toIterable
().
extracting
(
"name"
)
.
containsExactlyInAnyOrder
(
"one"
,
"two"
);
});
}
@Test
...
...
@@ -143,7 +154,12 @@ class DataSourceHealthContributorAutoConfigurationTests {
@Bean
AbstractRoutingDataSource
routingDataSource
()
{
return
mock
(
AbstractRoutingDataSource
.
class
);
Map
<
Object
,
DataSource
>
dataSources
=
new
HashMap
<>();
dataSources
.
put
(
"one"
,
mock
(
DataSource
.
class
));
dataSources
.
put
(
"two"
,
mock
(
DataSource
.
class
));
AbstractRoutingDataSource
routingDataSource
=
mock
(
AbstractRoutingDataSource
.
class
);
given
(
routingDataSource
.
getResolvedDataSources
()).
willReturn
(
dataSources
);
return
routingDataSource
;
}
}
...
...
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