I've got a library that has a configuration class (no spring configuration class) defined as a data class. I want a Bean of that configuration which can be configured via application.properties. The problem is that I don't know how to tell Spring to create ConfigurationProperties according to that external data class. I am not the author of the configuration class so I can't annotate the class itself. @ConfigurationProperties in conjunction with @Bean does not work as the properties are immutable. Is this even possible?
Spring Kotlin @ConfigurationProperties for data class defined in dependency
1.2k Views Asked by Ceryni At
2
There are 2 best solutions below
0

If I understand correctly, do you need a way to turn a third-party object into a bean with properties from your application.properties
file ?
Given an application.properties
file:
third-party-config.params.simpleParam=foo
third-party-config.params.nested.nestedOne=bar1
third-party-config.params.nested.nestedTwo=bar2
Create a class to receive your params from properties file
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration
@Configuration
@ConfigurationProperties(prefix = "third-party-config")
data class ThirdPartConfig(val params: Map<String, Any>)
Here is an example of the object that you want to use
class ThirdPartyObject(private val simpleParam: String, private val nested: Map<String, String>) {
fun printParams() =
"This is the simple param: $simpleParam and the others nested ${nested["nestedOne"]} and ${nested["nestedTwo"]}"
}
Create the configuration class with a method that turns your third-party object into an injectable bean.
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class ThirdPartObjectConfig(private val thirdPartConfig: ThirdPartConfig) {
@Bean
fun thirdPartyObject(): ThirdPartyObject {
return ThirdPartObject(
simpleParam = thirdPartConfig.params["simpleParam"].toString(),
nested = getMapFromAny(
thirdPartConfig.params["nested"]
?: throw IllegalStateException("'nested' parameter must be declared in the app propertie file")
)
)
}
private fun getMapFromAny(unknownType: Any): Map<String, String> {
val asMap = unknownType as Map<*, *>
return mapOf(
"nestedOne" to asMap["nestedOne"].toString(),
"nestedTwo" to asMap["nestedTwo"].toString()
)
}
}
So now you can inject your third-party object as a bean with custom configurated params from your application.properties
files
@SpringBootApplication
class StackoverflowAnswerApplication(private val thirdPartObject: ThirdPartObject): CommandLineRunner {
override fun run(vararg args: String?) {
println("Running --> ${thirdPartObject.printParams()}")
}
}
Maybe change scan packages to inlcude the packages that do you want.
take a look this: Configuration using annotation @SpringBootApplication