[Play 2.4] Initialise code after Application has started

5,500 views
Skip to first unread message

Eddie

unread,
Jun 28, 2015, 9:09:28 PM6/28/15
to play-fr...@googlegroups.com
Hi all,

Before Play 2.4, we had onStart in GlobalSetttings which allowed us to execute some code AFTER the application started.
Since Play 2.4 and the dependency injection orientation, it's recommended to for a class to perform its initialization in it's constructor. The eager binding works well when we want execute some code on start up without injecting the object anywhere, but it's happening before Application is really started.

Is there a way to do the same thing, but after the application started ? Some of the initialization I have in my case need the application to be started. And I don't want to inject those objects in a controller, just to get the constructor called after the application started....

Thanks for your help

James Roper

unread,
Jun 29, 2015, 9:05:19 PM6/29/15
to play-framework
On 29 June 2015 at 11:09, Eddie <edouard...@gmail.com> wrote:
Hi all,

Before Play 2.4, we had onStart in GlobalSetttings which allowed us to execute some code AFTER the application started.
Since Play 2.4 and the dependency injection orientation, it's recommended to for a class to perform its initialization in it's constructor. The eager binding works well when we want execute some code on start up without injecting the object anywhere, but it's happening before Application is really started.

Is there a way to do the same thing, but after the application started ? Some of the initialization I have in my case need the application to be started.

A Play application doesn't do anything.  It consists of many components that do things.  So it doesn't make sense to say "I depend on an application being started", since it doesn't make sense to depend on something that does nothing.  What is likely is that you depend on some components that the application starts.  If that's the case, then simply make those components dependencies of your component.

Also, if you really want to depend on the whole application, then @Inject it into your component.  Then you will get a fully initialised application.

And I don't want to inject those objects in a controller, just to get the constructor called after the application started....

Thanks for your help

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/55fb2ed3-bd05-48ad-b5ef-0653dd139e15%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
James Roper
Software Engineer

Typesafe – Build reactive apps!
Twitter: @jroper

Eddie

unread,
Jun 30, 2015, 3:48:55 AM6/30/15
to play-fr...@googlegroups.com
Hi James,

Thanks for your help, but I'm still not sure how to proceed.
Let me try to be more clear with an example: I have a service initializing some background tasks with Akka.system(). This initialization only needs to be done once, but I can't use an eager singleton because the instance would be created when the application starts up, and at this point Akka.system() is not available yet.

What I'm looking for is a way to add a start hook on the ApplicationLifecyle, just like we have a addStopHook method on the ApplicationLifecycle class.

Thanks for your help,

Christian Kaps

unread,
Jun 30, 2015, 8:15:55 AM6/30/15
to play-fr...@googlegroups.com
Hi,

I would also be interested in this topic. We follow the same approach to initialize some Akka jobs on application start.

Best regards,
Christian

Eddie

unread,
Jun 30, 2015, 10:20:57 PM6/30/15
to play-fr...@googlegroups.com

Hi Christian,

Right now, we moved away 99% of the code we had in GlobalSetting (onStop, onError, onRequest etc...).
But because I can't find a way to add a start hook on the application life cycle, we still have to use Global but just the onstart(Application app) method.

We use app.injector() .instanceOf method to initialize a couple of stuff and that's all.

Cheers,

Christian Kaps

unread,
Jul 1, 2015, 2:38:00 AM7/1/15
to play-fr...@googlegroups.com
Hi Eddie,

Thank you for your answer! Although, it would be nice if Play provides a startup hook without the Global object.

@James

If it's worth to create an issue for this?

Cheers,
Christian

p...@semlab.nl

unread,
Jul 1, 2015, 3:57:27 AM7/1/15
to play-fr...@googlegroups.com
The constructor itself is the startup hook. Any injected argument to your constructor will be initialized before the constructor is called. If you want what was once `Akka.system()`, just add a dependency to `ActorSystem` and it should work.

So:

import javax.inject.Inject;

import akka.actor.ActorSystem;

class ExampleClass
{
   
@Inject
   
public ExampleClass(ActorSystem actorSystem)
   
{
        actorSystem
.actorOf(SomeActor.props());
   
}
}



Op woensdag 1 juli 2015 08:38:00 UTC+2 schreef Christian Kaps:

Christian Kaps

unread,
Jul 1, 2015, 4:40:40 AM7/1/15
to play-fr...@googlegroups.com
Hi,

Please correct me if I'm wrong, but you need an entry point in which your dependencies will be injected. In Play the entry point is the controller instance which gets initialized if a route was requested on this controller. I cannot find any information regarding the lifecycle of a controller, so I assume that controllers are instantiated the same as all other dependency injected components. The documentation says:
  • New instances are created every time a component is needed. If a component is used more than once, then, by default, multiple instances of the component will be created. If you only want a single instance of a component then you need to mark it as a singleton.

It sounds like that on every request a new controller instance will be created. This means also that my dependencies get injected on every request. As you can see this is not a viable option for an application wide startup hook, because it isn't guaranteed that my tasks get executed on application startup and it's also not guaranteed that it will be executed only once. Even if the controller will be instantiated once if an action will be called on it, then it isn't guaranteed that the controller will be ever issued. 

