Skip to content

Instantly share code, notes, and snippets.

@dineshbhagat
Created August 11, 2022 13:09
Show Gist options
  • Save dineshbhagat/1b38d1afc6ffce06929b63a1272895ae to your computer and use it in GitHub Desktop.
Save dineshbhagat/1b38d1afc6ffce06929b63a1272895ae to your computer and use it in GitHub Desktop.

Reload application properties dynamically

import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit
import mu.KLogging
import org.apache.commons.configuration2.FileBasedConfiguration
import org.apache.commons.configuration2.PropertiesConfiguration
import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder
import org.apache.commons.configuration2.builder.fluent.Parameters
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler
import org.apache.commons.configuration2.event.Event
import org.apache.commons.configuration2.ex.ConfigurationException
import org.apache.commons.configuration2.reloading.PeriodicReloadingTrigger
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.SpringBootConfiguration
import org.springframework.cloud.context.refresh.ContextRefresher
import org.springframework.context.annotation.Bean

/**
 * @see "https://commons.apache.org/proper/commons-configuration/userguide/howto_reloading.html"
 *
 */
@SpringBootConfiguration
open class ApplicationPropertiesConfig {
    companion object : KLogging()

    @Bean
    open fun propertiesConfiguration(
        @Qualifier("configDataContextRefresher")
        contextRefresher: ContextRefresher,
    ): FileBasedConfiguration? {
        val filePath = "src/main/resources/application.properties"
        val file = File(filePath)
        if (!file.exists()) {
            return null
        }

        val builder =
            ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration::class.java)
                .configure(
                    Parameters().fileBased()
                        .setFile(file)
                        .setListDelimiterHandler(DefaultListDelimiterHandler(','))
                )
        builder.addEventListener(
            Event.ANY
        ) {
            if (builder.reloadingController.checkForReloading(null)) {
                logger.info {
                    "properties updated: ${contextRefresher.refreshEnvironment()}, lastModifiedTime: ${
                        Date("${file.lastModified()}".toLong())
                    }"
                }
                builder.reloadingController.resetReloadingState()
            }
        }

        val trigger = PeriodicReloadingTrigger(
            builder.reloadingController,
            null, 30, TimeUnit.SECONDS
        )
        trigger.start()
        logger.info { "Spring properties auto-reload trigger started ..." }

        try {
            return builder.configuration
            // config contains all properties read from the file
        } catch (cex: ConfigurationException) {
            logger.error { "loading of the configuration file failed" }
        }
        return null
    }

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment