playframework 2.4 GlobalSettings onStart 弃用
playframework 2.4 GlobalSettings onStart Deprecated
我正在将我的应用程序从 Play 2.3 迁移到 2.4。
在我的 GlobalSettings 中的 2.3 应用程序中,我必须使用 slick 访问数据库以创建 postgres 数据库函数。
由于 GlobalSettings 在 2.4 中已弃用,替代方法是使用 Eager Bindings:
https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection#Eager-bindings
像这样:
class MyModule extends AbstractModule {
def configure() = {
db.withSession { implicit ss =>
StaticQuery.update("""CREATE OR REPLACE FUNCTION ... """).execute
}
}
}
但这给了我错误:
java.lang.ExceptionInInitializerError:
core.includes$.<init>(includes.scala:14)
core.includes$.<clinit>(includes.scala)
Application$$anonfun$configure.apply(Application.scala:17)
Application$$anonfun$configure.apply(Application.scala:15)
scala.slick.backend.DatabaseComponent$DatabaseDef$class.withSession(DatabaseComponent.scala:34)
scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon.withSession(JdbcBackend.scala:61)
modules.jdbc.Database$$anonfun$withSession.apply(Database.scala:14)
modules.jdbc.Database$$anonfun$withSession.apply(Database.scala:14)
Application.configure(Application.scala:15)
com.google.inject.AbstractModule.configure(AbstractModule.java:62)
com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
com.google.inject.spi.Elements.getElements(Elements.java:110)
com.google.inject.util.Modules$OverrideModule.configure(Modules.java:177)
com.google.inject.AbstractModule.configure(AbstractModule.java:62)
com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
com.google.inject.spi.Elements.getElements(Elements.java:110)
com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:138)
com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104)
com.google.inject.Guice.createInjector(Guice.java:96)
com.google.inject.Guice.createInjector(Guice.java:73)
com.google.inject.Guice.createInjector(Guice.java:62)
play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:126)
play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:93)
play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
有人知道我该如何解决这个问题吗?谢谢
引用自https://www.playframework.com/documentation/2.4.2/GlobalSettings:
GlobalSettings.beforeStart and GlobalSettings.onStart: Anything that needs to happen on start up should now be happening in the constructor of a dependency injected class. A class will perform its initialisation when the dependency injection framework loads it. If you need eager initialisation (because you need to execute some code before the application is actually started), define an eager binding.
如您所见,只有在应用程序启动之前需要发生某些事情时才能使用急切绑定,这不适用于您的情况,因为db.withSession需要一个启动的应用程序上下文。这就是发生异常的原因(顺便说一句,严格来说,您没有以适当的方式使用急切绑定)。
那么你怎样才能达到目标呢?答案在引文的前两句。
首先,你必须定义如下内容:
@Singleton
class DatabaseService {
db.withSession { implicit ss =>
StaticQuery.update("""CREATE OR REPLACE FUNCTION ... """).execute
}
}
然后如果将DatabaseService注入到另一个单例中class(你最好将其注入到另一个单例中class,否则代码可能会被调用多次),后面的class被Guice初始化,调用DatabaseService构造函数中的代码(因为DatabaseService是Guice先初始化的,作为后面class的依赖)。
例如,您可以将其注入到控制器中:
@Singleton
class Application @Inject() (dbService: DatabaseService) extends Controller {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
}
然后如果有人访问索引页面,您的代码将被执行。
编辑:
我发现另一个关于该主题的 Whosebug post,请看这里:PlayFramework 2.4 run some code after application has started。它在应用程序启动后找出正确的方法 运行 代码,同时仍然使用急切绑定。 :)
如果您依赖于 ActorSystem,只需将 actorSystem: ActorSystem 注入您的 class,如下所示:
@Singleton
class QuartzSchedulerService @Inject() (configuration: Configuration,
actorSystem: ActorSystem,
@Named("library.actors.ApiExecutionRecorderRouter") apiExecutionRecorderRouter: ActorRef
) {
val scheduler = QuartzSchedulerExtension(actorSystem)
scheduler.schedule("QuartzSchedulerTest", apiExecutionRecorderRouter, "Start")
}
我正在将我的应用程序从 Play 2.3 迁移到 2.4。
在我的 GlobalSettings 中的 2.3 应用程序中,我必须使用 slick 访问数据库以创建 postgres 数据库函数。
由于 GlobalSettings 在 2.4 中已弃用,替代方法是使用 Eager Bindings:
https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection#Eager-bindings
像这样:
class MyModule extends AbstractModule {
def configure() = {
db.withSession { implicit ss =>
StaticQuery.update("""CREATE OR REPLACE FUNCTION ... """).execute
}
}
}
但这给了我错误:
java.lang.ExceptionInInitializerError:
core.includes$.<init>(includes.scala:14)
core.includes$.<clinit>(includes.scala)
Application$$anonfun$configure.apply(Application.scala:17)
Application$$anonfun$configure.apply(Application.scala:15)
scala.slick.backend.DatabaseComponent$DatabaseDef$class.withSession(DatabaseComponent.scala:34)
scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon.withSession(JdbcBackend.scala:61)
modules.jdbc.Database$$anonfun$withSession.apply(Database.scala:14)
modules.jdbc.Database$$anonfun$withSession.apply(Database.scala:14)
Application.configure(Application.scala:15)
com.google.inject.AbstractModule.configure(AbstractModule.java:62)
com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
com.google.inject.spi.Elements.getElements(Elements.java:110)
com.google.inject.util.Modules$OverrideModule.configure(Modules.java:177)
com.google.inject.AbstractModule.configure(AbstractModule.java:62)
com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
com.google.inject.spi.Elements.getElements(Elements.java:110)
com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:138)
com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104)
com.google.inject.Guice.createInjector(Guice.java:96)
com.google.inject.Guice.createInjector(Guice.java:73)
com.google.inject.Guice.createInjector(Guice.java:62)
play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:126)
play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:93)
play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
有人知道我该如何解决这个问题吗?谢谢
引用自https://www.playframework.com/documentation/2.4.2/GlobalSettings:
GlobalSettings.beforeStart and GlobalSettings.onStart: Anything that needs to happen on start up should now be happening in the constructor of a dependency injected class. A class will perform its initialisation when the dependency injection framework loads it. If you need eager initialisation (because you need to execute some code before the application is actually started), define an eager binding.
如您所见,只有在应用程序启动之前需要发生某些事情时才能使用急切绑定,这不适用于您的情况,因为db.withSession需要一个启动的应用程序上下文。这就是发生异常的原因(顺便说一句,严格来说,您没有以适当的方式使用急切绑定)。
那么你怎样才能达到目标呢?答案在引文的前两句。
首先,你必须定义如下内容:
@Singleton
class DatabaseService {
db.withSession { implicit ss =>
StaticQuery.update("""CREATE OR REPLACE FUNCTION ... """).execute
}
}
然后如果将DatabaseService注入到另一个单例中class(你最好将其注入到另一个单例中class,否则代码可能会被调用多次),后面的class被Guice初始化,调用DatabaseService构造函数中的代码(因为DatabaseService是Guice先初始化的,作为后面class的依赖)。
例如,您可以将其注入到控制器中:
@Singleton
class Application @Inject() (dbService: DatabaseService) extends Controller {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
}
然后如果有人访问索引页面,您的代码将被执行。
编辑:
我发现另一个关于该主题的 Whosebug post,请看这里:PlayFramework 2.4 run some code after application has started。它在应用程序启动后找出正确的方法 运行 代码,同时仍然使用急切绑定。 :)
如果您依赖于 ActorSystem,只需将 actorSystem: ActorSystem 注入您的 class,如下所示:
@Singleton
class QuartzSchedulerService @Inject() (configuration: Configuration,
actorSystem: ActorSystem,
@Named("library.actors.ApiExecutionRecorderRouter") apiExecutionRecorderRouter: ActorRef
) {
val scheduler = QuartzSchedulerExtension(actorSystem)
scheduler.schedule("QuartzSchedulerTest", apiExecutionRecorderRouter, "Start")
}