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?
I found How To Instantiatiate Multiple Beans Dinamically in Spring-Boot Depending on Configuration-Properties but (to be honest) I barely understand that.
CodePudding user response:
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);
}
}
}