Providing type-safe configuration through configuration properties 

While the @Value annotation provides dynamic configuration, it also has several drawbacks:

  • If we want to use three property values in a service, we would need to autowire them using @Value three times.
  • The @Value annotations and the keys of the messages would be spread across the application. If we want to find the list of the configurable values in an application, we have to search through the application for @Value annotations.

Spring Boot provides a better approach to application configuration through the strongly typed ConfigurationProperties feature. This allows us to do the following:

  • Have all the properties in a predefined bean structure.
  • This bean would act as the centralized store for all application properties.
  • The configuration bean can be autowired wherever application configuration is needed.

An example configuration bean is as follows:

  @Component
@ConfigurationProperties("application")
public class ApplicationConfiguration {

private boolean enableSwitchForService1;
private String service1Url;
private int service1Timeout;

public boolean isEnableSwitchForService1() {
return enableSwitchForService1;
}

public void setEnableSwitchForService1 (boolean enableSwitchForService1) {
this.enableSwitchForService1 = enableSwitchForService1;
}

public String getService1Url() {
return service1Url;
}

public void setService1Url(String service1Url) {
this.service1Url = service1Url;
}

public int getService1Timeout() {
return service1Timeout;
}

public void setService1Timeout(int service1Timeout) {
this.service1Timeout = service1Timeout;
}

}

A couple of important things to note are as follows:

  • @ConfigurationProperties("application"): This is the annotation for an externalized configuration. We can add this annotation to any class to bind to external properties.  application is used as a prefix while binding external configuration to this bean.
  • We are defining multiple configurable values in the bean.
  • Getters and setters are required since binding happens through Java bean's property descriptors.

The following snippet shows how the values for these properties can be defined in application.properties:

    application.enableSwitchForService1=true

application.service1Url=http://abc-dev.service.com/somethingelse

application.service1Timeout=250

A couple of important things to note are as follows:

  • application: The prefix is defined as part of @ConfigurationProperties("application") while defining the configuration bean.
  • Values are defined by appending the prefix to the name of the property.

We can use configuration properties in other beans by autowiring ApplicationConfiguration into the bean:

    @Component
public class SomeOtherDataService {

@Autowired
private ApplicationConfiguration configuration;

public String retrieveSomeData() {

// Logic using the url and getting the data
System.out.println(configuration.getService1Timeout());

System.out.println(configuration.getService1Url());

System.out.println(configuration.isEnableSwitchForService1());

return "data from service";
}
}

A couple of important things to note are as follows:

  • @Autowired private ApplicationConfiguration configuration: ApplicationConfiguration is autowired into SomeOtherDataService.
  • configuration.getService1Timeout(), configuration.getService1Url(), configuration.isEnableSwitchForService1(): These values can be accessed in bean methods using the getter methods on the configuration bean.

By default, any failure in binding externally configured values to the configuration properties bean would result in the failure of the server startup. This prevents problems that arise on account of misconfigured applications running in production.

Let's use the misconfigure service timeout to see what happens:

application.service1Timeout=SOME_MISCONFIGURATION

The application will fail to start up, generating the following error:

 ***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target com.mastering.spring.springboot.configuration.ApplicationConfiguration@79d3473e failed:

Property: application.service1Timeout
Value: SOME_MISCONFIGURATION
Reason: Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'service1Timeout'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [int]

Action:
Update your application's configuration
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset