Generating configuration metadata from @ConfigurationProperties items written in Kotlin doesn't work _for defaultValue fields_. It works fine for all the other fields. In java, it works fine for everything. Here is an example. Note that I'm using Spring Boot 2.0 and Gradle.
kapt 'org.springframework.boot:spring-boot-configuration-processor'
kapt {
arguments {
arg("org.springframework.boot.configurationprocessor.additionalMetadataLocations", "$projectDir/src/main/resources")
}
}
compileJava.dependsOn(processResources)
My @ConfigurationProperties file looks like this:
@Component
@ConfigurationProperties("flowr.epg")
class EpgProperties {
/** Whether or not schedules should be computed/refreshed on (re)start */
var refreshOnRestart = true
/** Number of threads used to store new images */
var nImagesUploadThreads = 10
}
The result looks like this:
{
"hints": [],
"groups": [
{
"sourceType": "com.taktik.flowr.epg.properties.EpgProperties",
"name": "flowr.epg",
"type": "com.taktik.flowr.epg.properties.EpgProperties"
}
],
"properties": [
{
"sourceType": "com.taktik.flowr.epg.properties.EpgProperties",
"defaultValue": false,
"name": "flowr.epg.refresh-on-restart",
"description": "Whether or not schedules should be computed\/refreshed on (re)start",
"type": "java.lang.Boolean"
},
{
"sourceType": "com.taktik.flowr.epg.properties.EpgProperties",
"defaultValue": 0,
"name": "flowr.epg.n-images-upload-threads",
"description": "Number of threads used to store new images",
"type": "java.lang.Integer"
}
}
Support for default values in Kotlin would be a really nice feature to have for my company.
Note: replicated from https://stackoverflow.com/questions/53636533/spring-boot-configurationproperties-metadata-generation-wrong-default-values
It's actually worse. It doesn't detect the default value and use default value for the underlying type. I guess we will need to see if we can't hook into some low-level APIs as we've done for the Java compiler.
I'm seeing the same problem. Just to be clear: the problem is only with the generated metadata, the default values specified in Kotlin @ConfigurationProperties do get picked up, they are just not documented in the metadata, right?
Correct.
Unfortunately there's not much we can do at the moment, please vote for KT-30164. In the meantime, we could attempt to detect that the source model is a Kotlin class and then deactivate default handling to avoid writing wrong value in the metadata.
Ok, yes I guess it would be a good idea to do that in the meantime.
Thanks for everything!
It works fine for all the other fields.
@Simon3 that doesn't match my analysis. Can you please share a sample where other Kotlin fields have a proper default value in the generated metadata? (a small project I can run would be ideal). Thanks!
What I meant is that the "name", "description" and "type" fields are all always correct. But the "defaultValue" field is always incorrect. It is illustrated by the example in my first post.
Cool, we're on the same page now. Thanks for the feedback.
Unfortunately, there hasn't been enough progress on the kotlin side of things to implement this. My gut feeling is that another hook point might be required (Kotlin compiler plugin?). We'll adapt to whatever is available to us and I'll update this issue accordingly.
Any update on this? KT-30164 is fixed now.
@m-kay I need to double check but I don't think this is changing much for most use cases, per
Moreover, since Kotlin 1.4 the compiler will emit value attributes only for const vals.
That definitely isn't helping for what we're trying to achieve here.
KT-30164 is marked as fixed in 1.3.70 and Kotlin 1.3.70 has just been released. We just updated our projects to that version now and after a rebuild the spring-configuration-metadata.json contains the correct defaultValues for our configuration properties now.
So this seems to be fixed to me, or at least something has changed for the better.
@darioseidl thanks for the nudge. We'll ugprade to 1.3.70 and then revisit this one. I've a number of test cases and it's great to hear your use cases are working as expected.
@darioseidl I have been unable to get defaultValues generated correctly in spring-configuration-metadata.json, could you please double check on your side? I have published my repro project , could you please have a look and send me your feedback?
Default values now work fine for me too!
All I had to do regarding my original post was to upgrade Kotlin to 1.3.70 :)
Thanks snicoll!
Ok I have found the difference, it works for regular var properties but not with @ConstructorBinding.
Works:
@ConfigurationProperties("demo")
class DemoProperties {
var title: String = "foo"
}
Does not work and require @DefaultValue to get defaultValues metadata generated correctly:
@ConstructorBinding
@ConfigurationProperties("demo")
class DemoProperties(val title: String = "foo")
This issues is already tracked on Kotlin side by https://youtrack.jetbrains.com/issue/KT-29355.
Ah, yes, we are using var properties and it works for them. We haven't tried @ConstructorBinding yet.
This issue has been superseded by a fix in Kotlin, see KT-30164. This will be available as of 2.2.6 or if you override to Kotlin 1.3.70 or later.
This seems to be meant to be closed based on the last comment from @snicoll.
Thanks @izeye.