Reputation: 566
I have this situation:
abstract class BaseWebClient(baseUrl: String) {
abstract val defaultHeaders: HttpHeaders
val client = WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
class AnimalsPortalClient(val config: Config, baseUrl: String) : BaseWebClient(baseUrl) {
override val defaultHeaders: HttpHeaders
get() {
val headers = HttpHeaders()
headers.add("app-name", config.appName)
headers.add("app-version", config.appVersion)
return headers
}
fun getAnimals(): String {
return client.get( // ... etc
}
}
This solution doesn't work, because - when defaultHeaders
are attempted to be retrieved from overriding property in derived class - the variable config
is null
.
A possible solution is to pass the config
object to the base class' constructor:
abstract class BaseWebClient(val config: Config, baseUrl: String) {
abstract val defaultHeaders: HttpHeaders
// ... etc
}
class AnimalsPortalClient(localConfig: Config, baseUrl: String) : BaseWebClient(localConfig, baseUrl) {
override val defaultHeaders: HttpHeaders
get() {
val headers = HttpHeaders()
headers.add("app-name", config.appName)
headers.add("app-version", config.appVersion)
return headers
}
// ... etc
}
But this solution has a drawback: not all extending classes need a config object. In most of derived class I have empty default headers. Like this:
class SoccerPortalClient(baseUrl: String) : BaseWebClient(baseUrl) {
override val defaultHeaders: HttpHeaders
get() = HttpHeaders()
Using the solution I proposed, I would be forced to always have a config object to pass to the base class, even if there is no need for it.
So basically:
Thank you!
Upvotes: 0
Views: 284
Reputation: 7882
You are trying to access defaultHeaders
property at the moment when derived class is not yet initialized.
Consided either convert client
property initializer to getter:
val client
get() = WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
or use lazy delegate:
val client by lazy {
WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
Upvotes: 2
Reputation: 4951
The problem is that your client
field in the base class is initialized before anything else. You can initialize it lazily. Like so:
val client by lazy {
WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
Upvotes: 2