December 04, 2019

Part 10: Microservices (Configuring Spring Boot Application: @Value, @ConfigurationProperties)

Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use properties files, YAML files, environment variables, and command-line arguments to externalize configuration.

Using property file config with Spring Boot

Let's say you have configured below property in Spring Boot's application.properties:
our.greeting=Hello

Now you want to use this property in your application. Let's say we have greetMe() API inside GreetingController, this API returns the message configured in property file. To read the message from the property file, we can use 'value injection'. We can inject the property values directly into our beans by using the @Value annotation. e.g:


Let's say you want to reference one property from another property, e.g in the welcome.message can use the configured properties our.greeting and app.name.

our.greeting=Hello!
app.name=Scrutiny Pvt. Ltd.
welcome.message={our.greeting}, Welcome to {app.name}

Let's say we have a list of values configured in application.properties.
redis.clusters=172.11.11.111, 172.22.22.222, 172.33.33.333

Inside the bean we can write:
@Value("${redis.clusters}")
private List redisClusters;

This will convert the comma separated values from the properties file and convert it into a list of Strings.

This not only works with a list but also with a key-value pairs. We can mention a value in property file, which itself is a key-value pair. e.g
neo4j.properties={url: 'bolt://172.11.11.111', username=: 'neo4j', password: 'admin'}

Inside the bean we can write:
@Value("${#{neo4j.properties}}")
private Map neo4jProperties;

Accessing Command Line Properties

How to use external property sources with Spring Boot?
We have configured 'our.greeting' in our application.properties, let's say we have created our JAR (lets say name of the jar is mygreeting.jar) and now want to change update 'our.greeting' without changing the value in the JAR.

Let's say we have configured the server port in our application.properties and created the JAR(lets say name of the jar is mygreeting.jar).
server.port=8081

Now we want to use the port 8082, while running the JAR without changing the value in properties file. We can do this via command line option arguments.  FYI, the command line properties always take precedence over other property sources.

By default, SpringApplication converts any command line option arguments (e.g the arguments starting with --, such as --server.port=9000) to a property and adds them to the Spring Environment.

We can disable the command line properties to be added to the Environment, by using SpringApplication.setAddCommandLineProperties(false).

To change the port while running the jar we can use below command.
java -jar mygreeting.jar --server.port=9000

We can also create another application.properties and save it in the same folder where our jar is present. Now, when we run the jar, Spring will find another application.properties and use it instead of application.properties, which is present inside the jar.

@ConfigurationProperties in Spring Boot
In Spring Boot, the @ConfigurationProperties annotation allows us to map the resource files such as properties or YAML files to Java Bean object. This annotation is applied to a class or a @Bean method in a @Configuration class to map or validate the external properties or YAML files.

Let's say we have configured below properties in our application.properties file:
kafka.bootstrapServers=172.18.31.184:9092,172.18.31.179:9092
kafka.topic=appNotificationTest
kafka.groupid=appNotificationTest
kafka.retryBackoffMsConfig=100



We use @Configuration so that Spring creates a Spring bean in the application context. @ConfigurationProperties works best with hierarchical properties that all have the same prefix. So we add a prefix of 'kafka'.

The Spring framework uses standard Java bean setters, so we must declare setters for each of the properties.

Please note, if you don't use @Configuration in the POJO class, then you need to add @EnableConfigurationProperties(KafkaConfiguration.class) in the main Spring application class to bind the properties into the POJO.

As, of Spring Boot 2.2, Spring finds and registers @ConfigurationProperties classes via classpath scanning. Therefore, its not required to annotate such classes with @Component (and other meta-annotations like @Configuration) or even use the @EnableConfigurationProperties. The classpath scanner enabled by @SpringBootApplication is going to find the ConfigProperties class, even though if you didn't annotate this class with @Component.

Property Validation
@ConfigurationProperties provides validation of properties using the JSR-303 format. e.g:

@NotBlank //for mandatory fields
private String password;

@Length(max = 4, min = 1)//for the length validation
private String userName;

@Min(1025)
@Max(65536)
private int port;

//regex can be used to validate the fields
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String email;

-K Himaanshu Shuklaa..

No comments:

Post a Comment