4

Language: Scala; Framework: Play 2.5; Libraries: Silhouette 4.0, Guice, scala-guice.

One of the official Silhouette seed projects uses guice and scala-guice (net.codingwell.scalaguice.ScalaModule) to write DI configuration. Code looks like this:

import net.codingwell.scalaguice.ScalaModule

class Module extends AbstractModule with ScalaModule{

  /**
    * Configures the module.
    */
  def configure() {

    bind[Silhouette[MyEnv]].to[SilhouetteProvider[MyEnv]]
    bind[SecuredErrorHandler].to[ErrorHandler]
    bind[UnsecuredErrorHandler].to[ErrorHandler]
    bind[IdentityService[User]].to[UserService]

I wonder, how would this code look like without magic from net.codingwell.scalaguice library. Could someone re-write these bindings using only original guice ?

in addition I have also this code:

@Provides
  def provideEnvironment(
      userService: UserService,
      authenticatorService: AuthenticatorService[CookieAuthenticator],
      eventBus: EventBus
  ): Environment[MyEnv] = {
    Environment[MyEnv](
      userService,
      authenticatorService,
      Seq(),
      eventBus
    )
  }

Thanks in advance.

RB_
  • 1,195
  • 15
  • 35

2 Answers2

3

Thanks to insan-e for pointing in a right direction. Here is the answer showing how to inject generic implementations using guice:

Inject Generic Implementation using Guice

Thus if removing scala-guice library from equation, bindings can be written like this:

import com.google.inject.{AbstractModule, Provides, TypeLiteral}
class Module extends AbstractModule {

  /**
    * Configures the module.
    */
  def configure() {
    bind(new TypeLiteral[Silhouette[MyEnv]]{}).to(new TypeLiteral[SilhouetteProvider[MyEnv]]{})
Community
  • 1
  • 1
RB_
  • 1,195
  • 15
  • 35
2

There is a description right on the trait introducing the functions, have a look here: https://github.com/codingwell/scala-guice/blob/develop/src/main/scala/net/codingwell/scalaguice/ScalaModule.scala#L32

So, in this case it would translate to something like this:

class SilhouetteModule extends AbstractModule {

  def configure {
    bind(classOf[Silhouette[DefaultEnv]]).to(classOf[SilhouetteProvider[DefaultEnv]])
    bind(classOf[CacheLayer]).to(classOf[PlayCacheLayer])

    bind(classOf[IDGenerator]).toInstance(new SecureRandomIDGenerator())
    bind(classOf[PasswordHasher]).toInstance(new BCryptPasswordHasher)
    ...
}
Moritz
  • 549
  • 5
  • 13
  • Thanks for answer, but I already tried that, and for some reason it doesn't work. I can' figure out why. If I'm writing this: bind(classOf[Silhouette[DefaultEnv]]).to(classOf[SilhouetteProvider[DefaultEnv]]) instead of this : bind[Silhouette[MyEnv]].to[SilhouetteProvider[MyEnv]], I get compilation error: – RB_ Nov 07 '16 at 20:04
  • 1
    CreationException: Unable to create injector, see the following errors: 1) com.mohiva.play.silhouette.api.Environment cannot be used as a key; It is not fully specified. at com.mohiva.play.silhouette.api.SilhouetteProvider.(Silhouette.scala:103) at identity.Module.configure(Module.scala:47) (via modules: com.google.inject.util.Modules$OverrideModule -> identity.Module) – RB_ Nov 07 '16 at 20:06
  • 1
    Can't bind generic types like that. It is more like this: bind(new TypeLiteral[Silhouette[DefaultEnv]] {}).to(classOf[SilhouetteProvider[DefaultEnv]]]) – insan-e Nov 07 '16 at 22:00