I have generic ClientProperties
class used by multiple rest clients to bind the client specific properties with implementation.
@Data
@Validated
public class ClientProperties {
@NotBlank
private String url;
@NotNull
private LoggingProperties logging;
}
Here is an example of application.properties
# Kasittely service
kasittelyservice.url= ...
kasittelyservice.logging.enabled=true
# Some other service
otherservice.url= ...
otherservice.logging.enabled=false
Currently I'm doing this with remote clients
@Service
public class KasittelyServiceClient {
private final RestTemplate restTemplate;
@SuppressWarnings("unused")
public KasittelyServiceClient(RestTemplateBuilder builder, @Qualifier("kasittelyService") ClientProperties properties) {
builder.rootUri(properties.getUrl());
if (properties.getLogging().isEnabled()) {
// TODO: debug logging interceptor
}
restTemplate = builder.build();
}
public VastausDto kasittelePyynto(PyyntoDto pyyntoDto) {
return restTemplate.postForObject("/kasittelePyynto", pyyntoDto, VastausDto.class);
}
@Configuration
public static class KasittelyServiceClientConfiguration {
@Bean
@Qualifier("kasittelyService")
@ConfigurationProperties(prefix = "kasittelyservice")
public ClientProperties properties() {
return new ClientProperties();
}
}
}
However, that is a lot of boilerplate to bind properties for each client.
Ideally, I would like to do something like this, which isn't allowed
public KasittelyServiceClient(RestTemplateBuilder builder, @ConfigurationProperties("kasittelyService") ClientProperties properties) {
builder.rootUri(properties.getUrl());
if (properties.getLogging().isEnabled()) {
// TODO: debug logging interceptor
}
restTemplate = builder.build();
}
How do I reduce boilerplate in this case?
CodePudding user response:
You can create an additional @ConfigurationProperties
class that will contain the properties of all clients, which requires an additional prefix to be defined. For example:
@Data
@Component
@ConfigurationProperties(prefix = "properties")
public class AllClientsProperties {
Map<String, ClientProperties> clients;
public ClientProperties getClientPropertiesByKey(String key) {
return clients.get(key);
}
}
Then, change your application.properties
accordingly.
# Kasittely service
properties.clients.kasittelyservice.url= ...
properties.clients.kasittelyservice.logging.enabled=true
# Some other service
properties.clients.otherservice.url= ...
properties.clients.otherservice.logging.enabled=false
Lastly, add the AllClientsProperties
bean as a dependency to the constructor of the client service, and get the properties of the client by the key which are used to perform the initialization logic.
@Service
public class KasittelyServiceClient {
public static final String PROPERTIES_KEY = "kasittelyservice";
private final RestTemplate restTemplate;
@SuppressWarnings("unused")
public KasittelyServiceClient(RestTemplateBuilder builder, AllClientsProperties allClientsProperties) {
ClientProperties properties = allClientsProperties.getClientPropertiesByKey(PROPERTIES_KEY);
builder.rootUri(properties.getUrl());
if (properties.getLogging().isEnabled()) {
// TODO: debug logging interceptor
}
restTemplate = builder.build();
}
//...
}