InsertKoinIO/koin

Installing Koin plugin to Ktor (2.0.0-beta-1) is not working

ronjunevaldoz opened this issue ยท 21 comments

Describe the bug
Due to Ktor 2.0.0-beta-1 breaking changes koin install is not working,

To Reproduce
Create a sample installation of the plugin. https://ktor.io/docs/creating-custom-plugins.html

fun Application.configureDependencyInjection() {
    install(CustomKoinPlugin) {
        slf4jLogger(Level.ERROR)
        modules(appModule)
    }
}

Expected behavior
No error will be encountered in IDE

Ktor dependency injection
ktor: 2.0.0-beta-1
koin-ktor: koin-ktor version 3.1.5

Workaround

// Copy from the latest koin code and reimport
val KApplicationStarted = EventDefinition<KoinApplication>()
val KApplicationStopPreparing = EventDefinition<KoinApplication>()
val KApplicationStopped = EventDefinition<KoinApplication>()
// Create a new custom application plugin
internal class CustomKoinPlugin(internal val koinApplication: KoinApplication) {
    // Implements ApplicationPlugin as a companion object.
    companion object Plugin : ApplicationPlugin<ApplicationCallPipeline, KoinApplication, CustomKoinPlugin> {
        // Creates a unique key for the plugin.
        override val key = AttributeKey<CustomKoinPlugin>("CustomKoinPlugin")

        // Code to execute when installing the plugin.
        override fun install(
            pipeline: ApplicationCallPipeline,
            configure: KoinApplication.() -> Unit
        ): CustomKoinPlugin {
            val monitor = pipeline.environment?.monitor
            val koinApplication = startKoin(appDeclaration = configure)
            if (monitor != null) {
                monitor.raise(KApplicationStarted, koinApplication)
                monitor.subscribe(ApplicationStopping) {
                    monitor.raise(KApplicationStopPreparing, koinApplication)
                    stopKoin()
                    monitor.raise(KApplicationStopped, koinApplication)
                }
            } 
            return CustomKoinPlugin(koinApplication)
        }
    }
}
// also copy and reimport the inject extensions
wlara commented

I'm running into the same issue. And I also tried Koin 3.2.0-beta-1 and got the same result.

wlara commented

And, btw in the workaround you can eliminate all of the:

val KApplicationStarted = EventDefinition<KoinApplication>()
val KApplicationStopPreparing = EventDefinition<KoinApplication>()
val KApplicationStopped = EventDefinition<KoinApplication>()

Since no one will subscribe to those events.

Is there any work on this? Ktor 2.0.0 was released. The workaround is not working any longer.

Ktor 2.0 is in production, Koin is not working. I tried to migrate my project today, everything else worked except Koin.
Any updates?

@Marek00Malik Have you found a working solution?
I have a working solution here: https://gist.github.com/MarkusNowotny/c245b5f493bfdde09d7b9853ef91fb55
This works in my code but I havn't testet it against ktor and koin. Maybe this helps you

@MarkusNowotny you may want to check the existing PR and suggest your solution. Thanks man!

@MarkusNowotny you may want to check the existing PR and suggest your solution. Thanks man!

@ceosilvajr can you provide an actual working solution with an example.
I'm getting an error None of the following functions can be called with the arguments supplied. modules(vararg Module) defined in org.koin.core.KoinApplication modules(List<Module>) defined in org.koin.core.KoinApplication modules(Module) defined in org.koin.core.KoinApplication
in the createApplicationPlugin function when trying to add the modules, everything else looks ok but this function throws an error, if I remove pluginConfig.modules the function is not complaining. It looks like the parameters it requires are incorrect

So I tried @MarkusNowotny solution, indeed it works, at least in tests and basic solutions.
This file is what needs to be added, add it as a separate file and use as default Koin plugin.

fun Application.configureKoin() {
    install(Koin) {
        modules = arrayListOf(<your Koin modules>)
    }
}

The module import you are talking about is the one that is from Koin itself.

These are the imports that I'm using.

