Spring-boot: Provide an alternative to @Value("\${foo}") for Kotlin projects

Created on 23 Jan 2017  路  8Comments  路  Source: spring-projects/spring-boot

As discussed in #5537 and this Stackoverflow question, Spring default property placeholder prefix is not a good fit with Kotlin because it is already used in the language for String interpolation and #{...} can't be used as a droppin replacement and has other meaning.

The current workaround I suggest to Kotlin users is to declare these customized PropertySourcesPlaceholderConfigurer that allow to support @Value("%{foo}") without breaking existing Java @Value("${foo}") or Kotlin @Value("\${foo}") annotations.

@Bean
fun kotlinPropertyConfigurer() = PropertySourcesPlaceholderConfigurer().apply {
    setPlaceholderPrefix("%{")
    setIgnoreUnresolvablePlaceholders(true)
}

@Bean
fun defaultPropertyConfigurer() = PropertySourcesPlaceholderConfigurer()

I suggest @Value("%{foo}") since that sounds a not so bad convention, but it could obviously be a different one.

It would be nice if that could be done by default (and documented) in Spring Boot 2.0, using for example @ConditionalOnClass(Unit.class) (kotlin.Unit is the Kotlin class equivalent for Void in Java).

Another way to tackle this issue could be to allow customizing such prefix with an application.properties property + configuring that by default for start.spring.ioKotlin projects, but I tend to think providing such default convention for Kotlin projects is more what I would expect from Spring Boot, but that's open to discussion ;-)

declined

Most helpful comment

In Kotlin you have to escape the $: @Value("\${foo}"), it's not the end of the world but it's ugly so Kotlin developers almost never write this in practice.

All 8 comments

We've moved almost full gears to @ConfigurationProperties and aren't really advising the use of @Value (I can see @dsyer objecting to that in a min). @Value is a Spring Framework feature and we don't do anything special in Spring Boot about it (AFAIK).

I'd be tempted to leave things as they are.

I don't think it matters if we advise using it or not. If it doesn't work in Kotlin we should try and support it, and the suggestion sounds pragmatic.

In Groovy you can just use '${foo}'. Is there no equivalent in Kotlin (a String literal with no replacements)?

In Kotlin you have to escape the $: @Value("\${foo}"), it's not the end of the world but it's ugly so Kotlin developers almost never write this in practice.

Ugliness is in the eye of the beholder, I suppose. It doesn't seem so bad to me, and it's a Spring annotation, so Spring dictates the contents, and if that means escaping, that's just the way it is.

I guess I agree with @snicoll after all (it's fine the way it is).

I understand, I guess we can just promote @ConfigurationProperties usage. Please just continue providing alternative to @Value like you did with @LocalServerPort in order to avoid situation when @Value is mandatory ;-)

I have updated the related Stack Overflow question accordingly. An eventual improvement could be to support @ConfigurationProperties on Kotlin data classes with immutable (val) properties provided via the constructor, but I need to experiment about that and that's not critical since I think you can just use regular Kotlin classes with mutable (var) properties currently.

For what it's worth, here is my opinion: I use injection through constructor whenever possible and I also prefer to have my properties immutable, so I use @Value most of the time with it's corresponding escaped $. It's ugly, but it's not the end of the world like @dsyer said and definitely better (for me) than having mutable properties all over the place. I've used @ConfigurationProperties for some special property loading and I like it, but I'll be willing to use it more when it supports val properties.

@eacasanovaspedre We're not really happy with the mutable nature of @ConfigurationProperties either. We've recently completed a big piece of work that will make it easier to support immutable configuration properties in the future and hopefully you'll soon be able to use Kotlin data classes as configuration properties (watch #8762 for updates).

Was this page helpful?
0 / 5 - 0 ratings