@Configuration / @ConfigurationProperties doesn't ...
# spring
d
@Configuration / @ConfigurationProperties doesn't work. My application.yml
Copy code
seon:
  uri: 123
My SeonConfiguration class:
Copy code
@Configuration
@ConfigurationProperties(prefix = "seon")
data class SeonConfiguration(
    var uri: String = ""
)
My main class:
Copy code
@SpringBootApplication
@ConfigurationPropertiesScan
@EnableConfigurationProperties
class WadzpayServiceApplication
fun main(args: Array<String>) {
    val seonConfiguration: SeonConfiguration = SeonConfiguration()
    print(seonConfiguration.uri) //this line prints null
    runApplication<WadzpayServiceApplication>(*args)
}
I had been looking all the possibile answers on stackoverflow, getting my head crazy but still can't make it work. Any help would be massively appreciated!
a
Well, to start with, Spring has not even had a chance to build it's DAG because you are inspecting the configuration before
runApplication(...)
is executed. Secondarily,
val seonConfiguration: SeonConfiguration = SeonConfiguration()
is simply creating a new instance of
SeonConfiguration
class and not using the one Spring would eventually create - hence the
null
you are seeing. Lastly, this is not a Kotlin-specific issue you are experiencing. You should spend a few more minutes with the Spring documentation/examples.
d
@ashmelev, thank you for your insights. I would love to have a foundation understanding of Spring but I was put in a project without any proper preparation and it is quite urgent, therefore I am having trouble to caught up. I am trying to learn about IOC, dependency injection, etc.. as fast as possible, but still having a lot of problems. Back to the question, after doing a bit of searching I understand your 2 points now. But for the 2nd point, how would I initiate
val seonConfiguration
to the bean object instead of new object (if I understand it correctly)?
m
@Dany what issue U have …. to read the configuration ? try something like this :
Copy code
@SpringBootApplication
@EnableConfigurationProperties(SeaonConfigurer::class)
class WadzpayServiceApplication

fun main(args: Array<String>) {
    runApplication<WadzpayServiceApplication>(*args)
}


@ConstructorBinding
@ConfigurationProperties(prefix = "seon")
class SeaonConfigurer(var uri: String)
Copy code
@Service
class SeonService(private val seaonConfigurer: SeaonConfigurer) {

    fun foo() {
       val bar = seaonConfigurer.host
    }
}
d
@marzelwidmer, thanks for your example, I tried to follow it, at the end, how would I call the SeonService class? If I create a new object like:
val seonService = SeonService()
then AFAIK, configuration data won't be injected. As far as I understand, I need to call the BEAN object created from Spring, not initiate a new one - I am at this point and stuck
m
You have a sample on github ?
image.png
or you try to initialise with the DLS? maybe I get it wrong …
d
Hi, I don't have the sample on GitHub, I am working on a branch on a big project. But here are my code which is following your suggestion. Here is my application.yml:
Copy code
seon:
  uri: 123
Here is my SeonConfiguration.kt
Copy code
@Configuration
@ConfigurationProperties(prefix = "seon")
class SeonConfiguration {
    var uri: String = ""
}
Here is my SeonService.kt
Copy code
@Service
class SeonService(private val seonConfiguration: SeonConfiguration) {
    fun foo() {
        println(seonConfiguration.uri)
    }
}
Here is my main method - which I don't know how to call the method in SeonService to print out the configuration
Copy code
@SpringBootApplication
@ConfigurationPropertiesScan
@EnableConfigurationProperties(SeonConfiguration::class)
class WadzpayServiceApplication

fun main(args: Array<String>) {
    runApplication<WadzpayServiceApplication>(*args)
    /*
    What kind of magic here to make the program print 123
    */
}
m
Ok my question is why or what you try in the magic part for a use case … ? you try to do something on application start up time ?
maybe you can do something like
Copy code
main(args: Array<String>) {
   runApplication<WadzpayServiceApplication>(*args){
      addInitializers(
         beans {
            bean {
               ApplicationRunner { println("ApplicationRunner -----------------> with some magic....") }
            }
         }
      )

   }
}
d
😂, no, I just wanted it somehow call the method
foo
from
SeonService
class, and
foo
will somehow print the uri from configuration file, which is
123
m
image.png
🙂 1
🙌 1
1
✔️ 1
d
Ok, its probably simple for you, but its still some magic to me, I kinda understand that you call it as a bean object - which was created by Spring, therefore you were able to print the URL, but I failed miserably to achieve that. Thanks a lot
m
Maybe there is also a other way but I think it have to be somehow in a springContext.. I think.
k
isn't @ConstructorBinding all you were missing? rest is standard dependency injection
s
The service will be called from the controller. In the controller you have to add service dep. Although it depends on what you are building? Is a REST API?