1 Reply Latest reply on Mar 9, 2009 8:47 PM by Pete Muir

    WebBeans SE Lifecycle - Shutting Down

    Peter Royle Newbie

      The question of when to call shutdown is easily answered within an app server where lifecycle is clearly defined by the server. However for non-EE apps the question is a bit more difficult to answer.


      Currently the main application is executed by the firing of the @Deployed Manager event, which synchronously executes the appropriate observer method in the main app and then returns, at which point the manager will fire the Shutdown event (yet to be defined) and then shut down. As discussed previously the Shutdown event is useful for things like Quartz Scheduler shutdown etc.


      Essentially:



      • WebBeans Boots

      • WebBeans fires @Initialized Manager

      • 3rd Party extensions initialiase

      • WebBeans Fires @Deployed Manager

      • Main App executes

      • WebBeans fires Shutdown event

      • Main app and 3rd party extensions shut down and clean up

      • WebBeans shuts down (this is a effectively a NOOP, which is significant in point 2.2.1)



      The above works fine for simple apps where all the processing happens synchronously during the observer method, for example:



       Example A: 
      public void (@Observes Deployed Manager manager, @Parameters List<String> params) {
          System.out.println("You provided " + params.size() + " parameters. Well done.");
      }
      



      What I'm trying to do now is to define an approach for kicking off asynchronous/multithreaded applications. For example:



       Example B:
      public void (@Observes Deployed Manager manager, @Parameters List<String> params, @Current MainFrame mainFrame) {
          mainFrame.setVisible(true);
      }
      



      The above won't work very well, because the observer method will return immediately, causing WebBeans to go straight into the shutdown sequence.


      So here's a few options I've come up with. I would appreciate anyone and everyone's feedback on these, and if someone could point out any good approaches I've missed, that would be great.




      (1) Automatic Shutdown




      I tried thinking of ways to make the shutdown automatic in all cases but haven't really come up with anything I'm completely convinced about.



      (1.1) Use of finally method




      Even though I think the very idea is dubious, I tried it anyway and couldn't get it working. I'm no expert on the finally method but I couldn't get mine to fire. Plus I think it's too unreliable. Thoughts from experts? Can we rule this one out?


      (1.2) WebBeans Manages All Treads



      In this case, all threads are obtained by calls to WebBeans (or by injection?), so WebBeans knows which threads to wait for (join) before shutting down. This seems too restrictive though, especially for integration of 3rd party libs.


      (1.3) WebBeans Spies On All Threads



      This involves some kind of AOP wiring to catch and register the creation of all threads. Is this doable? Will it work for all 3rd party libs - ie: is there a limited number of ways a thread can be created such that we can catch them all, no matter what device the client code uses to kick off a thread (eg: EventQueue.invokeLater(...) ).




      (2) Manual Shutdown



      If we can't trigger shutdown automatically then the application developer is responsible for triggering the shutdown sequence. So in Example A above the developer would be responsible for initiating the shutdown sequence directly after the println statement.


      This poses the following questions (2.1) and (2.2):


      (2.1) How is the shutdown initiated?



      I can think of two obvious options, and they're not necessarily mutually exclusive:


      (2.1.1) Shutdown-triggering event



      This might look something like:



       Example C:
      @Fires Event<ShutdownRequest> shutdownRequest;
       
      public void (@Observes Deployed Manager manager, @Parameters List<String> params) {
          System.out.println("You provided " + params.size() + " parameters. Well done.");
          shutdownRequest.fire();
      }
      



      Alternatively it could be this, but it's a bit harder to remember:



       Example D:
      @Fires Event<Shutdown> shutdownRequest;
      
      public void (@Observes Deployed Manager manager, @Parameters List<String> params) {
         System.out.println("You provided " + params.size() + " parameters. Well done.");
         shutdownRequest.fire( new RequestLiteral() {} );
      }
      



      (2.1.2) Call to static method



      A boring old call to ShutdownHelper.requestShutdown() or something after the println statement. Seems to go against the grain, but the benefit is that it looks easier to digest in examples and is easier to remember.


      (2.2) Is the call to shutdown Mandatory?



      I see three possible answers:


      (2.2.1) Not Mandatory (Let the developer decide)



      So sometimes, as with Example A, it's not necessary to call shutdown, regardless of whether the app is single or multithreaded, because we've not introduced any third party libraries which require shutting down, and WebBeans will happily exit gracefully without explicit shutdown. Therefore developers could leave it out in such cases. However if they do add 3rd party libs that need clean shutting down without adding the call to shutdown they'll get weird behaviour (eg: Quartz will keep their app running after they close their main window).


      (2.2.2) Always Mandatory (No decision necessary)



      We could make it mandatory so that it appears in all examples and developers just get used to putting it in. Could that be enforced at runtime/compiletime?


      (2.2.3) Only Mandatory for Ansynchronous/Multithreaded Apps, Optional for Synchronous



      We could (maybe) detect when a multithreaded app has been started so that we don't automatically call shutdown as soon as the @Deployed Manager observer method returns /for multithreaded apps/, otherwise we do. Therefore the explicit call to shutdown by the developer is only required for apps which are marked/detected as being multithreaded. Below are some potential strategies for marking the multithreadedness of an app.


      (2.2.3.1) Special Binding Type for Observer Method



      If we introduced an annotation like @Asynchronously for use with @Deployed, like so:



       Example D:
      public void (@Asynchronously @Observes Deployed Manager manager, @Parameters List<String> params) {
          System.out.println("You provided " + params.size() + " parameters. Well done.");
      }
      



      ... or an annotation on the observer class like so:



       Example E:
      @Multithreaded
      public class Main {
      
         public void (@Observes Deployed Manager manager, @Parameters List<String> params) {
            System.out.println("You provided " + params.size() + " parameters. Well done.");
         }
      
      }
      



      Then we'd need a way of acknowledging the presence of the annotation when the event fires, though I'd be looking for ideas on exactly how.


      (2.2.3.2) By Configuration



      The developer could set a configuration variable to let WebBeans know that they will be taking responsibility for initiating the shutdown sequence when it makes sense for their app, and hence WebBeans needn't do any automatic shutdown sequence. This could be done programatically:



       Example F:
      public void (@Observes Deployed Manager manager, @Parameters List<String> params, @Current Configuration config) {
         config.setManualShutdown(true);
         System.out.println("You provided " + params.size() + " parameters. Well done.");
      }
      



      Alternatively this could be done by setting a property in beans.xml or beans.properties.



      SO. What does anyone think? I would love to have one of the automatic solutions so app developers never have to think about it, regardless of what 3rd party libs they happen to depend upon. However, if that's not possible then I'm leaning towards manual, completely mandatory invocation of shutdown every time using a static utility method which fires the underlying event.


      Please opine :)