PlayHTTPLayer Errors


#1

I am currently migrating from Play 2.3 to Play 2.5 and I am getting errors when the following provider is requested:

  @Provides
  def provideHTTPLayer(client: WSClient): HTTPLayer = new PlayHTTPLayer(client)

1) No implementation for com.mohiva.play.silhouette.api.actions.SecuredAction was bound.
  while locating com.mohiva.play.silhouette.api.actions.SecuredAction
    for parameter 1 at com.mohiva.play.silhouette.api.SilhouetteProvider.<init>(Silhouette.scala:103)
  at modules.DefaultModule.bind(DefaultModule.scala:48)

2) No implementation for com.mohiva.play.silhouette.api.actions.UnsecuredAction was bound.
  while locating com.mohiva.play.silhouette.api.actions.UnsecuredAction
    for parameter 2 at com.mohiva.play.silhouette.api.SilhouetteProvider.<init>(Silhouette.scala:103)
  at modules.DefaultModule.bind(DefaultModule.scala:48)

3) No implementation for com.mohiva.play.silhouette.api.actions.UserAwareAction was bound.
  while locating com.mohiva.play.silhouette.api.actions.UserAwareAction
    for parameter 3 at com.mohiva.play.silhouette.api.SilhouetteProvider.<init>(Silhouette.scala:103)
  at modules.DefaultModule.bind(DefaultModule.scala:48)

4) No implementation for play.api.i18n.MessagesApi was bound.
  while locating play.api.i18n.MessagesApi
    for parameter 0 at com.mohiva.play.silhouette.api.actions.DefaultSecuredErrorHandler.<init>(SecuredAction.scala:276)
  at modules.DefaultModule.bind(DefaultModule.scala:48)

5) No implementation for play.api.i18n.MessagesApi was bound.
  while locating play.api.i18n.MessagesApi
    for parameter 0 at com.mohiva.play.silhouette.api.actions.DefaultUnsecuredErrorHandler.<init>(UnsecuredAction.scala:201)
  at modules.DefaultModule.bind(DefaultModule.scala:48)

6) No implementation for play.cache.CacheApi was bound.
  while locating play.cache.CacheApi
    for parameter 0 at org.pac4j.play.store.PlayCacheStore.<init>(PlayCacheStore.java:32)
  at modules.DefaultModule.configure(DefaultModule.scala:77)

7) No implementation for play.api.libs.ws.WSClient was bound.
  at modules.DefaultModule.provideHTTPLayer(DefaultModule.scala:180)

8) Could not find a suitable constructor in play.api.Configuration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Configuration.class(Configuration.scala:175)
  at modules.DefaultModule.provideAuthenticatorService(DefaultModule.scala:129)

9) Could not find a suitable constructor in play.api.Configuration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Configuration.class(Configuration.scala:175)
  at modules.DefaultModule.provideAuthenticatorCookieSigner(DefaultModule.scala:167)

10) Could not find a suitable constructor in play.api.Configuration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Configuration.class(Configuration.scala:175)
  at modules.DefaultModule.provideAuthenticatorCrypter(DefaultModule.scala:174)

I do not see how this is done in the play-silhouette-seed. What am I missing?


#2
package modules

import com.google.inject.name.Named
import com.google.inject.{AbstractModule, Provides}
import com.mohiva.play.silhouette.api.actions._
import com.mohiva.play.silhouette.api.crypto.{CrypterAuthenticatorEncoder, Crypter, CookieSigner}
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.{SilhouetteProvider, Silhouette, Environment, EventBus}
import com.mohiva.play.silhouette.api.services.AuthenticatorService