Best regards,
Christian

Igmar Palsenberg

unread,
Jul 2, 2015, 3:03:07 AM7/2/15
to play-fr...@googlegroups.com
Please correct me if I'm wrong, but you need an entry point in which your dependencies will be injected. In Play the entry point is the controller instance which gets initialized if a route was requested on this controller. I cannot find any information regarding the lifecycle of a controller, so I assume that controllers are instantiated the same as all other dependency injected components. The documentation says:
  • New instances are created every time a component is needed. If a component is used more than once, then, by default, multiple instances of the component will be created. If you only want a single instance of a component then you need to mark it as a singleton.

It sounds like that on every request a new controller instance will be created. This means also that my dependencies get injected on every request. As you can see this is not a viable option for an application wide startup hook, because it isn't guaranteed that my tasks get executed on application startup and it's also not guaranteed that it will be executed only once. Even if the controller will be instantiated once if an action will be called on it, then it isn't guaranteed that the controller will be ever issued. 

Then make it a singleton. We use this frequently in controller / bootstrap code.


Igmar

p...@semlab.nl

unread,
Jul 2, 2015, 3:53:03 AM7/2/15
to play-fr...@googlegroups.com
As Igmar said, make it a Singleton to ensure Guice will only create one instance. I don't get the last bit of your comment. The dependency injection insures all dependencies are initialized and passed on when a class gets instantiated. For controllers this happens when they're called on from a route, for other classes this happens when you inject them somewhere, explicitly call new or make them eager (in which case they get instantiated at startup).

Taking previous code and making it Singleton:
import javax.inject.Inject;
import javax.inject.Singleton;

import akka.actor.ActorSystem;

@Singleton
class ExampleClass implements ExampleInterface

{
   
@Inject
   
public ExampleClass(ActorSystem actorSystem)
   
{
        actorSystem
.actorOf(SomeActor.props());
   
}
}

To make it eager, you'll need to do some extra plumbing (I really dislike this extra boilerplate myself, but it is what it is):

ExampleClass.java
import javax.inject.Inject;
import javax.inject.Singleton;

import akka.actor.ActorSystem;

@Singleton
class ExampleClass
{
   
@Inject
   
public ExampleClass(ActorSystem actorSystem)
   
{
        actorSystem
.actorOf(SomeActor.props());
   
}
}

ExampleModule
import com.google.inject.AbstractModule;

class ExampleModule extends AbstractModule
{
   
@Override
   
protected void configure()
   
{
        bind
(ExampleInterface.class).to(ExampleClass.class).asEagerSingleton();
   
}
}

ExampleInterface.java
interface ExampleInterface {}





Op woensdag 1 juli 2015 10:40:40 UTC+2 schreef Christian Kaps:

Johan Dahlberg

unread,
Jul 2, 2015, 12:12:59 PM7/2/15
to play-fr...@googlegroups.com
I also have a few actors that is started in onStart and are used for scheduled reports for example. Doesn't this solution demand that I inject them in a controller so that they are created on the first request? Because then I need to add the injection to every controller which feels like a very ugly solution. Isn't there any way of binding it so they are started when I start the application (e.g. sbt ~run). Or maybe I don't understand you correctly.

/Johan

Christian Schmitt

unread,
Jul 2, 2015, 4:17:37 PM7/2/15
to play-fr...@googlegroups.com
if you add them with bindActor they will be blinded Eagerly which means ON Startup.
Currently I do that to create a Index on Elasticsearch if he doesn't exists and that works fine.

Not sure whats this thread is all about. If you have some code in the constructor of a eagerly binded class it will run when ALL dependencies of that constructor are resolved, but it will still run on startup, so you could control which features needs to be started to run your code.

Johan Dahlberg

unread,
Jul 2, 2015, 4:57:06 PM7/2/15
to play-fr...@googlegroups.com
Ah, I think I understand now. So the three snippets in the post before mine is everything that needs to be added to make it load on startup.

/Johan

Santosh Kumar

unread,
Jul 2, 2015, 5:07:06 PM7/2/15
to play-fr...@googlegroups.com
I created a unit-test and Guice does its magic for the Eager singleton as shown in the trace:



trait
StartupClass {
 
def dummyCounter = 100
}


class StartupClassImpl extends StartupClass {
  println("Eager Singleton Initialized during startup.. perform startup related tasks like Akka ActorSystem management etc....")
}


@RunWith(classOf[org.specs2.runner.JUnitRunner])
class StartupClassSpec extends PlaySpecification with Mockito with AkkaTestkitSpecs2Support {
  sequential


 
"A Startup Class " should {
   
"must be available from Injector " in new MyContext {
     
new WithApplication(application) {
        val m
= application.injector
        val y
= application.injector.instanceOf[StartupClass]
        y
.dummyCounter mustEqual 100
     
}
   
}
 
}


  trait
MyContext extends TestContext {


    val testModule
= new AbstractModule with AkkaGuiceSupport {
     
def configure = {
        bind
(classOf[StartupClass]).to(classOf[StartupClassImpl]).asEagerSingleton();
     
}
   
}


   
/**
     * The application.
     */

    lazy val application
= new GuiceApplicationBuilder()
     
.overrides(new FakeModule)
     
.overrides(testModule)
     
.build()
 
}


}

