I intend to write some HealtCheckContributors
for a Spring Boot application using spring-boot-actuator. Hence, I implemented two of them. they are intended for checking the health of different apps, of course, but have a nearly identical structure, except the configuration properties, …
SonarQube complains about that and I wonder if it is possible to have a single health check class but instantiated as many times as defined in application.properties
.
An example:
application.properties
:
# actuator app1.management.baseUrl=http://localhost:10000 app1.management.name=app1HealthCheckContributor app2.management.basUrl=http://localhost:10001 app2.management.name=app2HealthCheckContributor
HealthCheckContributor
for app1:
@Slf4j @Component("xxx") public class App1HealthCheckContributor extends AbstractHealthIndicator { private final App1Properties app1Properties; public App1HealthCheckContributor(final App1Properties app1Properties) { this.app1Properties = app1Properties; } @Override protected void doHealthCheck(Health.Builder builder) {...} }
…and this code for each HealthCheckContributor
only distinct in its appXProperties.
Isn’t it possible to have some kind of base class like:
@Slf4j @Component() public class MyHealthCheckContributor extends AbstractHealthIndicator { private final MyProperties myProperties; public MyHealthCheckContributor(final MyProperties myProperties) { this.myProperties = myProperties; } @Override protected void doHealthCheck(Health.Builder builder) {...} }
and let Spring Boot take care of instantiating two HealthCheckContributors
(in our case App1HealthCheckContributor
and App2HealthCheckContributor
)?
This would eliminate code duplication.
An example of the properties class file:
@Slf4j @Data @ConfigurationProperties(prefix = "app1.management") public class App1Properties { private String baseUrl; private String ...; }
How can I achieve this and how must an application.properties
file looks like to achieve what I intend to do?
The final question: How to test multiple instance creation of a bean of one class filled with values from application.properties?
Advertisement
Answer
Assuming the code in doHealthCheck
is exactly the same for all apps to be checked you could do the following.
You would start by creating a single health check class:
@Slf4j public class AppHealthCheckContributor extends AbstractHealthIndicator { private final AppProperties appProperties; public App1HealthCheckContributor(final AppProperties appProperties) { this.appProperties = appProperties; } @Override protected void doHealthCheck(Health.Builder builder) {...} }
And the properties model as follows:
@Slf4j @Data public class AppProperties { private String baseUrl; private String name; }
This means that the configuration would be something like the following (in application.yml
):
health-check: apps: - baseUrl: http://localhost:10000 name: app1 - baseUrl: http://localhost:10001 name: app2
Finally, you would need to create a bean for each app and register them in the application context:
@Slf4j @Data @Configuration @ConfigurationProperties(prefix = "health-check") public class AllAppPropertiesConfiguration { private List<AppProperties> apps; @Autowired private GenericApplicationContext applicationContext; @PostConstruct fun init() { for (AppProperties app : apps) { applicationContext.registerBean(app.getName(), AppHealthCheckContributor.class, app); } } }