DefaultApplicationLifecycle.stop()

134 views
Skip to first unread message

Michael Slinn

unread,
Jul 19, 2016, 11:13:19 AM7/19/16
to play-framework
I'd like to shut down the webapp in a controlled manner when a fatal error is encountered.

I could inject the Application instance (actually a DefaultApplication instance) into the class which will allow me to stop the webapp by invoking Application.stop(), which invokes DefaultApplicationLifecycle.stop()

We know that using GuiceApplicationBuilder is the preferred way to create an Application for testing. Application contains many other injectable components, such as ActorSytem, Configuration, Environment, Materializer, etc. The best practice is to minimize dependencies by injecting the minimum state possible. Thus injecting the entire Application is undesirable, however there are a few loose ends (such as the stop method) which are not provided in any other injectable component.

Questions:
  1. Is accessing Application in a live app recommended?
  2. Will DefaultApplication.stop() be exposed directly in a future version of Play Framework?
  3. Is there a better way of stopping the webapp?
Mike

Will Sargent

unread,
Jul 19, 2016, 11:49:36 AM7/19/16
to play-fr...@googlegroups.com
1.  Accessing Application in a live app is not recommended in general practice -- it is available for lifecycle events and for modules / framework code, but is too much of a "god object" to pass around.

2.  Again, Application is supposed to be internal housekeeping for Play, so it's unlikely. 

3.  If you want to stop the JVM at the same time, sending a SIGTERM signal when you've set up some shutdown hooks:


If you want to start and stop a Play application without worrying about JVM shutdown, you should embed a Play server inside your application:


and then call server.stop().

Will.

--
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/a74cf356-074e-4d6c-8a63-69c087e574e9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mike Slinn

unread,
Jul 19, 2016, 12:36:48 PM7/19/16
to play-fr...@googlegroups.com
Will,

Thanks for the quick response :)

My #2 should have asked about DefaultApplicationLifecycle.stop(), not DefaultApplication.stop()

How would you recommend a play app send SIGTERM to itself?

Mike
You received this message because you are subscribed to a topic in the Google Groups "play-framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/play-framework/3uLFHhWMudo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to play-framewor...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/CAJmgB61-ShujXRmZ-sPnkk48-ow3B6VF4u7Ec-tDCJDhJJdKog%40mail.gmail.com.

Will Sargent

unread,
Jul 19, 2016, 12:52:36 PM7/19/16
to play-fr...@googlegroups.com
To be clear, I don't think a Play instance receiving a fatal error should try and do a graceful shutdown.  A fatal error, by definition, is fatal and should kill the JVM solidly -- that means calling System.exit or even Runtime.halt.  

If that's inappropriate, then the system should alert as loud and clear as possible that it is solidly b0rked and then it's the admin and the services manager's (i.e. systemd) responsibility to send a SIGTERM / SIGKILL and clean up.  The system can't do a graceful anything itself because there's no grace or trust left in the system after a fatal error.

Will.

Michael Slinn

unread,
Jul 19, 2016, 1:01:47 PM7/19/16
to play-framework
Sorry, I don't think I said what I meant. For an app that decides that it wants to shut down of its own volition, even though no exceptions have been thrown and some might say that nothing is wrong, how might that best be done? Ultimately, whatever mechanism is employed, it is clear that DefaultApplicationLifecycle.stop() will be called.

Will Sargent

unread,
Jul 19, 2016, 1:15:45 PM7/19/16
to play-fr...@googlegroups.com

You'd set up an actor that would track all the resources you want to shut down, and then have that call System.exit() once you had confirmation everything was down.  Play is stateless, so you're not losing anything after that point.

Will.


On 07/19/2016 10:01 AM, Michael Slinn wrote:
Sorry, I don't think I said what I meant. For an app that decides that it wants to shut down of its own volition, even though no exceptions have been thrown and some might say that nothing is wrong, how might that best be done? Ultimately, whatever mechanism is employed, it is clear that DefaultApplicationLifecycle.stop() will be called.
--
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.

Mike Slinn

unread,
Jul 19, 2016, 1:23:32 PM7/19/16
to play-fr...@googlegroups.com
After I call System.exit, will the shutdown hooks be called before the webapp exits?

Mike

Will Sargent

unread,
Jul 19, 2016, 1:30:52 PM7/19/16
to play-fr...@googlegroups.com

Shutdown hooks are called when the application exits normally (System.exit(0)), but the shutdown hooks may be called in any order.

If you're asking "how do I call into the application shutdown lifecycle" -- that's something that is mostly there to support the development "live-reload" feature, so the JVM doesn't memory leak and OOM.  In live applications, Play runs until it's hit by a signal, like any other long running Unix process. 

If you have systems that need to be gracefully shut off or segregated, then the best way to do it is by building in circuit breakers and bulkheads so you can reconnect to your resources.  Then, if you want to have a feature that shuts off all external access, you can flip the switch.