import io.ktor.events.EventDefinition
import io.ktor.server.application.Application
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.ApplicationStopped
import io.ktor.server.application.createApplicationPlugin
import io.ktor.server.application.install
import io.ktor.server.routing.Route
import io.ktor.server.routing.Routing
import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.core.context.GlobalContext
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.core.module.Module
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.dsl.KoinAppDeclaration

@iamdamjanmiloshevski you need to use themodules from KoinConfig class and use the list to add your koin module.

I made some modification, I explicitly use org.koin.core.module.Module

class KoinConfig {

    internal var modules: ArrayList<org.koin.core.module.Module> = ArrayList()

    operator fun org.koin.core.module.Module.unaryPlus() {
        modules.add(this)
    }

    operator fun List<org.koin.core.module.Module>.unaryPlus() {
        modules.addAll(this)
    }

}

Then you can do

fun Application.configureKoin() {
    install(KoinPlugin) {
        modules = arrayListOf(
            module{}
        )
    }
}

@ceosilvajr, @Marek00Malik thank you both very much, I got it working, just tested. It was the bloody imports that caused the issue. IntelliJ wasn't picking them up automatically, just copied the imports and the code was ok. The app is running perfectly.

I owe you guys a beer ๐Ÿป or crypto if you want ๐Ÿ˜Ž

Awesome @iamdamjanmiloshevski! Happy to help ๐Ÿ˜Ž

Pay attention that the modules variable is internal and may not be callable.

I have used it in this way:

fun Application.configureInjection(modules: List<Module> = emptyList()) {
	install(Koin) {
		+module {
			single { environment.config }
			single { log }
		}
		+modules
	}
}

Pay attention that the modules variable is internal and may not be callable.

I have used it in this way:

fun Application.configureInjection(modules: List<Module> = emptyList()) {
	install(Koin) {
		+module {
			single { environment.config }
			single { log }
		}
		+modules
	}
}

@MarkusNowotny it works ok now, I tested. Anyway you helped a lot, thanks. I hope the Koin team accepts this solution asap and release an official update.

This is how I used it

fun Application.configureDependencyInjection() {
    install(Koin){
        modules = arrayListOf(module1, module2, module3)
    }
}

for me it didn't worked(
I get bunch of errors in the code
1.

One type argument expected for interface ApplicationPlugin<out TConfiguration : Any>

2

'key' overrides nothing

3

'install' overrides nothing

4

Type mismatch.
Required:
io.ktor.server.application.Plugin<TypeVariable(P), TypeVariable(B), TypeVariable(F)>
Found:
com.example.base.CustomKoinPlugin.Plugin

for me it didn't worked( I get bunch of errors in the code 1.

One type argument expected for interface ApplicationPlugin<out TConfiguration : Any>

2

'key' overrides nothing

3

'install' overrides nothing

4

Type mismatch.
Required:
io.ktor.server.application.Plugin<TypeVariable(P), TypeVariable(B), TypeVariable(F)>
Found:
com.example.base.CustomKoinPlugin.Plugin

Please check this repo https://github.com/iamdamjanmiloshevski/betting-doctor-api with a working project available in production.
Let me know if you need any help

Koin for Ktor 2.0 is now ready in https://github.com/InsertKoinIO/koin-ktor

@arnaudgiuliani Hey! Could you plz provide an example for new usage of koin plugin? For me previous approach still is not works for the ktor 2.0

I don't see references to Koin 3.2.0 Beta 2 anywhere other than in the koin-ktor project. Is that already published somewhere? It seems like koin-ktor needs beta2, right?

because koin-ktor will be soon published as stable. Just wait those next days.

these are my gradle properties
ktorVersion=2.0.0
kotlinVersion=1.5.31
logbackVersion=1.2.6
koinVersion=3.1.3

install(Koin) { //I am geeting error
slf4jLogger()
}

how ro fix this?

@Abhijeet41 Just wait for release of new version of ktor-koin (3.2.0-beta-2 or 3.2.0 release)