maloney
maloney

Reputation: 1653

Load spring config programmatically

I have 3 micro services which all need use a 'common' library. I need to add a new Spring configuration to the common library. The problem is that Microservice A doesn't care about the new code and doesn't want to be forced to add config in order to get the application to run. I need a way of programmatically loading the config only for Microservice B and C.

New config in common library:

@Configuration
public class HttpConnectionConfiguration {

    @Value("${http.connect.timeout}")
    private int httpConnectTimeout;

    @Value("${http.connect.request.timeout}")
    private int httpConnectRequestTimeout;

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        restTemplate.setRequestFactory(getClientHttpRequestFactory());

        return restTemplate;
    }

    private ClientHttpRequestFactory getClientHttpRequestFactory() {
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(httpConnectTimeout)
                .setConnectionRequestTimeout(httpConnectRequestTimeout)
                .build();

        CloseableHttpClient client = HttpClientBuilder
                .create()
                .useSystemProperties()
                .setDefaultRequestConfig(config)
                .build();

        return new HttpComponentsClientHttpRequestFactory(client);
    }
}

Config in Microservice B and C of application.yaml:

http:
  connect:
    timeout: 5000
    request:
      timeout: 5000

Microservice B and C start fine, but A gives this error: Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'http.connect.timeout' in value "${http.connect.timeout}

What is the best way around this problem without providing dummy values in microservice A?

Upvotes: 4

Views: 1201

Answers (2)

rustyx
rustyx

Reputation: 85371

Solution 1: use a configuration hierarchy with an additional @Configuration class that makes a RestTemplate bean, and activate it only for B and C (or when the property is available):

@Configuration
@ConditionalOnProperty("http.connect.timeout")
public class HttpConnectionConfiguration {

    // rest of code ...

Solution 2: use defaults. Since the default timeout is -1, use that:

    @Value("${http.connect.timeout:-1}")
    private int httpConnectTimeout;

    @Value("${http.connect.request.timeout:-1}")
    private int httpConnectRequestTimeout;

Upvotes: 1

shazin
shazin

Reputation: 21883

You can specify default values inside @Value using SpEL Expression like below.

@Value("${http.connect.timeout:10}")
private int httpConnectTimeout;

@Value("${http.connect.request.timeout:10}")
private int httpConnectRequestTimeout;

Upvotes: 0

Related Questions