I am currently digging into using Quartz in our play 2.4 application.
Initially, I tried initializing everything through Global
object, and everything worked perfectly.
Now, I an trying to move away from Global
utilize modules infrastructure.
Here is what I have until now.
JobSchedulingService
@Singleton
class JobSchedulingService @Inject()(lifecycle: ApplicationLifecycle) extends ClassLogger{
lazy val schedulerFactory = current.injector.instanceOf[StdSchedulerFactory]
lazy val scheduler = schedulerFactory.getScheduler
/**
* Let's make sure that scheduler shuts down properly
*/
lifecycle.addStopHook{ () =>
Future.successful{
if (scheduler.isStarted) {
scheduler.shutdown(true)
}
}
}
protected def init() : Unit = {
logger.info("Initializing scheduler...")
scheduler.start()
}
init()
}
SchedulerModule - here for initialization of the service above.
class SchedulerModule extends AbstractModule{
override def configure(): Unit = {
bind(classOf[JobSchedulingService]).asEagerSingleton
}
}
And in my application.conf
I added:
play.modules.enabled += "scheduling.modules.SchedulerModule"
It looks pretty strait forward. However, when the app starts I am getting an exception:
2016-03-23 00:07:42,173 INFO s.JobSchedulingService - Initializing scheduler... 2016-03-23 00:07:42,213 ERROR application -
! @6pfp72mh6 - Internal server error, for (GET) [/] ->
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) Error injecting constructor, java.lang.RuntimeException: There is no started application at scheduling.JobSchedulingService.(JobSchedulingService.scala:15) at scheduling.modules.SchedulerModule.configure(SchedulerModule.scala:11) (via modules: com.google.inject.util.Modules$OverrideModule -> scheduling.modules.SchedulerModule) while locating scheduling.JobSchedulingService
...
The thing is, in our app, the scheduler is based of off persistence job storage and should restart when the application restarts. Again, when I did it through Global
, it worked perfectly.
How do I get around this problem? What is the correct way to initialize an instance on startup?
Thanks,
You should probably be using the dependency injection for everything. Inject the scheduler like..
class JobSchedulingService @Inject()(lifecycle: ApplicationLifecycle, schedulerFactory: StdSchedulerFactory) extends ClassLogger{
lazy val scheduler = schedulerFactory.getScheduler