¿Cómo realizo una acción en el inicio del servidor en Scala Play Framework?
playframework startup (1)
Tengo un archivo de configuración servers.conf
en mi directorio conf/
que es leído por mi ServerController cada vez que se golpea la ruta /servers
. Esto no es eficaz porque requiere que se vuelva a leer el archivo de configuración en cada golpe sucesivo cuando el archivo no cambie. Además, si hay problemas con el archivo de configuración, puedo decirle al usuario lo antes posible en lugar de lanzar una excepción en un golpe de página.
Actualmente tengo esto en mi ServerController.scala
:
case class Server(ip: String, port: String)
/**
* This controller creates an `Action` to handle HTTP requests to the
* application''s server page.
*/
@Singleton
class ServerController @Inject() extends Controller {
/**
* Create an Action to render an HTML page with a the list of servers.
* The configuration in the `routes` file means that this method
* will be called when the application receives a `GET` request with
* a path of `/servers`.
*/
def index = Action {
val serverList = ConfigFactory.load().getConfigList("servers")
val servers: List[Server] = serverList match {
case null => Nil
case _ => serverList map { s =>
Server(s.getString("ip"), s.getString("port"))
} filter { s =>
s.ip != null && s.port != null
}.toList
}
Ok(views.html.servers(servers))
}
}
Mi objetivo es que el servidor lea el archivo de configuración en el inicio y pase la lista de servidores al ServerController cuando se golpea la ruta si no hay problemas para leer el archivo de configuración. Si hay problemas, quiero que se lance una excepción inmediatamente.
Sin embargo, parece que no puedo encontrar un punto de entrada para mi aplicación, así que no sé cómo realizar acciones en el inicio.
¿Alguien sabe como hacer esto? Estoy usando Play 2.5.x.
Si está utilizando la versión más reciente de Play, busca en el inicio cualquier clase llamada Module
que se encuentre en el paquete raíz (es decir, no hay una definición de package
en la parte superior del archivo). Aquí hay un ejemplo tomado de la última plantilla de Activator para Play 2.5.x, que he modificado para demostrar que ejecutamos el código en el inicio y cierre de la aplicación:
En services/Say.scala
, este sería un servicio simple para decir "¡Hola!" en el inicio y "¡Adiós!" cuando la aplicación se apaga:
package services
import javax.inject._
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future
trait Say {
def hello(): Unit
def goodbye(): Unit
}
@Singleton
class SayImpl @Inject() (appLifecycle: ApplicationLifecycle) extends Say {
override def hello(): Unit = println("Hello!")
override def goodbye(): Unit = println("Goodbye!")
// You can do this, or just explicitly call `hello()` at the end
def start(): Unit = hello()
// When the application starts, register a stop hook with the
// ApplicationLifecycle object. The code inside the stop hook will
// be run when the application stops.
appLifecycle.addStopHook { () =>
goodbye()
Future.successful(())
}
// Called when this singleton is constructed (could be replaced by `hello()`)
start()
}
En Module.scala,
import com.google.inject.AbstractModule
import services._
/**
* This class is a Guice module that tells Guice how to bind several
* different types. This Guice module is created when the Play
* application starts.
* Play will automatically use any class called `Module` that is in
* the root package. You can create modules in other locations by
* adding `play.modules.enabled` settings to the `application.conf`
* configuration file.
*/
class Module extends AbstractModule {
override def configure() = {
// We bind the implementation to the interface (trait) as an eager singleton,
// which means it is bound immediately when the application starts.
bind(classOf[Say]).to(classOf[SayImpl]).asEagerSingleton()
}
}
Algunos recursos adicionales que pueden resultarle útiles son la documentación de inyección de dependencia (DI) de Scala y la documentación de Guice . Guice es el marco DI predeterminado utilizado por Play.