Scala Play 2.5如何使Java的上下文/会话/请求可供视图访问?

时间:2016-12-21 23:06:26

标签: scala playframework play-authenticate

我正在开发这个Scala play-authenticate-usage-scala项目,我在Java框架play-authenticate之上构建(我知道,生活并不完美......)。在运行应用程序时,我看到了下面的例外情况。

仔细检查堆栈跟踪会引导我进入使用views._providerPartial.scala.html模板的视图forProviders.scala.html,该模板依次使用依赖于Java的Play play.mvc.Http.{ Session, Context, etc}的类,因此,错误,因为我的示例应用程序带来了Scala play.api.mvc._

我知道我可以在Scala中做到:

import play.core.j.JavaHelpers

val jContext : play.mvc.Http.Context = JavaHelpers.createJavaContext(request)
val jSession : play.mvc.Http.Session = context.session() 

问题是如何才能使上述隐含的视图可用于该视图。

[error] application - 

! @72ef8b5j8 - Internal server error, for (GET) [/login] ->

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[RuntimeException: There is no HTTP Context available from here.]]
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:293)
    at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:220)
    at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
    at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
    at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:100)
    at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
    at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
    at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:346)
    at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:345)
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
Caused by: java.lang.RuntimeException: There is no HTTP Context available from here.
    at play.mvc.Http$Context.current(Http.java:62)
    at play.mvc.Http$Context$Implicit.session(Http.java:330)
    at com.feth.play.module.pa.views.html.forProviders_Scope0$forProviders$$anonfun$apply$1.apply(forProviders.template.scala:37)
    at com.feth.play.module.pa.views.html.forProviders_Scope0$forProviders$$anonfun$apply$1.apply(forProviders.template.scala:35)
    at play.twirl.api.TemplateMagic$.defining(TemplateMagic.scala:13)
    at com.feth.play.module.pa.views.html.forProviders_Scope0$forProviders.apply(forProviders.template.scala:35)
    at views.html._providerPartial_Scope0$_providerPartial.apply(_providerPartial.template.scala:38)
    at views.html.login_Scope0$login_Scope1$login.apply(login.template.scala:74)
    at controllers.Application$$anonfun$4$$anonfun$apply$4.apply(Application.scala:57)
    at controllers.Application$$anonfun$4$$anonfun$apply$4.apply(Application.scala:57)

更新我尝试了以下操作,但没有成功。基本上Java方面期望ThreadLocal中的所有这些。特定ThreadLocal实例公开位于play.mvc.Http.Context.current。因此我准备了一个名为_adaptScalaToJava.scala.html的模板助手:

@import be.objectify.deadbolt.scala._
@import play.core.j.JavaHelpers

@()(implicit request: AuthenticatedRequest[Any])

@play.mvc.Http.Context.current.set(JavaHelpers.createJavaContext(request))

它直接在当前线程中设置jContext,并使用如下:

@_adaptScalaToJava
@forProviders(playAuth, skipCurrent) { p =>
    <li>
    @if(p.getKey() == "openid") {
        <a href="javascript:void(0);" onclick="askOpenID('@p.getUrl()');">
    } else {
        <a href="@p.getUrl()">
    }
    @_providerIcon(p.getKey())</a>
    </li>
}

但即使编译发现仍然会触发相同的异常......

1 个答案:

答案 0 :(得分:0)

在令人不安的代码解决问题之前只放置这一行:

@if (play.mvc.Http.Context.current.get() == null) { 
    @play.mvc.Http.Context.current.set(play.core.j.JavaHelpers.
         createJavaContext(request)) 
} 

试图让它变得更干净,即它不会一直重置,对我来说,为什么它不会起作用仍然是个谜。

play.mvc.Http.Context.current

好像null不是@play.core.j.JavaHelpers.withContext(request) { jContext => @forProviders(playAuth, skipCurrent) { p => ... } } ...底线是我需要连接IDE并调试代码。

更新实际上这是正式的方法:

{{1}}