Here is the console output:


SLF4J
: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J
: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
[info] p.a.l.c.ActorSystemProvider - Starting application default Akka system: application
Eager Singleton Initialized during startup.. perform startup related tasks like Akka ActorSystem management etc....
creating blogdaoactor
[info] p.a.l.c.ActorSystemProvider - Shutdown application default Akka system: application


I didn't have to make a HHTP Request to the application in my unit test. All plumbing in there in DI....

Cristi Prodan

unread,
Jul 3, 2015, 2:26:17 AM7/3/15
to play-fr...@googlegroups.com
Hi all,

I'm also curious about this. I've just started with play 2.4 and cannot figure a way to simply start/schedule some Akka actors after the play application has started. 

A small snippet would be very useful and appreciated. Thanks!

Regards,
Cristi Prodan

James Roper

unread,
Jul 3, 2015, 2:37:18 AM7/3/15
to play-framework
Hi Eddie,

Simply inject the actor system into your component, and you'll get the actor system, eg

class MyComponent @Inject() (actorSystem: ActorSystem) {
}

or in Java:

public class MyComponent {
  @Inject ActorSystem actorSystem;
}

Regards,

James


For more options, visit https://groups.google.com/d/optout.

James Roper

unread,
Jul 3, 2015, 2:39:15 AM7/3/15
to play-framework

Christian Kaps

unread,
Jul 3, 2015, 4:11:54 AM7/3/15
to play-fr...@googlegroups.com
Hi,

Thanks all for clarification. The eager singleton would also work for my scenario.

Best regards,
Christian

Johan Dahlberg

unread,
Jul 3, 2015, 5:38:59 AM7/3/15
to play-fr...@googlegroups.com
Nice, it works perfectly!

I have only one question. Is it possible to do something like "app.isTest()" in the old GlobalSettings file? Because many of these actors is not necessary when running the tests.

/Johan

Igmar Palsenberg

unread,
Jul 3, 2015, 5:44:33 AM7/3/15
to play-fr...@googlegroups.com

 
I have only one question. Is it possible to do something like "app.isTest()" in the old GlobalSettings file? Because many of these actors is not necessary when running the tests.

Yes, @Inject Environment, that has an isDev() / isProd() / isTest() method.


Igmar

Johan Dahlberg

unread,
Jul 3, 2015, 6:23:48 AM7/3/15
to play-fr...@googlegroups.com
Awesome! I couldn't mange to inject JPAApi the same way. Shouldn't that be possible?

This code causes: "CreationException: Unable to create injector, see the following errors:".

@Singleton
public class OnStartClass implements OnStartInterface {
    private static Logger.ALogger logger = Logger.of(OnStartClass.class);

    private ActorSystem actorSystem;
    private Configuration configuration;
    private JPAApi jpa;

    @Inject
    public OnStartClass(ActorSystem actorSystem, Configuration configuration, Environment environment) {
        this.actorSystem = actorSystem;
        this.configuration = configuration;
        this.jpa = jpa;
        logger.info("Executing OnStartClass");

        if(!environment.isTest()) {
        scheduleReports();
        }
    }

    private void reloadRemoveUnitActors() {
... empty for now
    }
}


p...@semlab.nl

unread,
Jul 6, 2015, 3:54:34 AM7/6/15
to play-fr...@googlegroups.com
I don't see any `jpa` argument in your constructor, maybe that is the problem?

Op vrijdag 3 juli 2015 12:23:48 UTC+2 schreef Johan Dahlberg:

Johan Dahlberg

unread,
Jul 6, 2015, 4:08:17 AM7/6/15
to play-fr...@googlegroups.com
A typo in the post. Here is the code I have:

@Singleton
public class OnStartClass implements OnStartInterface {
    private static Logger.ALogger logger = Logger.of(OnStartClass.class);

    private ActorSystem actorSystem;
    private Configuration configuration;
    private JPAApi jpa;

    /**
     * @param actorSystem the {@link akka.actor.ActorSystem}
     */
    @Inject
    public OnStartClass(ActorSystem actorSystem, Configuration configuration, Environment environment, JPAApi jpa) {
        this.actorSystem = actorSystem;
        this.configuration = configuration;
        this.jpa = jpa;
        logger.info("Executing OnStartClass");

        if(!environment.isTest()) {
            scheduleReports();
        }
    }

    private void scheduleReports() {
        jpa.withTransaction(() -> {
            List<Unit> scheduledUnits = ReportsDAO.newInstance().all();
   ...
        });
    }
}


and the error:

! @6ml1ifk9l - 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.ExceptionInInitializerError
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:35)
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:30)
  while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
  while locating play.db.jpa.JPAApi
    for parameter 3 at actors.OnStartClass.<init>(OnStartClass.java:45)
  at actors.OnStartClass.class(OnStartClass.java:34)
  while locating actors.OnStartClass
  at modules.OnStartModule.configure(OnStartModule.java:15) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.OnStartModule)
  while locating interfaces.OnStartInterface

