Play 2.4 Adding Module instead of Plugin

我是研究僧i 提交于 2019-12-23 03:49:23

问题


I have a Play 2.3 app that I'm migrating to Play 2.4 and I'm working on one of the warnings which is about migrating the plugin's to modules. I'm following this documentation here:

https://www.playframework.com/documentation/2.4.x/PluginsToModules

I have now a couple of questions in my application that has some Akka actors. So far here is what I did with the plugins:

  class MyPlugin extends Plugin {

    // I get the current Application
    val app = play.api.Play.current

    // On start of the plugin, I call my initializers
    def onStart: Unit = {
      super.onStart()
      doInitialize(app)
    }
  }

Now in my doInitialize routine, I do the initialization of the different services that I need. I later expose these services as a trait and I mix this trait on the places where I need the service references. So for example., my controller looks like:

object Application extends Controller with MyServices {

  ....
}

where MyServices is

trait MyServices {

  def myActorRef: ActorRef
  ...
  ...
}

How should this setup now be migrated to using Modules with little impact to the overall application? It is also not clear as to where I should put my onStart method contents when I migrate from Plugin to Module!

Edit: I tried the following:

sealed trait MyComp
class MyCompImpl @Inject() (lifecycle: ApplicationLifecycle) extends MyComp {
  val application = MyConfig(play.api.Play.current)

  // initialize upon start
  Initializer.doInitialize(application)

  // destroy upon stop
  lifecycle.addStopHook(() => {
    Future.successful { Initializer.destroyConfig(application) }
  })
}

I have the module defined as below:

class MyModule extends Module {

  override def bindings(environment: play.api.Environment, configuration: Configuration): Seq[Binding[_]] = {
    logger.info(s"registering bindings")
    Seq(
      bind[MyComp].to[MyCompImpl].eagerly()
    )
  }
}

This now fails with the reason:

CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.RuntimeException: There is no started application
  at com.config.MyCompImpl.<init>(MyModule.scala:25)
  while locating com.config.MyCompImpl

It is becoming a pain in the *** with each upgrade to a Play application's to newer versions!


回答1:


You need to take in to account one more change in 2.4: "Removing GlobalSettings":

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.

on this page - https://www.playframework.com/documentation/2.4.x/PluginsToModules - you have:

bind[MyComponent].to[MyComponentImpl]

in your example you need to use

bind[MyComponent].to[MyComponentImpl].asEagerSingleton

and the code doInitialize(app) must be run in the constructor of MyComponentImpl like

class MyComponentImpl extends MyComponent {
  initialize() 
  def initialize() = {
     //initialize your app
  }
}



回答2:


I managed to solve this as below:

sealed trait MyComp
class MyCompImpl @Inject() (app: Application, lifecycle: ApplicationLifecycle) extends MyComp {
  val application = Myconfig(app)

  // initialize upon start
  Initializer.doInitialize(application)

  // destroy upon stop
  lifecycle.addStopHook(() => {
    Future.successful { Initializer.destroyConfig(application) }
  })
}


来源:https://stackoverflow.com/questions/33195850/play-2-4-adding-module-instead-of-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!