import com.mohiva.play.silhouette.api.util._
import com.mohiva.play.silhouette.crypto.{JcaCrypter, JcaCrypterSettings, JcaCookieSigner, JcaCookieSignerSettings}
import com.mohiva.play.silhouette.impl.authenticators.{CookieAuthenticatorService, CookieAuthenticatorSettings, CookieAuthenticator}
import com.mohiva.play.silhouette.impl.providers.{OpenIDInfo, CredentialsProvider, OAuth2Info, OAuth1Info}
import com.mohiva.play.silhouette.impl.util.{DefaultFingerprintGenerator, SecureRandomIDGenerator}
import com.mohiva.play.silhouette.password.BCryptPasswordHasher
import com.mohiva.play.silhouette.persistence.daos.DelegableAuthInfoDAO
import com.mohiva.play.silhouette.persistence.repositories.DelegableAuthInfoRepository
import net.codingwell.scalaguice.{ScalaMultibinder, ScalaModule}
import org.pac4j.play.store.{PlaySessionStore, PlayCacheStore}
import org.sedis.{SentinelPool, Pool}
import play.api.i18n.{DefaultLangs, MessagesApi, DefaultMessagesApi}
import play.api.libs.ws.WSClient
import play.api.{Configuration, Play}
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ArbitraryTypeReader._
import play.cache.DefaultCacheApi
import play.i18n.Lang
import redis.clients.jedis.{JedisSentinelPool, JedisPool}
import services.auth
import services.auth.silhouette._
import play.api.libs.concurrent.Execution.Implicits._
import services.auth.{ClientTokenProvider, RemoteCredentialsProvider}
import services.cache.CacheApi
import services.cache.redis.{RedisCacheApi, SedisPoolProvider, JedisPoolProvider}
import services.meta.virtual.{MetaDataVirtualDomainProvider, VirtualDomainProvider}
import services.meta.{MetaDataService, MetaDataServiceRESTImpl}
import services.rest.{DefaultRestService, RestService}
import services.search.{SearchService, SearchServiceImplNew}
import services.user.{UserService, UserServiceImpl}


import scala.concurrent.duration.Duration

//import models.daos._
import models.User

/**
 * The Guice module which wires all Silhouette dependencies.
 */
class DefaultModule extends AbstractModule with ScalaModule {

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

    bind[UserService].to[UserServiceImpl]
    //    bind[UserDAO].to[UserDAOImpl]
    /*bind[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordInfoDAO]
    bind[DelegableAuthInfoDAO[OAuth1Info]].to[OAuth1InfoDAO]
    bind[DelegableAuthInfoDAO[OAuth2Info]].to[OAuth2InfoDAO]*/

    bind[Silhouette[DefaultEnv]].to[SilhouetteProvider[DefaultEnv]]
    bind[UnsecuredErrorHandler].to[DefaultUnsecuredErrorHandler]
    bind[SecuredErrorHandler].to[DefaultSecuredErrorHandler]
    bind[MetaDataService].to[MetaDataServiceRESTImpl]
    bind[CacheLayer].to[DocupaceCacheLayer]
    bind[IDGenerator].toInstance(new SecureRandomIDGenerator())
    bind[PasswordHasher].toInstance(new BCryptPasswordHasher)
    bind[FingerprintGenerator].toInstance(new DefaultFingerprintGenerator(false))
    bind[EventBus].toInstance(EventBus())
    bind[SearchService].toInstance(new SearchServiceImplNew())
    bind[RestService].toInstance(new DefaultRestService())
    bind[DefaultRestService].toInstance(new DefaultRestService())
    bind[JedisSentinelPool].toProvider[JedisPoolProvider]
    bind[SentinelPool].toProvider[SedisPoolProvider]
    bind[CacheApi].to[RedisCacheApi]
    bind[Clock].toInstance(Clock())
    bind(classOf[PlaySessionStore]).to(classOf[PlayCacheStore])



