Search

Dark theme | Light theme

October 6, 2024

Spring Sweets: Using Configuration Properties With DataSize

With @ConfigurationProperties in Spring Boot we can bind configuration properties to Java classes. The class annotated with @ConfigurationProperties can be injected into other classes and used in our code. We can use the type DataSize to configure properties that express a size in bytes. When we set the value of the property we can use a long value. The size is then in bytes as that is the default unit. We can also add a unit to the value. Valid units are B for bytes, KB for kilobytes, MB for megabytes, GB for gigabytes and TB for terabytes.

We can also use the @DataSizeUnit annotation to specify the unit of the property in our class annotated with @ConfigurationProperties. In that case a the value without a unit assigned to the property is already in the specified unit.

In the following example we define a record StorageProperties annotated with @ConfigurationProperties and two properties maxFileSize and cacheSize. The property maxFileSize has no unit assigned to the value so it will be in the default unit of bytes. The property cacheSize has the unit MB assigned so the value will be in megabytes.

package mrhaki;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties(prefix = "storage")
public record StorageProperties(
    DataSize maxFileSize /* Default unit is bytes */,
    @DataSizeUnit(DataUnit.MEGABYTES) DataSize cacheSize /* Explicit unit is megabytes */
) {}

In the following test we test the values of the properties in the class StorageProperties. We set the value of the maxFileSize property to 10MB with an explicit unit and the value of the cacheSize property without an explicit unit. We also test the values of the properties in bytes.

package mrhaki;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
@TestPropertySource(properties = {
    "storage.max-file-size=10MB", // value with explicit unit
    "storage.cache-size=500" // value without explicit unit
})
class StoragePropertiesTest {

    @Autowired
    private StorageProperties storageProperties;

    @Test
    void testMaxFileSize() {
        assertThat(storageProperties.maxFileSize())
            .isNotNull()
            // The DataSize class has useful static methods
            // to get values for a certain unit.
            .isEqualTo(DataSize.ofMegabytes(10));
    }

    @Test
    void testCacheSize() {
        assertThat(storageProperties.cacheSize())
            .isNotNull()
            .isEqualTo(DataSize.of(500, DataUnit.MEGABYTES));
    }

    @Test
    void testValuesInBytes() {
        // We can use the toBytes() method to get the actual bytes.
        assertThat(storageProperties.maxFileSize().toBytes())
            .isEqualTo(10 * 1024 * 1024);
        assertThat(storageProperties.cacheSize().toBytes())
            .isEqualTo(500 * 1024 * 1024);
    }
}

Written with Spring Boot 3.3.4.