So with a Guice binding example of:
bind(javaClass <EmailSender>()).to(javaClass <DummyEmailSender>())
Is there a better syntax alternative? I’ve tried adding a helper function that takes KClass but not progressing that (EmailSender::class.javaClass is not EmailSender.class so I’m not sure how to progress that yet).
Has anyone got some good thoughts?
Cheers, Rob.
orangy
June 8, 2015, 11:30am
2
You can add reified inline function to help with syntax:
inline fun <reified T> Binder.bind() = bind(javaClass<T>())
inline fun <reified T> Binding.to() = to(javaClass<T>())
and then use it like this:
binder.bind<EmailSender>().to<DummyEmailSender>()
PS: I don’t know Guice very well, so I may be choosing wrong receiver types for extension functions.
udalov
June 8, 2015, 12:05pm
3
If you want to get a java.lang.Class instance by a KClass instance, you can use "java" extension property (defined in kotlin.reflect.jvm): EmailSender::class.java
Thanks IIya,
That does compile but it does give me a VerifyError when I run. If you are keen you can git clone from https://github.com/avaje-metric/example-app …
I’m using Java build 1.8.0_45-b14, Kotlin 0.12.213
In case it is interesting the error I see is:
00:07:21.700 [org.example.main.MainPackage.main()] DEBUG o.example.myapp.web.module.WebModule - configuring module …
00:07:21.709 [org.example.main.MainPackage.main()] WARN o.e.j.u.component.AbstractLifeCycle - FAILED o.e.j.w.WebAppContext@5866c318{/,file:/home/rob/work-avaje/example-app/src/main/webapp/,STARTING}: java.lang.VerifyError: Bad access to protected data in invokevirtual
Exception Details:
Location:
org/example/myapp/service/module/AppServiceModule.bind(Lcom/google/inject/AbstractModule;)Lcom/google/inject/binder/AnnotatedBindingBuilder; @14 : invokevirtual
Reason:
Type ‘com/google/inject/AbstractModule’ (current frame, stack[0]) is not assignable to ‘org/example/myapp/service/module/AppServiceModule’
Current Frame:
bci: @14
flags: { }
locals: { ‘org/example/myapp/service/module/AppServiceModule’, ‘com/google/inject/AbstractModule’ }
stack: { ‘com/google/inject/AbstractModule’, ‘java/lang/Class’ }
Bytecode:
0x0000000: 2b12 11b8 0017 2b12 19b8 001d 121f b600
0x0000010: 22b0
Thanks Alexander, yes I like that better. With the syntax highlighting of "::class" and ".java" in Idea it's much more readable than what I had before.
Example:
bind(MetricService::class .java ).asEagerSingleton()
bind(EmailSender::class .java ).to(DummyEmailSender::class .java )
Thanks, Rob.
orangy
June 8, 2015, 12:32pm
6
We'll take a look at VerifyError, it looks like Kotlin confused two receivers - instance and extension. Meanwhile, try moving these two functions out of class so they become top-level extension functions.
I've reproduced VerifyError, here is an issue: https://youtrack.jetbrains.com/issue/KT-7971
Unfortunately, my previous idea won’t work, because “bind” is protected in AbstractModule
Great, thanks for that. I've given the ticket a vote :)