We have been getting "org.kodein.di.Kodein$Depende...
# kodein
e
We have been getting "org.kodein.di.Kodein$DependencyLoopException: Dependency recursion:" errors on and off for a while. We have ended up removing any Kodein access from class initialisation. The Kodein instance is only accessed within functions and inner classes, so we cannot work out how it is causing problems. We are looking for some information about what causes this to occur. To my thinking: * we access the Kodein instance to get an instance (A), which gets initialised, stored (in the Kodein container) and returned * a function (f1) on the returned instance (A) is executed * this function (f1) accesses the Kodein instance to get a different instance (B), which gets initialised, stored and returned * a function (f2) on the new returned instance (B) is executed * this function (f2) accessed the Kodein instance to get the original instance (A) which should already be stored and just be returned
org.kodein.di.Kodein$DependencyLoopException: Dependency recursion: bind<com.github.evanbennett.module.models.generated.ProfileFactory>() ??>bind<com.github.evanbennett.module.models.generated.ProfileVersionFactory>() ? ?>bind<com.github.evanbennett.module.models.generated.ProfileFactory>() ?????? at org.kodein.di.internal.KodeinContainerImpl$Node.check$kodein_di_core(KodeinContainerImpl.kt:83) at org.kodein.di.internal.KodeinContainerImpl.factory(KodeinContainerImpl.kt:154) at org.kodein.di.KodeinContainer$DefaultImpls.factory$default(KodeinContainer.kt:33) at org.kodein.di.KodeinContainer$DefaultImpls.provider(KodeinContainer.kt:77) at org.kodein.di.internal.KodeinContainerImpl.provider(KodeinContainerImpl.kt:6) at org.kodein.di.KodeinContainer$DefaultImpls.provider$default(KodeinContainer.kt:76) at org.kodein.di.internal.DKodeinBaseImpl.Instance(DKodeinImpl.kt:30) at com.github.evanbennett.module.models.generated.managed.ProfileVersionFactory.versionedFactory(ProfileVersion.kt:462) at com.github.evanbennett.module.models.generated.managed.ProfileVersionFactory.versionedFactory(ProfileVersion.kt:123) at com.github.evanbennett.module.models.AbstractVersion$Factory$DefaultImpls.currentVersion(Version.kt:26) at com.github.evanbennett.module.models.Version$Factory$DefaultImpls.currentVersion(Version.kt) at com.github.evanbennett.module.models.generated.managed.ProfileVersionFactory.currentVersion(ProfileVersion.kt:123) at com.github.evanbennett.module.models.generated.managed.ProfileVersion.formTabIsEditableAndButtons$suspendImpl(ProfileVersion.kt:96) at com.github.evanbennett.module.models.generated.managed.ProfileVersion.formTabIsEditableAndButtons(ProfileVersion.kt) at com.github.evanbennett.module.models.generated.managed.ProfileVersion.formTab$suspendImpl(ProfileVersion.kt:108) at com.github.evanbennett.module.models.generated.managed.ProfileVersion.formTab(ProfileVersion.kt) at com.github.evanbennett.module.controllers.generated.managed.ProfileVersions.displayResult$suspendImpl(ProfileVersions.kt:36) at com.github.evanbennett.module.controllers.generated.managed.ProfileVersions$displayResult$1.invokeSuspend(ProfileVersions.kt) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:238) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:405) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834)
r
Your thinking description can be the clue to your problem. if A.f1() calls B.f2() that is actually calling A.f1() you might fall into an infinite loop. If not, the only fact that dependency are referencing each other can also be an issue. In any Dependency Injection framework its not recommended to have dependency loop because you'll never now in which order the dependencies will be resolved, leading to problems
e
Thanks.
There is no infinite loop. The stacktrace above is from the "Profile" controller, factory and model. The code is generated by a Gradle plugin that we have written. This Gradle plugin also generates the same structured code for the "User" controller, factory and model. Which works fine. (i.e. Does not throw a DependencyLoopException.) The situation gets even more complicated (and I left it out initially as I had hoped to find a solution without complicating things). This is part of a Ktor web application. Once I run the application and login through Chrome, if I access the "Profile" first it throws this exception. Instead, if I run the application, login and access the "User" first, the "Profile" then works (and keeps working until I restart the application). This seems wierd to me, but there is a link (in the database structure) from the "ProfileVersion" to the "User. So I thought that might be the cause, until I noticed a link (in the database structure) from the "UserVersionProfile" to the "Profile". We have created another project which extends this project, written additional database structure, which the Gradle plugin uses to generate the same structured controller, factory and model for other tables. These tables have the link to the "User", but I get the DependencyLoopException even if I access the "User" first. I have been trying to work out how to remove the dependency loop, but am having trouble. I will see how I go.
r
ooh, right. It's way beyond a simple configuration! Is your Gradle plugin public ? Is generating code based on your database structure ?