【问题标题】:Error on porting a play 2.2 application to 2.3.2 version (Scala)将 play 2.2 应用程序移植到 2.3.2 版本时出错 (Scala)
【发布时间】:2026-02-23 04:10:01
【问题描述】:

我正在将 Play 2.2 应用程序移植到 Play 2.3 应用程序 (Scala)。 为此,我将安全社交版本更改为支持 Play 2.3 的 master-SNAPSHOT。 但是在编译时在我的游戏控制台中遇到错误。

怎么了?

[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:33: ambiguous implicit values:
[error]  both method request2lang in trait Controller of type (implicit request: play.api.mvc.RequestHeader)play.api.i18n.Lang
[error]  and value lang of type play.api.i18n.Lang
[error]  match expected type play.api.i18n.Lang
[error]     securesocial.views.html.Registration.signUp(form, token)
[error]                                                ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:44: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     securesocial.views.html.Registration.startSignUp(form)
[error]                                                     ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:55: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     securesocial.views.html.Registration.startResetPassword(form)
[error]                                                            ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:66: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     securesocial.views.html.Registration.resetPasswordPage(form, token)
[error]                                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:77: not found: type SecuredRequest
[error]   def getPasswordChangePage[A](implicit request: SecuredRequest[A], form: Form[ChangeInfo]): Html = {
[error]                                                  ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:78: Cannot find any HTTP Request Header here
[error]     securesocial.views.html.passwordChange(form)
[error]                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:99: not found: type Identity
[error]   def getAlreadyRegisteredEmail(user: Identity)(implicit request: RequestHeader): (Option[Txt], Option[Html]) = {
[error]                                       ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:100: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     (None, Some(securesocial.views.html.mails.alreadyRegisteredEmail(user)))
[error]                                                                     ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:110: not found: type Identity
[error]   def getWelcomeEmail(user: Identity)(implicit request: RequestHeader): (Option[Txt], Option[Html]) = {
[error]                             ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:111: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     (None, Some(securesocial.views.html.mails.welcomeEmail(user)))
[error]                                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:122: too many arguments for method apply: ()(implicit request: play.api.mvc.RequestHeader, implicit lang: play.api.i18n.Lang)play.twirl.api.HtmlFormat.Appendable in object unknownEmailNotice
[error]     (None, Some(securesocial.views.html.mails.unknownEmailNotice(request)))
[error]                                                                 ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:133: not found: type Identity
[error]   def getSendPasswordResetEmail(user: Identity, token: String)(implicit request: RequestHeader): (Option[Txt], Option[Html]) = {
[error]                                       ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:134: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     (None, Some(securesocial.views.html.mails.passwordResetEmail(user, token)))
[error]                                                                 ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:144: not found: type Identity
[error]   def getPasswordChangedNoticeEmail(user: Identity)(implicit request: RequestHeader): (Option[Txt], Option[Html]) = {
[error]                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:145: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     (None, Some(securesocial.views.html.mails.passwordChangedNotice(user)))
[error]                                                                    ^
[error] /Users/alberto/git/recommendation-system/app/security/CustomTemplatesPlugin.scala:155: could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment[_]
[error]     securesocial.views.html.notAuthorized()
[error]                                          ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:4: object Token is not a member of package securesocial.core.providers
[error] import securesocial.core.providers.Token
[error]        ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:5: object IdentityId is not a member of package securesocial.core
[error] import securesocial.core.IdentityId
[error]        ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:25: not found: type Identity
[error]   passwordInfo: Option[PasswordInfo] = None) extends Identity {
[error]                                                      ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:16: not found: type IdentityId
[error]   identityId: IdentityId,
[error]               ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:30: not found: type IdentityId
[error]   implicit val identityIdFormat = Json.format[IdentityId]
[error]                                               ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:35: Unapply of object LoginUser has no parameters. Are you using an empty case class?
[error]   implicit val storageFormat = Json.format[LoginUser]
[error]                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:39: not found: type IdentityId
[error]   implicit val identityIdFormat = Json.format[IdentityId]
[error]                                               ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:49: not found: type Identity
[error]   def apply(user: Identity): Option[LoginUser] = {
[error]                   ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:58: not found: type UserServicePlugin
[error] class UserService(application: Application) extends UserServicePlugin(application) {
[error]                                                     ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:59: not found: type Token
[error]   private var tokens = Map[String, Token]()
[error]                                    ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:69: not found: type Identity
[error]   def find(id: IdentityId): Option[Identity] = {
[error]                                    ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:69: not found: type IdentityId
[error]   def find(id: IdentityId): Option[Identity] = {
[error]                ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:72: No Json formatter found for type security.LoginUser. Try to implement an implicit Format for this type.
[error]     val futureUser = UserServiceLogin.find(Json.obj("identityId" -> Json.toJson(id))).one
[error]                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:86: not found: type Identity
[error]   def findByEmailAndProvider(email: String, providerId: String): Option[Identity] = {
[error]                                                                         ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:88: No Json formatter found for type security.LoginUser. Try to implement an implicit Format for this type.
[error]     val futureUser = UserServiceLogin.find(Json.obj("email" -> email)).one
[error]                                           ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:97: not found: type Identity
[error]   def save(user: Identity): Identity = {
[error]                             ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:97: not found: type Identity
[error]   def save(user: Identity): Identity = {
[error]                  ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:117: not found: type Token
[error]   def save(token: Token) = {
[error]                   ^
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:130: not found: type Token
[error]   def findToken(token: String): Option[Token] = {
[error]                                        ^
[error] /Users/alberto/git/recommendation-system/conf/routes:41: value resetPassword is not a member of securesocial.controllers.Registration
[error] GET       /reset/:token                 @securesocial.controllers.Registration.resetPassword(token)
[error] /Users/alberto/git/recommendation-system/conf/routes:36: value startResetPassword is not a member of securesocial.controllers.Registration
[error] POST      /signup                       @securesocial.controllers.Registration.startResetPassword
[error] /Users/alberto/git/recommendation-system/conf/routes:42: value handleResetPassword is not a member of securesocial.controllers.Registration
[error] POST      /reset/:token                 @securesocial.controllers.Registration.handleResetPassword(token)
[error] /Users/alberto/git/recommendation-system/conf/routes:49: value notAuthorized is not a member of securesocial.controllers.ProviderController
[error] GET       /not-authorized               @securesocial.controllers.ProviderController.notAuthorized            
[error] /Users/alberto/git/recommendation-system/conf/routes:36: value startResetPassword is not a member of securesocial.controllers.Registration
[error] POST      /signup                       @securesocial.controllers.Registration.startResetPassword
[error] /Users/alberto/git/recommendation-system/conf/routes:39: value startResetPassword is not a member of securesocial.controllers.Registration
[error] GET       /reset                        @securesocial.controllers.Registration.startResetPassword
[error] /Users/alberto/git/recommendation-system/conf/routes:40: value startResetPassword is not a member of securesocial.controllers.Registration
[error] POST      /reset                        @securesocial.controllers.Registration.startResetPassword
[error] /Users/alberto/git/recommendation-system/conf/routes:41: value resetPassword is not a member of securesocial.controllers.Registration
[error] GET       /reset/:token                 @securesocial.controllers.Registration.resetPassword(token)
[error] /Users/alberto/git/recommendation-system/conf/routes:42: value handleResetPassword is not a member of securesocial.controllers.Registration
[error] POST      /reset/:token                 @securesocial.controllers.Registration.handleResetPassword(token)
[error] /Users/alberto/git/recommendation-system/conf/routes:49: value notAuthorized is not a member of securesocial.controllers.ProviderController
[error] GET       /not-authorized               @securesocial.controllers.ProviderController.notAuthorized            
[error] /Users/alberto/git/recommendation-system/app/views/secure/login.scala.html:5: object Registry is not a member of package securesocial.core
[error] @import securesocial.core.AuthenticationMethod._
[error]                             ^
[error] /Users/alberto/git/recommendation-system/app/views/secure/login.scala.html:35: not found: value Registry
[error]         @defining( Registry.providers.all.values.filter( _.id != UsernamePassword) ) { externalProviders =>
[error]                    ^
[error] /Users/alberto/git/recommendation-system/app/views/secure/provider.scala.html:4: object Registry is not a member of package securesocial.core
[error] @import securesocial.core.IdentityProvider
[error]                              ^
[error] /Users/alberto/git/recommendation-system/app/views/secure/provider.scala.html:8: object RoutesHelper is not a member of package securesocial.core.providers.utils
[error] @import play.api.Logger
[error]      ^
[error] /Users/alberto/git/recommendation-system/app/views/secure/provider.scala.html:12: not found: value Registry
[error] @Registry.providers.get(providerId).map { provider =>
[error]  ^

谢谢 阿尔贝托

【问题讨论】:

    标签: scala playframework-2.0 securesocial


    【解决方案1】:

    在 2.1.4 和 master 之间,securesocial 发生了巨大的重构。

    整个插件系统已被删除以支持注入组件。 Identity 和 IdentityId 特征已被删除,现在 Actions 由您自己的类型参数化。

    UserService API 也发生了很大变化,从同步变为异步。

    文档目前仍在编写中。您必须查看 samples 以了解这一切如何结合在一起。

    @编辑

    关于视图模板: securesocial.controllers.ViewTemplates 现在是一个特征,您可以扩展它以覆盖相应的视图。那么您必须更改默认接线以引入您自己的视图提供程序。

    如果您查看 Global 中的示例,它会创建一个对象 MyRuntimeEnvironment

    object MyRuntimeEnvironment extends RuntimeEnvironment.Default[DemoUser] {
        override lazy val routes = new CustomRoutesService()
        override lazy val userService: InMemoryUserService = new InMemoryUserService()
        override lazy val eventListeners = List(new MyEventListener())
      }
    

    您可以创建自己的 ViewTemplate 并在此处覆盖它:

      object MyRuntimeEnvironment extends RuntimeEnvironment.Default[DemoUser] {
        override lazy val routes = new CustomRoutesService()
        override lazy val userService: InMemoryUserService = new InMemoryUserService()
        override lazy val eventListeners = List(new MyEventListener())
        override lazy val viewTemplates = new ViewTemplates{
    
          override def getLoginPage(form: Form[(String, String)], msg: Option[String])(implicit request: RequestHeader, lang: Lang): Html = ???
    
          override def getPasswordChangePage(form: Form[ChangeInfo])(implicit request: RequestHeader, lang: Lang): Html = ???
    
          override def getNotAuthorizedPage(implicit request: RequestHeader, lang: Lang): Html = ???
    
          override def getStartSignUpPage(form: Form[String])(implicit request: RequestHeader, lang: Lang): Html = ???
    
          override def getSignUpPage(form: Form[RegistrationInfo], token: String)(implicit request: RequestHeader, lang: Lang): Html = ???
    
          override def getResetPasswordPage(form: Form[(String, String)], token: String)(implicit request: RequestHeader, lang: Lang): Html = ???
    
          override def getStartResetPasswordPage(form: Form[String])(implicit request: RequestHeader, lang: Lang): Html = ???
        }
      }
    

    当然我不建议直接实现它,正确的方法是创建

    class CustomViewTemplates extends ViewTemplates{
    //...
    }
    

    然后

    override lazy val viewTemplates = new CustomViewTemplates()
    

    ViewTemplates 的默认实现在securesocial.core.ViewTemplates.Default

    每个“旧”插件(userService、authenticator store、IdGenerator、PasswordValidator、邮件模板等)都可以使用相同的机制,实际列表实际上可以从securesocial.core.RuntimeEnvironment.Default派生出来

    设计已更改为允许基于编译和运行时的依赖注入。它可能(不幸的是)必须再次使用 play 2.4 和 play 3.0 进行更改,这将使运行时 DI 成为框架的一等公民(同时仍然支持编译时注入)

    【讨论】:

    • 我在 github 存储库上看到了示例,但它对我没有帮助,因为不要使用 ViewTemplates
    • 感谢您的回答。我的问题在于 ViewTemplates 特征的实现,我在 github 上的示例项目中没有看到任何示例。编译器给了我找不到隐式值的错误。
    • 我添加了指向 ViewTemplates 的默认实现的链接...见 github.com/jaliss/securesocial/blob/master/module-code/app/…
    • 我已经解决了 ViewTemplates 的问题,现在我在使用 Registry 导致的视图包上出现了三个错误。我希望完成今晚的迁移。谢谢
    • 上面讨论的问题很多,能不能说的更准确点?在 java 示例 github.com/jaliss/securesocial/blob/master/samples/java/demo/… 中演示了创建自定义运行时环境,但是 securesocial 控制器本身是用 scala 编写的,而您可以在 java 中编写视图模板(因为 ViemTemplates 特征实际上是一个接口)它可能不是最理想的,因为您需要返回 scala 类型。随时提出具体问题并在此处链接,我会尽力提供帮助