我与Play 2.6's Scala documentation and sample code for creating non-blocking actions一起关注,并且遇到了一些运行时问题。我已经使用Scala template(sbt new playframework/play-scala-seed.g8
)创建了一个新的Play应用程序。
Play文档建议使用的代码应在新控制器上工作(此代码是从Play文档页面逐字记录的,其中还包括一些额外的导入信息):
// some imports added by me to get the code to compile
import javax.inject.Inject
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import akka.actor.ActorSystem
import play.api.libs.concurrent.CustomExecutionContext
import play.api.mvc._
import play.api.mvc.ControllerComponents
// end imports added by me
import play.api.libs.concurrent.CustomExecutionContext
trait MyExecutionContext extends ExecutionContext
class MyExecutionContextImpl @Inject()(system: ActorSystem)
extends CustomExecutionContext(system, "my.executor") with MyExecutionContext
class HomeController @Inject()(myExecutionContext: MyExecutionContext, val controllerComponents: ControllerComponents) extends BaseController {
def index = Action.async {
Future {
// Call some blocking API
Ok("result of blocking call")
}(myExecutionContext)
}
}
然后,根据documentation for using other thread pools,我在应用程序的my.executor
文件中定义了application.conf
线程池:
my.executor {
fork-join-executor {
parallelism-factor = 20.0
parallelism-max = 200
}
}
我应该注意,我不不想使用默认执行上下文,因为我想为在单独的上下文中运行期货做准备,该上下文可能用于有限的资源,例如数据库连接池。
所有这些都可以使用sbt compile
进行编译。但是,当我使用sbt run
运行此程序并在网络浏览器中访问我的应用程序时,出现此错误:
CreationException:无法创建注射器,请参见以下错误:
1)没有为controllers.MyExecutionContext绑定的实现。 在定位controller.MyExecutionContext时 用于controllers.NewController的第一个参数。(NewController.scala:17) 在定位controller.NewController时 用于router.Routes的第二个参数。(Routes.scala:29) 在play.api.inject.RoutesProvider $ .bindingsFromConfiguration(BuiltinModule.scala:121)处: 绑定(路由器类。路由到自身)(通过模块:com.google.inject.util.Modules $ OverrideModule-> play.api.inject.guice.GuiceableModuleConversions $$ anon $ 1)
我过去使用过Play 2.3,并且知道当您定义对象的实例(通过@Singleton
或在模块中)时,依赖项注入有效。但是,Play 2.6's documentation on DI表示“ Guice可以在其构造函数上使用@Inject自动实例化任何类,而不必显式绑定它。此功能在Guice文档中有更详细的描述,这称为及时绑定。 “
我的问题是:要使这项工作有效,我需要在Play自己的示例中添加哪些特定的代码行或配置?为什么?
答案 0 :(得分:1)
在Scala依赖注入文档页面的Binding Annotations部分中进一步阅读时,我找到了一种可能的解决方案。特别指出:
将实现绑定到接口的最简单方法是使用Guice @ImplementedBy批注。
因此,通过将其添加到我的MyExecutionContext
trait
中,如下所示:
import com.google.inject.ImplementedBy
@ImplementedBy(classOf[MyExecutionContextImpl])
trait MyExecutionContext extends ExecutionContext
实例化MyExecutionContextImpl
的实例并将其正确注入控制器。
可惜的是,non-blocking action文档的示例代码中没有列出此@ImplementedBy
注释!