I'm a Java developer new to Kotlin and I'm trying to access values that I set in an application.yml
file.
application.yml
q:
client:
apiUrl: https://app.abc.com/api/integr/v1.0
apiToken: abc
apiSecret: abc
authEmail: [email protected]
sourceName: abc
This is my configuration class, which follows a similar pattern to Java.
@Component
@FeignClient(name = "q", url = "\${q.client.api-url}")
interface QClient {
@PostMapping("/user/get")
fun findUser(@RequestBody request: QRequest?):
QResponse<List<QUser?>?>
@PostMapping("/user/delete")
fun deleteUser(@RequestBody request: QRequest?): QResponse<DeleteResponse?>?
@Configuration
class QConfig {
@Value("\${q.client.apiToken}")
private val apiToken: String? = null
@Value("\${q.client.apiSecret}")
private val apiSecret: String? = null
@Value("\${q.client.authEmail}")
private val authEmail: String? = null
@Value("\${q.client.sourceName}")
private val sourceName: String? = null
fun createAuthRequest(): QAuth {
return QAuth(apiToken, apiSecret, authEmail, sourceName)
}
}
I don't want to assign null as default values for the instance variables, but Kotlin wants me to declare them like this to avoid null references.
I need to create an auth request and I'm calling the config class from the main class.
private fun generateRequest(email: String): QRequest {
val config = QClient.QConfig()
val auth = config.createAuthRequest()
return QRequest(auth, email)
}
But when debugging it just returns null values.
So after googling, I changed my approach and set all the key values into parameters of QConfig
class like this:
@Configuration
class QConfig(
@Value("\${q.client.apiToken}") private val apiToken: String,
@Value("\${q.client.apiSecret}") private val apiSecret: String,
@Value("\${q.client.authEmail}") private val authEmail: String,
@Value("\${q.client.sourceName}") private val sourceName: String
) {
fun createAuthRequest(): QAuth {
return QAuth(apiToken, apiSecret, authEmail, sourceName)
}
}
The problem I faced here was it acts as a constructor and expects me to pass arguments while creating an instance for the QConfig
class on the main class, which I wont have in the main class.
How can I get the values from the application.yml
and access them as from instance variables?
CodePudding user response:
You can use @ConfigurationProperties
(ref)
@ConfigurationProperties("q.client")
@ConstructorBinding
data class ClientConfig(
val apiUrl: String, // variable name should be same as the one defined in application.yaml
val apiToken: String,
...other properties
)
@SpringBootApplication
@ConfigurationPropertiesScan
class SpringStackoverflowApplication {
@Autowired
private lateinit var clientConfig: ClientConfig
@EventListener(ApplicationReadyEvent::class)
fun doSomething() {
println("FOOBAR: $clientConfig")
}
}
fun main(args: Array<String>) {
runApplication<SpringStackoverflowApplication>(*args)
}
CodePudding user response:
I solved this with Joffrey's reply, I used this format of config file
@Component
@Configuration
class QConfig {
@Value("\${q.client.apiToken}")
private val apiToken: String? = null
@Value("\${q.client.apiSecret}")
private val apiSecret: String? = null
@Value("\${q.client.authEmail}")
private val authEmail: String? = null
@Value("\${q.client.sourceName}")
private val sourceName: String? = null
fun createAuthRequest(): QAuth {
return QAuth(apiToken, apiSecret, authEmail, sourceName)
}
}
Then created the instance of QConfig like this on main class
@Autowired
val config = QConfig()
My bad, tried creating reference of class manually instead of using AutoWire. When ran it pulled all the variables set on yml file into the local variables.