【问题标题】:playframework 2.4 GlobalSettings onStart Deprecatedplayframework 2.4 GlobalSettings onStart 已弃用
【发布时间】:2015-10-05 22:29:39
【问题描述】:

我正在将我的应用从 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$1.apply(Application.scala:17)
     Application$$anonfun$configure$1.apply(Application.scala:15)
     scala.slick.backend.DatabaseComponent$DatabaseDef$class.withSession(DatabaseComponent.scala:34)
     scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon$4.withSession(JdbcBackend.scala:61)
     modules.jdbc.Database$$anonfun$withSession$1.apply(Database.scala:14)
     modules.jdbc.Database$$anonfun$withSession$1.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)

有没有人知道我该如何解决这个问题?谢谢。

【问题讨论】:

    标签: playframework playframework-2.4


    【解决方案1】:

    根据https://www.playframework.com/documentation/2.4.2/GlobalSettings的报价:

    GlobalSettings.beforeStart 和 GlobalSettings.onStart:启动时需要发生的任何事情现在都应该在依赖注入类的构造函数中发生。一个类将在依赖注入框架加载它时执行它的初始化。如果您需要预先初始化(因为您需要在应用程序实际启动之前执行一些代码),请定义一个预先绑定。

    如您所见,只有在应用程序启动之前需要发生某些事情时才能使用急切绑定,这不适用于您的情况,因为 db.withSession 需要启动的应用程序上下文。这就是发生异常的原因(BTW 严格来说,您没有以适当的方式使用急切绑定)。

    那么如何才能实现目标呢?答案就在引文的前两句。

    首先,您必须定义如下内容:

    @Singleton
    class DatabaseService {
        db.withSession { implicit ss =>
          StaticQuery.update("""CREATE OR REPLACE FUNCTION ... """).execute
        }
    }
    

    然后如果你将DatabaseService注入到另一个单例类中(最好注入到另一个单例类中,否则代码可能会被多次调用),而后面的类被Guice初始化,那么调用DatabaseService的构造函数(因为DatabaseService首先被Guice初始化为后面类的依赖)。

    例如,您可以将其注入到控制器中:

    @Singleton
    class Application @Inject() (dbService: DatabaseService) extends Controller {
      def index = Action {
        Ok(views.html.index("Your new application is ready."))
      }
    }
    

    然后如果有人访问索引页,你的代码就会被执行。

    编辑:

    我发现另一个关于该主题的 stackoverflow 帖子,请参阅此处:PlayFramework 2.4 run some code after application has started。它找出了在应用程序启动后运行代码的正确方法,同时仍然使用急切绑定。 :)

    如果你依赖于 ActorSystem,只需将 actorSystem: ActorSystem 注入你的类,如下所示:

    @Singleton
    class QuartzSchedulerService @Inject() (configuration: Configuration,
                                            actorSystem: ActorSystem,
                                            @Named("library.actors.ApiExecutionRecorderRouter") apiExecutionRecorderRouter: ActorRef
                                            ) {
      val scheduler = QuartzSchedulerExtension(actorSystem)
      scheduler.schedule("QuartzSchedulerTest", apiExecutionRecorderRouter, "Start")
    }
    

    【讨论】:

    猜你喜欢
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多