    val vdpMulti = ScalaMultibinder.newSetBinder[VirtualDomainProvider](binder)
    vdpMulti.addBinding.toInstance(new MetaDataVirtualDomainProvider())
  }

  /**
   * Provides the Silhouette environment.
   *
   * @param userService The user service implementation.
   * @param authenticatorService The authentication service implementation.
   * @param eventBus The event bus instance.
   * @return The Silhouette environment.
   */
  @Provides
  def provideEnvironment(
                          userService: UserServiceImpl,
                          authenticatorService: AuthenticatorService[CookieAuthenticator],
                          eventBus: EventBus,
                          credentialsProvider: CredentialsProvider,
                          clientTokenProvider: ClientTokenProvider): Environment[DefaultEnv] = {

    Environment[DefaultEnv](
      userService,
      authenticatorService,
      /*Map(
        credentialsProvider.id -> credentialsProvider,
        clientTokenProvider.id -> clientTokenProvider,
        docupaceGenericProvider.id -> docupaceGenericProvider //TODO Lookat
      )*/
      Seq(),
      eventBus
    )
  }

  /**
   * Provides the authenticator service.
   *
   * @param cacheLayer The cache layer implementation.
   * @param idGenerator The ID generator used to create the authenticator ID.
   * @return The authenticator service.
   */

    @Provides
    def provideAuthenticatorService(
                                     @Named("authenticator-cookie-signer") cookieSigner: CookieSigner,
                                     @Named("authenticator-crypter") crypter: Crypter,
                                     fingerprintGenerator: FingerprintGenerator,
                                     idGenerator: IDGenerator,
                                     configuration: Configuration,
                                     clock: Clock): AuthenticatorService[CookieAuthenticator] = {

      val config = configuration.underlying.as[CookieAuthenticatorSettings]("silhouette.authenticator")
      val encoder = new CrypterAuthenticatorEncoder(crypter)

      new CookieAuthenticatorService(config, None, cookieSigner, encoder, fingerprintGenerator, idGenerator, clock)
    }


  /**
   * Provides the auth info service.
   *
   * @param passwordInfoDAO The implementation of the delegable password auth info DAO.
   * @param oauth1InfoDAO The implementation of the delegable OAuth1 auth info DAO.
   * @param oauth2InfoDAO The implementation of the delegable OAuth2 auth info DAO.
   * @return The auth info service instance.
   */

  /**
   * Provides the credentials provider.
   *
   * @param authInfoService The auth info service implemenetation.
   * @param passwordHasher The default password hasher implementation.
   * @return The credentials provider.
   */
  @Provides
  def provideCredentialsProvider(
                                  authInfoService: AuthInfoRepository,
                                  passwordHasherRegistry: PasswordHasherRegistry): CredentialsProvider = {

    new RemoteCredentialsProvider(authInfoService, passwordHasherRegistry)
  }

  @Provides
  def provideClientTokenProvider() = {
    new ClientTokenProvider()
  }

  @Provides @Named("authenticator-cookie-signer")
  def provideAuthenticatorCookieSigner(configuration: Configuration): CookieSigner = {
    val config = configuration.underlying.as[JcaCookieSignerSettings]("silhouette.authenticator.cookie.signer")

    new JcaCookieSigner(config)
  }

  @Provides @Named("authenticator-crypter")
  def provideAuthenticatorCrypter(configuration: Configuration): Crypter = {
    val config = configuration.underlying.as[JcaCrypterSettings]("silhouette.authenticator.crypter")

    new JcaCrypter(config)
  }

  @Provides
  def provideHTTPLayer(client: WSClient): HTTPLayer = new PlayHTTPLayer(client)

  @Provides
  def provideAuthInfoRepository(): AuthInfoRepository = {

    new DelegableAuthInfoRepository()
  }

  @Provides
  def providePasswordHasherRegistry(passwordHasher: PasswordHasher): PasswordHasherRegistry = {
    new PasswordHasherRegistry(passwordHasher)
  }

}

#3

Hi,

I think you miss the following import.

import play.api.libs.concurrent.Execution.Implicits._

@see https://github.com/mohiva/play-silhouette-seed/blob/master/app/modules/SilhouetteModule.scala#L32

The PlayHttpLayer needs an implicit ExecutionContext provided.

Best regards,
Christian