Most of the major work in Play is to support this dynamic connection style -- part of the reason that Plugins and Singleton object based JDBC connection pools are painful is because they don't let you swap out, proxy or reconnect through to different resources.

Will.


On 07/19/2016 10:23 AM, Mike Slinn wrote:
After I call System.exit, will the shutdown hooks be called before the webapp exits?

Mike
--
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.

Michael Slinn

unread,
Jul 19, 2016, 8:40:50 PM7/19/16
to play-framework
Will,

Slight shift in topic, but related: I've got a Play app, built from SBT subprojects, where the database layer is done without Play. I'd like to preload a cache from the database before the webapp gets its first request - both in dev and prod modes. Preloading takes under a second. I want to invoke the cache preload from Play's early startup sequence, which seems to be driven by Guice. The Play docs talk about implementing a custom ApplicationLoader - not sure if this is the right way to add an extra prestart task. The GuiceApplicationLoader ScalaDoc also makes it seem like this might be a way forward.

I don't want to create a new type of "Play-like" app server; the simplest way is probably the best, whatever that is. What would you recommend?

Thanks,

Mike

Greg Methvin

unread,
Jul 20, 2016, 5:25:51 AM7/20/16
to play-framework
A common solution is to use an eager singleton binding. If you have some injectable cache object that you want to initialize, you can bind a provider for that as an eager singleton, do the initialization within the provider, and return the resulting object.

A custom application loader is a completely valid way of doing it. If you are doing several disparate things on startup prefer to have all your initialization in one place you might prefer to go that direction. But usually if your initialization is tied to a particular component it's nice to do it in the component's provider or constructor, as that provides a stronger guarantee that if you've obtained a reference to that object it is properly initialized.

--
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
Senior Software Engineer

Michael Slinn

unread,
Jul 20, 2016, 10:01:33 AM7/20/16
to play-framework
Greg,

I tested and found that an eager singleton is not loaded in dev mode until the first request, so that won't do.

Am I missing anything in this loader?


import play.api.{ ApplicationLoader, LoggerConfigurator }
import play.api.inject.guice.{ GuiceApplicationBuilder, GuiceApplicationLoader }

class MyAppLoader extends GuiceApplicationLoader {
  override def builder(context: ApplicationLoader.Context): GuiceApplicationBuilder = {
    LoggerConfigurator(context.environment.classLoader).foreach {
      _.configure(context.environment)
    }

    // my init code goes here?

    initialBuilder
      .in(context.environment)
      .loadConfig(context.initialConfiguration)
      .overrides(overrides(context): _*)
  }
}


Mike

Michael Slinn

unread,
Jul 20, 2016, 10:23:42 AM7/20/16
to play-framework
Just tested an found that the custom app loader does not load until after the first request in dev mode. So that is also out.

What other options exist?

Mike

Igmar Palsenberg

unread,
Jul 21, 2016, 5:45:27 AM7/21/16
to play-framework
 
Just tested an found that the custom app loader does not load until after the first request in dev mode. So that is also out.

What other options exist?

Why is this an issue ? If you bind an eager singleton, that will run before the request is processed.


Igmar 

Michael Slinn

unread,
Jul 21, 2016, 9:09:08 AM7/21/16
to play-framework
Igmar,

I tested and found that an eager singleton does not run in dev mode before the first request. Have you tested this yourself and found otherwise?

Mike

Igmar Palsenberg

unread,
Jul 21, 2016, 9:15:09 AM7/21/16
to play-framework
 
I tested and found that an eager singleton does not run in dev mode before the first request. Have you tested this yourself and found otherwise?

No, it works this way. But why is that an issue ? The whole stack is bootstrapped in the first request, and that includes running the eager singleton before handling the request.
Hence my question : Why is this an issue for you ?


Igmar 

Michael Slinn

unread,
Jul 21, 2016, 9:41:06 AM7/21/16
to play-framework
Igmar,

You are shifting the topic from issues with "to cause a class constructor to run immediately when a Play webapp starts, even in dev mode, create an eager singleton", to "you cannot do that, why would you want to"? The new topic is not appropriate for this venue.

If there is no way to cause a class constructor to load immediately the docs should be updated. So far I've only looked at Guice-related mechanisms. What other mechanisms exist which would make this possible?

Mike

Igmar Palsenberg

unread,
Jul 21, 2016, 10:13:21 AM7/21/16
to play-framework
 
You are shifting the topic from issues with "to cause a class constructor to run immediately when a Play webapp starts, even in dev mode, create an eager singleton", to "you cannot do that, why would you want to"? The new topic is not appropriate for this venue.

I think it is, certainly for devs to assess if this needs fixing. The eager singleton is stick run way before the first request is processed, so I'm trying to understand why this is an issue for you.
 
If there is no way to cause a class constructor to load immediately the docs should be updated. So far I've only looked at Guice-related mechanisms. What other mechanisms exist which would make this possible?

In dev mode ? None that I'm aware off. Bootstrapping kicks in after the first request, also if you use a custom loader.


Igmar
Reply all
Reply to author
Forward
0 new messages