Problem with PasswordInfoDAO implmentation in Silhouette version 6.1

Hi, I am migrating my app from Silhouette 5.0 to 6.1 and found trouble with PasswordInfoDAO implementation.

My class definition as follows:

class PasswordInfoDAO @Inject() (db: Database)( implicit val classTag: ClassTag[PasswordInfo]) extends DelegableAuthInfoDAO[PasswordInfo]

and in SilhouetteModule:

bind[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordInfoDAO]

I am having the following execution error:

No implementation for scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo> was bound.

while locating scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo>

for the 2nd parameter of models.daos.PasswordInfoDAO.(PasswordInfoDAO.scala:18)

at modules.SilhouetteModule.configure(SilhouetteModule.scala:83) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.SilhouetteModule)

This class was executing well in version 5.0. I should be missing something.

Please help

Thank you

Hi,

We had this topic a while back in the gitter channel:

https://gitter.im/mohiva/play-silhouette?at=5d47f9ab3d8f1f29e0157831

Thank you Akkie for your quick response

I have included a Provider in the class definition as follows:

class PasswordInfoDAO @Inject() (db: Database, classTagProvider: Provider[ClassTag[PasswordInfo]])
extends DelegableAuthInfoDAO[PasswordInfo] {

val classTag = classTagProvider.get()

and still getting the same execution error:

No implementation for scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo> was bound.

while locating com.google.inject.Provider<scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo>>

for the 2nd parameter of models.daos.PasswordInfoDAO.(PasswordInfoDAO.scala:19)

at modules.SilhouetteModule.configure(SilhouetteModule.scala:83) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.SilhouetteModule)

Would you please provide an example of Silhouette 6.1 PasswordInfo DAO persistance implementation ? Any other path you might suggest ?

Thank you

You should use a Guice @Provides annotated method with a param classTag: ClassTag[PasswordInfo]. It will be filled automatically by the compiler.

I’ll add this to the migration guide if I’m home from vacation

Akkie, please tell me where the Guice @Provides annotated method should be defined. An implementation example of this will be very much appreciated.

Thanks.

1 Like

@gObando Please see https://www.silhouette.rocks/docs/migration-guide

Akkie, thank you so much for your neat explanation in Silhouette migration guide. It allows me to move forward.

Hi there, sorry I’m not sure how to get this to work still. My previous code was:

@Singleton
class PasswordDAO @Inject()(dbConfigProvider: DatabaseConfigProvider, loginDAO: LoginDAO) extends DelegableAuthInfoDAO[PasswordInfo] {...}

and

bind[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordDAO]

in my SilhouetteModule.

I changed this to:

@Singleton
class PasswordDAO @Inject()(dbConfigProvider: DatabaseConfigProvider, loginDAO: LoginDAO)(implicit val classTag: ClassTag[PasswordInfo]) extends DelegableAuthInfoDAO[PasswordInfo] {

removed the binding and put the following after override def config() { … }

@Provides @Named("password-repository")
  def providePasswordDAO(
    dbConfigProvider: DatabaseConfigProvider,
    loginDAO: LoginDAO): DelegableAuthInfoDAO[PasswordInfo] = {

    new PasswordDAO(dbConfigProvider, loginDAO)
  }

But can’t get it to work:


CreationException: Unable to create injector, see the following errors:

1) No implementation for scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo> was bound.
  while locating scala.reflect.ClassTag<com.mohiva.play.silhouette.api.util.PasswordInfo>
    for the 3rd parameter of auth.models.PasswordDAO.<init>(Password.scala:31)
  while locating auth.models.PasswordDAO
    for the 1st parameter of auth.services.PasswordService.<init>(PasswordService.scala:13)
  while locating auth.services.PasswordService
    for the 2nd parameter of controllers.AuthenticationController.<init>(AuthenticationController.scala:27)
  while locating controllers.AuthenticationController
    for the 3rd parameter of router.Routes.<init>(Routes.scala:97)
  at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:130):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)

Some help would be much appreciated and thanks for creating such an awesome library! :slight_smile:

Ok I found three solutions to this. Either by adding:

  @Provides
  def providePasswordService(
    passwordDAO: DelegableAuthInfoDAO[PasswordInfo]
  ): PasswordService = {

    new PasswordService(passwordDAO.asInstanceOf[PasswordDAO])
  }

OR by creating two providePasswordDAO:

  @Provides
  def providePasswordDAO(
    dbConfigProvider: DatabaseConfigProvider,
    loginDAO: LoginDAO
  ): DelegableAuthInfoDAO[PasswordInfo] = {

    new PasswordDAO(dbConfigProvider, loginDAO)
  }

  @Provides
  def providePasswordDAO2(
    dbConfigProvider: DatabaseConfigProvider,
    loginDAO: LoginDAO
  ): PasswordDAO = {

    new PasswordDAO(dbConfigProvider, loginDAO)
  }

OR by changing def provideAuthInfoRepository to:

  @Provides
  def provideAuthInfoRepository(
    passwordInfoDAO: PasswordDAO,
    oauth1InfoDAO: DelegableAuthInfoDAO[OAuth1Info],
    oauth2InfoDAO: DelegableAuthInfoDAO[OAuth2Info],
    openIDInfoDAO: DelegableAuthInfoDAO[OpenIDInfo]
  ): AuthInfoRepository = {

    new DelegableAuthInfoRepository(passwordInfoDAO, oauth1InfoDAO, oauth2InfoDAO, openIDInfoDAO)
  }

Is there a more elegant solution to this that I’m missing? Are all these solutions safe to use?

Thanks!

Hi,

Have you read: https://www.silhouette.rocks/docs/migration-guide

Best regards
Christian