Steps to reproduce :
ktor-hellowebapp from the samplesdeployment block of application.conf autoreload = true
watch = [ sample ]
Stacktrace :
> Task :run
(KOIN) :: [INFO] :: [context] create
(KOIN) :: [INFO] :: [module] declare Bean[class=org.koin.sample.BusinessService]
(KOIN) :: [INFO] :: [modules] loaded 1 definitions
(KOIN) :: [INFO] :: [properties] load koin.properties
(KOIN) :: [INFO] :: [properties] load extras properties : 2
(KOIN) :: [DEBUG] :: [Property] add properties 2
2018-03-13 10:59:17.640 [main] TRACE Application - {
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 8
"application" : {
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 9
"modules" : [
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 10
"org.koin.sample.KoinApplicationKt.main",
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 11
"org.koin.sample.JobRoutesKt.jobRoutes"
]
},
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 2
"deployment" : {
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 4
"autoreload" : true,
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 3
"port" : 8080,
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 5
"watch" : [
# application.conf @ file:/Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main/application.conf: 5
"sample"
]
},
# Content hidden
"security" : "***"
}
2018-03-13 10:59:17.740 [main] DEBUG Application - Java Home: /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home
2018-03-13 10:59:17.740 [main] DEBUG Application - Class Loader: sun.misc.Launcher$AppClassLoader@15db9742: [/* removed */]
2018-03-13 10:59:17.757 [main] DEBUG Application - Watching /Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/classes/kotlin/main/org for changes.
2018-03-13 10:59:17.757 [main] DEBUG Application - Watching /Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/resources/main for changes.
2018-03-13 10:59:17.757 [main] DEBUG Application - Watching /Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/classes/kotlin/main for changes.
2018-03-13 10:59:17.757 [main] DEBUG Application - Watching /Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/classes/kotlin/main/org/koin for changes.
2018-03-13 10:59:17.757 [main] DEBUG Application - Watching /Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/classes/kotlin/main/META-INF for changes.
2018-03-13 10:59:17.757 [main] DEBUG Application - Watching /Users/tarek/Sources/github/koin-samples/samples/ktor-hellowebapp/build/classes/kotlin/main/org/koin/sample for changes.
2018-03-13 10:59:18.124 [main] TRACE Application - Application started: io.ktor.application.Application@928763c
2018-03-13 10:59:23.849 [nettyCallPool-4-1] ERROR Application - Unhandled: GET - /bye
org.koin.error.NoBeanDefFoundException: No definition found to resolve type 'org.koin.sample.BusinessService'. Check your module definition
at org.koin.KoinContext.getVisibleBeanDefinition(KoinContext.kt:119)
at org.koin.KoinContext.resolveInstance(KoinContext.kt:77)
at org.koin.sample.JobRoutesKt$jobRoutes$$inlined$inject$2.invoke(KtorApplicationExt.kt:82)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)
at org.koin.sample.JobRoutesKt$jobRoutes$1$4.doResume(JobRoutes.kt:43)
at org.koin.sample.JobRoutesKt$jobRoutes$1$4.invoke(JobRoutes.kt)
at org.koin.sample.JobRoutesKt$jobRoutes$1$4.invoke(JobRoutes.kt)
at io.ktor.pipeline.PipelineContext.proceed(PipelineContext.kt:49)
at io.ktor.pipeline.Pipeline.execute(Pipeline.kt:22)
at io.ktor.routing.Routing.executeResult(Routing.kt:93)
at io.ktor.routing.Routing.interceptor(Routing.kt:19)
at io.ktor.routing.Routing$Feature$install$1.doResume(Routing.kt:60)
at io.ktor.routing.Routing$Feature$install$1.invoke(Routing.kt)
at io.ktor.routing.Routing$Feature$install$1.invoke(Routing.kt:45)
at io.ktor.pipeline.PipelineContext.proceed(PipelineContext.kt:49)
at io.ktor.features.CallLogging$Feature$install$1.doResume(CallLogging.kt:69)
at io.ktor.features.CallLogging$Feature$install$1.invoke(CallLogging.kt)
at io.ktor.features.CallLogging$Feature$install$1.invoke(CallLogging.kt:61)
at io.ktor.pipeline.PipelineContext.proceed(PipelineContext.kt:49)
at io.ktor.pipeline.Pipeline.execute(Pipeline.kt:22)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$2.doResume(DefaultEnginePipeline.kt:66)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$2.invoke(DefaultEnginePipeline.kt)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$2.invoke(DefaultEnginePipeline.kt)
at io.ktor.pipeline.PipelineContext.proceed(PipelineContext.kt:49)
at io.ktor.pipeline.Pipeline.execute(Pipeline.kt:22)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1.doResume(NettyApplicationCallHandler.kt:27)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1.invoke(NettyApplicationCallHandler.kt)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1.invoke(NettyApplicationCallHandler.kt:10)
at kotlinx.coroutines.experimental.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:44)
at kotlinx.coroutines.experimental.CoroutineStart.invoke(CoroutineStart.kt:113)
at kotlinx.coroutines.experimental.AbstractCoroutine.start(AbstractCoroutine.kt:161)
at kotlinx.coroutines.experimental.BuildersKt.launch(Builders.kt:68)
at kotlinx.coroutines.experimental.BuildersKt.launch$default(Builders.kt:61)
at io.ktor.server.netty.NettyApplicationCallHandler.handleRequest(NettyApplicationCallHandler.kt:22)
at io.ktor.server.netty.NettyApplicationCallHandler.channelRead(NettyApplicationCallHandler.kt:16)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:38)
at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:353)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Hello,
Ok. let us check with autoreload.
I pushed an update on https://github.com/Ekito/koin-samples
I can run the actual app :/ and it reloads
Give a try ?
Did you try calling /bye ?
/ works fine but all the other routes don't seem to work
(It is also maybe worth mentioning that I run the app using the gradle 'application' plugin)
@Baresse is it the good way of working?
@tokou yes, tests are ok. But can't run any other route than "/"
We will check that! 馃憤
We got it! It was a misconfiguration in application.conf. Watched module didn't exist.
Cheers.
@arnaudgiuliani The fix that was added just turns off auto-reload.
I can confirm this still exists. When engine reloading occurs, the BeanRegistry is still populated, but all calls to it fail.
As part of the engine reloading, it looks like the application and possibly classloader is destroyed: https://github.com/ktorio/ktor/blob/37cbb5c59e3c5ae26fd7d2185a26f6e23e076802/ktor-server/ktor-server-host-common/src/io/ktor/server/engine/ApplicationEngineEnvironmentReloading.kt#L171
The best workaround I've found is to do this, when the app is being restarted (as a ktor module):
kotlin
(StandAloneContext.koinContext as KoinContext).beanRegistry.clear()
loadKoinModules(listOf(modulesHere))
Alternatively, you could start koin inside of the ktor module, which is cleanly created every time, but you lose out on property resolution, which is only available(in my case) in the main method.
hello,
let us check that. You can also propose anything in the 1.0.0 branches.
You can check that this problem is still there in koin-ktor:1.0.0-beta-1?
Confirmed it still happens on beta-1. Switching from 0.9.2 to 1.0.0beta-1 was trivial though, so that's good.
(KOIN)::[err] Error while resolving instance for class 'JacksonObjectMapperService' - error: org.koin.error.NoBeanDefFoundException: No definition found to resolve type 'com.c2fo.tpf.service.common.Jackson$
bjectMapperService'. Check your module definition
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at kotlin.reflect.jvm.internal.FunctionCaller$Method.callMethod(FunctionCaller.kt:98)
at kotlin.reflect.jvm.internal.FunctionCaller$StaticMethod.call(FunctionCaller.kt:108)
at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:107)
at kotlin.reflect.jvm.internal.KCallableImpl.callDefaultMethod(KCallableImpl.kt:149)
at kotlin.reflect.jvm.internal.KCallableImpl.callBy(KCallableImpl.kt:111)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.callFunctionWithInjection(ApplicationEngineEnvironmentReloading.kt:330)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.executeModuleFunction(ApplicationEngineEnvironmentReloading.kt:286)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.instantiateAndConfigureApplication(ApplicationEngineEnvironmentReloading.kt:263)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createApplication(ApplicationEngineEnvironmentReloading.kt:120)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.start(ApplicationEngineEnvironmentReloading.kt:235)
at io.ktor.server.netty.NettyApplicationEngine.start(NettyApplicationEngine.kt:85)
at io.ktor.server.netty.NettyApplicationEngine.start(NettyApplicationEngine.kt:16)
at io.ktor.server.engine.ApplicationEngine$DefaultImpls.start$default(ApplicationEngine.kt:46)
at xxx.yyy.zzz.main(ApiApplicationV2.kt:101)
Caused by: org.koin.error.NoBeanDefFoundException: No definition found to resolve type 'xxx.yyy.zzz.JacksonObjectMapperService'. Check your module definition
at org.koin.core.bean.BeanRegistry.getVisibleBean(BeanRegistry.kt:121)
at org.koin.core.KoinContext.resolveInstance(KoinContext.kt:109)
I think it has to do with the classes getting evicted and reloaded as part of the dev environment being re-instantiated.
Calling beanRegistry.search(clazz) returns nothing, despite there being 17 beans defined, with expected class values.
I like the idea of Koin having property resolvers, so I'm hesitant to suggest this, but if you move the Koin start inside of Ktor's modules, you're fine (though I would guess there is a memory leak, since stale definitions aren't cleared).
I like the idea of Koin having property resolvers, so I'm hesitant to suggest this, but if you move the Koin start inside of Ktor's modules, you're fine (though I would guess there is a memory leak, since stale definitions aren't cleared).
We'll check in this direction thanks.
Don't hesitate to propose any solution with a PR if you want.
So far the only workaround that worked for me is
fun Application.main() {
...
StandAloneContext.closeKoin()
StandAloneContext.startKoin(arrayListOf(KoinModule))
}
A proposal can be to add a starter method for Ktor, which does the 2 things: close+start to be sure that Ktor can reload it.
I wrote an extension for Application: the installKoin() function, that does stop/start Koin. Work in my simple demo app below.
````
fun Application.main() {
// Install Ktor features
install(DefaultHeaders)
install(CallLogging)
installKoin(listOf(helloAppModule), logger = SLF4JLogger())
// Lazy inject HelloService
val service by inject<HelloService>()
// Routing section
routing {
get("/hello") {
call.respondText(service.sayHello())
}
v1()
}
}
```
Available in Koin 1.0.0-beta-6. koin-logger-slf4j project is in redindexing from jfrog.
And then, no need to start Koin from outside Ktor. Works also for unit test 馃憤
koin-ktor is fully available in 1.0.0-beta-6 with koin-logger-slf4j
Most helpful comment
Hello,
Ok. let us check with autoreload.