1 error]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:165) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:121) ~[play-server_2.11-2.4.2.jar:2.4.2]
at scala.Option.map(Option.scala:146) ~[scala-library-2.11.7.jar:na]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:121) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:119) ~[play-server_2.11-2.4.2.jar:2.4.2]
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.ExceptionInInitializerError
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:35)
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:30)
  while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
  while locating play.db.jpa.JPAApi
    for parameter 3 at actors.OnStartClass.<init>(OnStartClass.java:45)
  at actors.OnStartClass.class(OnStartClass.java:34)
  while locating actors.OnStartClass
  at modules.OnStartModule.configure(OnStartModule.java:15) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.OnStartModule)
  while locating interfaces.OnStartInterface

1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:184) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110) ~[guice-4.0.jar:na]
at com.google.inject.Guice.createInjector(Guice.java:96) ~[guice-4.0.jar:na]
at com.google.inject.Guice.createInjector(Guice.java:73) ~[guice-4.0.jar:na]
Caused by: java.lang.ExceptionInInitializerError: null
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_45]
at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_45]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:242) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.buildHibernateConfiguration(EntityManagerFactoryBuilderImpl.java:1136) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:853) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
Caused by: java.lang.RuntimeException: There is no started application
at scala.sys.package$.error(package.scala:27) ~[scala-library-2.11.7.jar:na]
at play.api.Play$$anonfun$current$1.apply(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at play.api.Play$$anonfun$current$1.apply(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at scala.Option.getOrElse(Option.scala:121) ~[scala-library-2.11.7.jar:na]
at play.api.Play$.current(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
2015-07-06 10:03:46,989 - [error] application - 


row 45 is the constructor and 34 is the on where the Logger is created.

/Johan

Johan Dahlberg

unread,
Jul 6, 2015, 10:54:32 AM7/6/15
to play-fr...@googlegroups.com
The application isn't started when my OnStartClass is executed so JPA isn't ready. How can I make it start when the application is started and JPA is ready.

/Johan

Johan Dahlberg

unread,
Jul 7, 2015, 8:30:54 AM7/7/15
to play-fr...@googlegroups.com
I noticed that JPAApi is an interface,  is there an implementation that is possible to inject?

/Johan

p...@semlab.nl

unread,
Jul 8, 2015, 3:43:26 AM7/8/15
to play-fr...@googlegroups.com
You should always inject interfaces, the DI provider will find the correct implementation to use (or at least, that's the theory). That said, I'm not quite sure why the JPAApi injection isn't working, hopefully someone from the Play team can enlighten us about that.

Op dinsdag 7 juli 2015 14:30:54 UTC+2 schreef Johan Dahlberg:

Igmar Palsenberg

unread,
Jul 8, 2015, 3:59:55 AM7/8/15
to play-fr...@googlegroups.com

 
Caused by: java.lang.RuntimeException: There is no started application
at scala.sys.package$.error(package.scala:27) ~[scala-library-2.11.7.jar:na]
at play.api.Play$$anonfun$current$1.apply(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at play.api.Play$$anonfun$current$1.apply(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at scala.Option.getOrElse(Option.scala:121) ~[scala-library-2.11.7.jar:na]
at play.api.Play$.current(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
2015-07-06 10:03:46,989 - [error] application - 

This is caused by the java-jpa module, not your code : 

JPA.java : 

public static JPAApi jpaApi() {
        Application app = Play.application();
        if (app == null) {
            throw new RuntimeException("No application running");
        }
        return app.injector().instanceOf(JPAApi.class);
    }

This causes the exception. @James, is there a reason for this isn't done using injection ?



Igmar


 

James Roper

unread,
Jul 8, 2015, 7:55:08 PM7/8/15
to play-framework
Check logs/application.log or change your logback.xml to log more than 5 lines of exception stack traces.  The true cause of the problem here is being masked, but it appears that one of your entity classes is statically accessing entity manager when it's loaded, and is a problem because that requires global state.  And also because you should never access resources like databases during a static class initialiser, that's a classloading timebomb waiting to go off.



 

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Johan Dahlberg

unread,
Jul 9, 2015, 3:49:15 AM7/9/15
to play-fr...@googlegroups.com
I have a newInstance method in my DAO's so I will get rid of them. But i still get the error in my OnStartClass where it says that the application isn't started.

This is everything that is printed in the log file.

! @6mlnb86mf - 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.ExceptionInInitializerError
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:35)
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:30)
  while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
  while locating play.db.jpa.JPAApi
    for parameter 3 at actors.OnStartClass.<init>(OnStartClass.java:45)
  at actors.OnStartClass.class(OnStartClass.java:34)
  while locating actors.OnStartClass
  at modules.OnStartModule.configure(OnStartModule.java:15) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.OnStartModule)
  while locating interfaces.OnStartInterface

1 error]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:165) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:121) ~[play-server_2.11-2.4.2.jar:2.4.2]
at scala.Option.map(Option.scala:146) ~[scala-library-2.11.7.jar:na]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:121) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:119) ~[play-server_2.11-2.4.2.jar:2.4.2]
at scala.util.Success.flatMap(Try.scala:231) ~[scala-library-2.11.7.jar:na]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:119) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:111) ~[play-server_2.11-2.4.2.jar:2.4.2]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) ~[scala-library-2.11.7.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) ~[scala-library-2.11.7.jar:na]
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402) ~[na:1.8.0_45]
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) ~[na:1.8.0_45]
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) ~[na:1.8.0_45]
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1689) ~[na:1.8.0_45]
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) ~[na:1.8.0_45]
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.ExceptionInInitializerError
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:35)
  at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:30)
  while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
  while locating play.db.jpa.JPAApi
    for parameter 3 at actors.OnStartClass.<init>(OnStartClass.java:45)
  at actors.OnStartClass.class(OnStartClass.java:34)
  while locating actors.OnStartClass
  at modules.OnStartModule.configure(OnStartModule.java:15) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.OnStartModule)
  while locating interfaces.OnStartInterface

