Kotlin Spring Boot Configuration properties best practices
Tags: spring, kotlin, java, developmentexperience
Published: 2022-07-14 14:59:55

_Jump to [the example](#demo) if you're quite advanced in Spring already_

### What do we have

Working in Spring Boot stack one of the first features that every developer is taking the advantage of is [Configuration Properties](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config)

Which could be configured as:
* class level beans
* method based beans

Basically method level beans are the same as class level but you can create N properties beans from a single class.

The properties itself can be propagated in different ways but the most common is through application properties / yaml files.

What's important about the properties that they can be:
* null
* defaulted

### Naming

Spring follows the next conventions as for the configuration (class with beans) and configuration properties classes:

* `@Configuration` - `*Configuration.kt`
* `@ConfigurationProperties` - `*Properties.kt`

It's good to follow the standards from the ecosystem you use to prevent confusions as:

> Properties class is not a configuration

### Anti-patterns

#### Difference between configuration and properties

* Configuration - is a class that defines beans
* Properties - is a class that defines data structure to describe the application properties, e.g. to map the properties to an object

The next example is **anti-pattern** because spring works differently with these concepts:

```java
@Configuration
@ConfigurationProperties
class MyProperties {
  String value;
}
```

#### Configuration properties bean must be initialised by Spring not manually

The next example is **anti-pattern** because configuration properties is a bean can be initialised much more naturally when it's loosely coupled with it's configuration, for instance it's [a problem](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties.constructor-binding) if you use `@ConstructorBinding`:

```java
@Component
@ConfigurationProperties
class MyProperties {
  String value;
}
```

### Standards, code consistency

The goal of the best practices is to find the golden mean. Where we expect that the data-structure represents in a neat way the mapping between the properties and the class.

* default value should be located as close as possible to the field so developer can immediately see it
* nullability should represent the actual necessity of the property
* it should be simple
* composite children fields are designed in the same way

Having all the requirements we have the next example: 

#### Demo

{% embed https://gist.github.com/artemptushkin/ac63c4f60850fd5cbf808fd9ae2b9e9b %}

Let's say we have this set of properties defined:

```yaml
io.github.artemptushkin.example:
  defaultOverriddenProperty: overridden
  requiredStringProperty: required-value
  notNullListProperty: ["foo", "baz"]
```

it will give us the next *runtime* properties:

```properties
io.github.artemptushkin.example.defaultedStringProperty=default
io.github.artemptushkin.example.defaultOverriddenProperty=overridden
io.github.artemptushkin.example.requiredStringProperty=required-value
io.github.artemptushkin.example.optionalStringProperty=null
io.github.artemptushkin.example.notNullListProperty[0]=foo
io.github.artemptushkin.example.notNullListProperty[1]=baz
```

Key points are:
* `@ConstructorBinding` let's us [use create immutable objects](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties.constructor-binding)
* Kotlin default constructor values let us use to have default values right in place in one single line
* Always initialise collections as empty by default to prevent nullable field

### Summary

It's possible to write clean classes and keep them concise from one project to another and within your company.

I hope this noted helped you.