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?
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);
}
}
}