1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:184) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110) ~[guice-4.0.jar:na]
at com.google.inject.Guice.createInjector(Guice.java:96) ~[guice-4.0.jar:na]
at com.google.inject.Guice.createInjector(Guice.java:73) ~[guice-4.0.jar:na]
at com.google.inject.Guice.createInjector(Guice.java:62) ~[guice-4.0.jar:na]
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:126) ~[play_2.11-2.4.2.jar:2.4.2]
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:93) ~[play_2.11-2.4.2.jar:2.4.2]
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21) ~[play_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:153) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:150) ~[play-server_2.11-2.4.2.jar:2.4.2]
at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[play_2.11-2.4.2.jar:2.4.2]
at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:150) ~[play-server_2.11-2.4.2.jar:2.4.2]
... 14 common frames omitted
Caused by: java.lang.ExceptionInInitializerError: null
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_45]
at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_45]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:242) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.buildHibernateConfiguration(EntityManagerFactoryBuilderImpl.java:1136) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:853) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) ~[hibernate-jpa-2.1-api-1.0.0.Final.jar:1.0.0.Final]
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39) ~[hibernate-jpa-2.1-api-1.0.0.Final.jar:1.0.0.Final]
at play.db.jpa.DefaultJPAApi.start(DefaultJPAApi.java:56) ~[play-java-jpa_2.11-2.4.2.jar:2.4.2]
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:42) ~[play-java-jpa_2.11-2.4.2.jar:2.4.2]
at play.db.jpa.DefaultJPAApi$JPAApiProvider$$FastClassByGuice$$dcd4cdbd.newInstance(<generated>) ~[guice-4.0.jar:2.4.2]
at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40) ~[guice-4.0.jar:na]
at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:61) ~[guice-4.0.jar:na]
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:105) ~[guice-4.0.jar:na]
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85) ~[guice-4.0.jar:na]
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267) ~[guice-4.0.jar:na]
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103) ~[guice-4.0.jar:na]
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40) ~[guice-4.0.jar:na]
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41) ~[guice-4.0.jar:na]
at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:61) ~[guice-4.0.jar:na]
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:38) ~[guice-4.0.jar:na]
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:62) ~[guice-4.0.jar:na]
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:104) ~[guice-4.0.jar:na]
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85) ~[guice-4.0.jar:na]
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267) ~[guice-4.0.jar:na]
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103) ~[guice-4.0.jar:na]
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40) ~[guice-4.0.jar:na]
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41) ~[guice-4.0.jar:na]
at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:56) ~[guice-4.0.jar:na]
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103) ~[guice-4.0.jar:na]
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40) ~[guice-4.0.jar:na]
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:205) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:199) ~[guice-4.0.jar:na]
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator.loadEagerSingletons(InternalInjectorCreator.java:199) ~[guice-4.0.jar:na]
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:180) ~[guice-4.0.jar:na]
... 25 common frames omitted
Caused by: java.lang.RuntimeException: There is no started application
at scala.sys.package$.error(package.scala:27) ~[scala-library-2.11.7.jar:na]
at play.api.Play$$anonfun$current$1.apply(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at play.api.Play$$anonfun$current$1.apply(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at scala.Option.getOrElse(Option.scala:121) ~[scala-library-2.11.7.jar:na]
at play.api.Play$.current(Play.scala:71) ~[play_2.11-2.4.2.jar:2.4.2]
at play.api.Play.current(Play.scala) ~[play_2.11-2.4.2.jar:2.4.2]
at play.Play.application(Play.java:17) ~[play_2.11-2.4.2.jar:2.4.2]
at models.file.Transcode.<clinit>(Transcode.java:34) ~[na:na]
... 72 common frames omitted

/Johan

Igmar Palsenberg

unread,
Jul 13, 2015, 3:06:03 AM7/13/15
to play-fr...@googlegroups.com
Hi,

The error is caused by the module providing this. I'll file a issue and pull to fix this.


Igmar

Johan Dahlberg

unread,
Jul 13, 2015, 7:31:00 AM7/13/15
to play-fr...@googlegroups.com
Nice, but which module?

/Johan

Alexander Gubin

unread,
Jul 23, 2015, 6:27:21 PM7/23/15
to play-framework, jo...@dahlberg.co
Hi, 

Following multiple replies I was able to make my scheduler working in 2.4.2:
commented /* ... */ are things that used to work in 2.3.x

// eager injection
public class GuiceModule extends AbstractModule {
    @Override
    protected void configure() {
bind(Pulse.class).to(ScheduledPulse.class).asEagerSingleton();
    }
}

public interface Pulse { }


@Singleton
public class ScheduledPulse /*extends GlobalSettings*/  implements Pulse {
@Inject
public ScheduledPulse(Configuration configuration, ActorSystem actorSystem) {
Logger.info("Hi, I am an eager singleton");

final String serviceUrl = /*Play.application().*/configuration.getString("service.url", "example.com");
int frequency = configuration.getInt("pulse.interval", 5);
eligibility = /* Akka.system() */ actorSystem.scheduler().schedule(
 Duration.create(10, TimeUnit.SECONDS),
 Duration.create(frequency, TimeUnit.MINUTES),
 new Runnable() {
 @Override
 public void run() {
  doWork(serviceUrl);
 }
 },
  /* Akka.system() */ actorSystem.dispatcher()
);
}

}

public void doWork(final String serviceUrl) {
JPA.withTransaction(new F.Callback0() { 
 @Override public void invoke() throws Throwable { 
List dbObjects = JPA.em().createQuery("select something from someTable")
.setParameter("status", "AutoPending") .setParameter("submitted", Referral.RefStatus.Submitted) 
 .getResultList(); 
Logger.info("Found " + dbObject.size() + " things");
  for (Object o : dbObjects) {
// do something meaningful
}
}
});
}
}

will try to inject JPAApi too, but I am happy with the result so far.

Please comment on what else can be improved in this scenario

Sincerely,
Alexander

Sergey Dashko

unread,
Jul 28, 2015, 9:10:32 PM7/28/15
to play-framework, edouard...@gmail.com
Hi all.
Can somebody show example how to eager load actor in Scala?
I have this actor to add scheduler and trying to run it on startup:

import akka.actor.Actor
import play.api.libs.concurrent.Akka
import scala.concurrent.duration._
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global

class Scheduler extends Actor {

  override def preStart() {
    val dbupdate = Akka.system.scheduler.schedule(
      0.microseconds, 5.minutes, self, "update")
    val pictureClean = Akka.system.scheduler.schedule(
      0.microseconds, 30.minutes, self, "clean")
  }

  def receive = {
    case "update" => updateDB()
    case "clean" => clean()
  }

  def updateDB(): Unit ={
    Logger.debug("updates running")
  }

  def clean(): Unit ={
    Logger.debug("cleanup running")
  


понедельник, 29 июня 2015 г., 4:09:28 UTC+3 пользователь Eddie написал:
Hi all,

Before Play 2.4, we had onStart in GlobalSetttings which allowed us to execute some code AFTER the application started.
Since Play 2.4 and the dependency injection orientation, it's recommended to for a class to perform its initialization in it's constructor. The eager binding works well when we want execute some code on start up without injecting the object anywhere, but it's happening before Application is really started.

Is there a way to do the same thing, but after the application started ? Some of the initialization I have in my case need the application to be started. And I don't want to inject those objects in a controller, just to get the constructor called after the application started....

Thanks for your help

Christian Kaps

unread,
Jul 29, 2015, 2:59:56 AM7/29/15
to play-framework, edouard...@gmail.com, sda...@gmail.com
Hi Sergey,

My scheduler:
class Scheduler @Inject() (
system: ActorSystem,
@Named("voucher-generator") voucherGenerator: ActorRef,
@Named("voucher-cleaner") voucherCleaner: ActorRef) {

// Schedule jobs
QuartzSchedulerExtension(system).schedule("VoucherGenerator", voucherGenerator, VoucherGenerator.Generate)
QuartzSchedulerExtension(system).schedule("VoucherCleaner", voucherCleaner, VoucherCleaner.Clean)

// Start immediately on initialization
voucherGenerator ! VoucherGenerator.Generate
voucherCleaner ! VoucherCleaner.Clean
}

My Guice module:
class JobModule extends ScalaModule with AkkaGuiceSupport {

def configure() = {
bindActor[VoucherCleaner]("voucher-cleaner")
bindActor[VoucherGenerator]("voucher-generator")
bind[Scheduler].asEagerSingleton()
}
}

I use the Akka Quartz Scheduler to schedule my jobs. But the Akka scheduler should work the same.

Best regards,
Christian

Sergey Dashko

unread,
Jul 29, 2015, 8:42:09 AM7/29/15
to play-framework, kaps.ch...@gmail.com
Thank you Christian.
Tried to implement scheduler like you did but it didn't compile.
After some research and reading of docs created this implementation:
class JobModule extends AbstractModule with AkkaGuiceSupport {
def configure() = {
bindActor[SchedulerActor]("scheduler-actor")
bind(classOf[Scheduler]).asEagerSingleton()
}
}

class Scheduler @Inject() (system: ActorSystem, @Named("scheduler-actor") schedulerActor: ActorRef)(implicit ec: ExecutionContext)
{
val dbupdate = system.scheduler.schedule(
0.microseconds, 5.second, schedulerActor, "update")
val pictureClean = Akka.system.scheduler.schedule(
0.microseconds, 1.minutes, schedulerActor, "clean")
}

class SchedulerActor @Inject() (updater: Updater) extends Actor {

def receive = {
case "update" => updateDB()
case "clean" => clean()
}

def updateDB(): Unit ={
    Logger.error("updates running")
}

def clean(): Unit ={
Logger.error("cleanup running")
}
}

Now system try to start scheduler but then it throws this error:
[application-akka.actor.default-dispatcher-3] [akka://application/user/scheduler-actor] There is no started application

Thanks for help 


среда, 29 июля 2015 г., 9:59:56 UTC+3 пользователь Christian Kaps написал:

Christian Kaps

unread,
Jul 29, 2015, 10:01:12 AM7/29/15
to play-framework, sda...@gmail.com
Hi Sergey,

I think the following code doesn't compile for you because I use scala-guice.
bind[Scheduler].asEagerSingleton()

To your problem regarding the started application. It seems that a component used in your code depends on a started application. This does not work and should be refactored.

Best regards,
Christian

Naftoli Gugenheim

unread,
Jul 29, 2015, 7:58:14 PM7/29/15
to play-framework, kaps.ch...@gmail.com

You can use a custom app loader.


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

Christian Schmitt

unread,
Jul 30, 2015, 2:30:16 AM7/30/15
to play-framework, kaps.ch...@gmail.com, nafto...@gmail.com
Mostly that is not necessary since the most people just rely on Environment and Configuration and could inject those. That would work just as fine.
However with his Code we can't see what he does.

Sergey Dashko

unread,
Jul 30, 2015, 10:49:51 AM7/30/15
to play-framework, c.sc...@briefdomain.de
I've injected application in scheduler constructor and now my scheduler works

class Scheduler @Inject() (val app: Application, val system: ActorSystem, @Named("scheduler-actor") val schedulerActor: ActorRef)(implicit ec: ExecutionContext)
{
  implicit val application = app

Regards,
Sergey

Roy Lin

unread,
Aug 7, 2015, 1:44:15 AM8/7/15
to play-framework, c.sc...@briefdomain.de
This still did not work for me. It still says "there is no started application"

Christian Schmitt

unread,
Aug 10, 2015, 3:24:57 AM8/10/15
to play-framework, c.sc...@briefdomain.de
You shouldn't rely on the Application trait.

It's enough to just use ActorSystem, Configuration and Environment

jch...@groupon.com

unread,
Sep 3, 2015, 5:04:12 PM9/3/15
to play-framework, c.sc...@briefdomain.de
+1 

Roy, are you using Java code to implement your classes? Just wondering if this would have anything to do w/ using Java classes. 

For me this kicks in right after application creation and just before the beforeStart. 

15:59:56.749 [application-akka.actor.default-dispatcher-19] INFO  p.a.l.concurrent.ActorSystemProvider - Starting application default Akka system: application

Starting Scheduling

15:59:56.784 [application-akka.actor.default-dispatcher-19] INFO  application - Running 'beforeStart'.


If I try to access anything (like scheduling using the scheduler) it fails w/ saying there is no started application. 

Roy Lin

unread,
Sep 4, 2015, 9:12:48 PM9/4/15
to play-framework, c.sc...@briefdomain.de
hi jchung,

I'm using Scala. And yes it is doing exactly that between app creation and start. But what I need is something after app start. I have gone back to using the GlobalSettings object as I have not found a solution to this yet.

Roy

Alexey Pismenskiy

unread,
Oct 7, 2015, 12:34:52 PM10/7/15
to play-framework, c.sc...@briefdomain.de
Here is a simple project - Play, Akka, Scala and Google Guice DI. When it starts it schedules a message and then when the actor receives a message it schedules  another message to itself after 5 seconds. 
We use a similar design in one of our applications that need to do some repetitive processes (like DB scans) every {Interval} seconds.
Message has been deleted

Kévin Laurent

unread,
Oct 22, 2015, 8:30:52 AM10/22/15
to play-framework
I change a little your code :
in common.conf i have :
play {
modules {
enabled+= "fr.JobModule"
}
}

and my file is :  
package fr
import akka.actor._
import com.google.inject.AbstractModule
import fr.v1.services.AlerteService
import play.api.Logger
import play.api.libs.concurrent.AkkaGuiceSupport

import scala.concurrent.duration._


class JobModule extends AbstractModule with AkkaGuiceSupport {
def configure() = {
bindActor[SchedulerActor]("scheduler-actor")
}
}

class SchedulerActor extends Actor {
import context.dispatcher

context.system.scheduler.schedule(10.second, 1.minute, self, "update")

val service: AlerteService = AlerteService


def receive = {
case "update" => updateDB()
}

 def updateDB(): Unit = {
Logger.error("updates running")
  service.purgeAlerte()
}
}
Thanks
kévin

Alexey Pismenskiy

unread,
Oct 22, 2015, 11:08:11 AM10/22/15
to play-framework
Can you change it so your dependency will be injected into the actor, instead of
val service: AlerteService = AlerteService?
With DI it will be unit-testable

Paweł B

unread,
Nov 27, 2015, 8:39:52 AM11/27/15
to play-framework
I'm using compile time dependency injection and I would like to execute some code after application startup.
That code has to be executed not earlier that after application has started, because it depends on `Play.current`.

The compile time DI in Play uses `ApplicationLoader.load` method (https://www.playframework.com/documentation/2.4.x/ScalaCompileTimeDependencyInjection) to start an application. I have my object wiring code there, but `Play.current` is set only after `ApplicationLoader.load` has been called, so putting my initialization code in `load` method would case my initialization code to execute to early.
Having `onStartup` would solve my problem, but it does not exist. Also, I could probably use deprecated Plugin feature to plug in into application lifecycle but I'd like to avoid it.

Thanks for your help,
Cheers,
Paweł

Marius Soutier

unread,
Nov 27, 2015, 10:22:37 AM11/27/15
to play-fr...@googlegroups.com
Can you rewrite the code such that it no longer needs Play.current?

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

raunak

unread,
Nov 27, 2015, 10:49:54 AM11/27/15
to play-framework
How does this work if you want to read configuration from the config file? My understanding is that, that requires play.current?

Paweł B

unread,
Nov 27, 2015, 11:13:09 AM11/27/15
to play-framework
I even tried that, but it's too big task to tackle right now for me.
Because `Play.current` is a global, lots of code is written as Scala objects instead of classes, the affected places multiply rapidly.. So I would like to avoid rewriting it.

Marius Soutier

unread,
Nov 28, 2015, 9:18:26 AM11/28/15
to play-fr...@googlegroups.com
As for Configuration, you can simply inject it. That’s the recommended and future-proof way. If you’re not using DI right now, maybe stick with 2.3?

Igmar Palsenberg

unread,
Nov 30, 2015, 2:57:16 AM11/30/15
to play-framework
 
I'm using compile time dependency injection and I would like to execute some code after application startup.
That code has to be executed not earlier that after application has started, because it depends on `Play.current`.

Then you application is broken. Fix that, and use an eager singleton.


Igmar

Farooq Kamal

unread,
Aug 16, 2016, 2:01:00 AM8/16/16
to play-framework
Hi Eddie,

I'm jumping in pretty late in the discussion but here is what I have found, as none of the suggestions worked for me. I wanted to use the Akka scheduler without any actors. The scheduler error (application not running) originates from calling Akka.system (akin to calling Play.current and is NOT the preferred way anymore). The trick is to @Inject()(system: ActorSystem) into the desired eagersingleton class and use the injected system ... system.scheduler.scheduleOnce(duration) . Worked for me! I believe it should resolve the of eliminating Global

Cheers

On Tuesday, June 30, 2015 at 10:20:57 PM UTC-4, Eddie wrote:

Hi Christian,

Right now, we moved away 99% of the code we had in GlobalSetting (onStop, onError, onRequest etc...).
But because I can't find a way to add a start hook on the application life cycle, we still have to use Global but just the onstart(Application app) method.

We use app.injector() .instanceOf method to initialize a couple of stuff and that's all.

Cheers,

Tuesday 30 June 2015 22:15:55 UTC+10, Christian Kaps wrote :
Hi,

I would also be interested in this topic. We follow the same approach to initialize some Akka jobs on application start.

Best regards,
Christian

Am Dienstag, 30. Juni 2015 09:48:55 UTC+2 schrieb Eddie:
Hi James,

Thanks for your help, but I'm still not sure how to proceed.
Let me try to be more clear with an example: I have a service initializing some background tasks with Akka.system(). This initialization only needs to be done once, but I can't use an eager singleton because the instance would be created when the application starts up, and at this point Akka.system() is not available yet.

What I'm looking for is a way to add a start hook on the ApplicationLifecyle, just like we have a addStopHook method on the ApplicationLifecycle class.

Thanks for your help,

On 30 June 2015 11:05:19 UTC+10, James Roper wrote:
On 29 June 2015 at 11:09, Eddie <edouard...@gmail.com> wrote:
Hi all,

Before Play 2.4, we had onStart in GlobalSetttings which allowed us to execute some code AFTER the application started.
Since Play 2.4 and the dependency injection orientation, it's recommended to for a class to perform its initialization in it's constructor. The eager binding works well when we want execute some code on start up without injecting the object anywhere, but it's happening before Application is really started.

Is there a way to do the same thing, but after the application started ? Some of the initialization I have in my case need the application to be started.

A Play application doesn't do anything.  It consists of many components that do things.  So it doesn't make sense to say "I depend on an application being started", since it doesn't make sense to depend on something that does nothing.  What is likely is that you depend on some components that the application starts.  If that's the case, then simply make those components dependencies of your component.

Also, if you really want to depend on the whole application, then @Inject it into your component.  Then you will get a fully initialised application.

And I don't want to inject those objects in a controller, just to get the constructor called after the application started....

Thanks for your help

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Greg Methvin

unread,
Aug 16, 2016, 2:25:32 AM8/16/16
to play-framework
There are a number of threads discussing this topic, but the bottom line is that the application is not "started" until all its components are started. If this were allowed, it could cause problems if you tried to access a component of the application that hadn't been initialized yet, and this was in fact a major problem with the plugins system in Play 2.3 and before.

app.injector.instanceOf should really never be used. The only reason it's provided is as a crutch for those migrating from static APIs. It defeats the purpose of using dependency injection completely.

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/a5a5e83a-9da8-4068-b8a3-f4461bd32e53%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Senior Software Engineer

Reply all
Reply to author
Forward
0 new messages