Improvement on Guice ... bind(javaClass<EmailSender>()).to(javaClass<DummyEmailSender>())

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.

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.

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.

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 :frowning:

Great, thanks for that.  I've given the ticket a vote :)