PicoContainer
  1. PicoContainer
  2. PICO-264

Cannot stop already started components if start of container fails

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.2-RC1
    • Fix Version/s: 1.2
    • Component/s: PicoContainer (Java)
    • Labels:
      None
    • Number of attachments :
      0

      Description

      If a container with multiple components is started and the start of a component fails if others have been started already, there is currently no way to stop them again:

      • a user does not know, which have been started
      • calling pico.stop() throws an IllegalStateException (although it knows which ones have been initialized)

        Issue Links

          Activity

          Hide
          Jörg Schaible added a comment -

          A similar question arises for stop and dispose. Should the Pico continue for the lasting components in case of an exception? IMHO, yes.

          Show
          Jörg Schaible added a comment - A similar question arises for stop and dispose. Should the Pico continue for the lasting components in case of an exception? IMHO, yes.
          Hide
          Mauro Talevi added a comment -

          Two approaches:

          • fail-fast: if any component fails on start() the pico.start() fails - safe but can be heavy-handed.
          • not fail-fast: continue after any components fails on start() - but you need to keep track of which components have
            started (not just initalised) so that they are stopped on stop() or else an ISE occurs.

          I would opt for fail-fast for release 1.2.

          Show
          Mauro Talevi added a comment - Two approaches: fail-fast: if any component fails on start() the pico.start() fails - safe but can be heavy-handed. not fail-fast: continue after any components fails on start() - but you need to keep track of which components have started (not just initalised) so that they are stopped on stop() or else an ISE occurs. I would opt for fail-fast for release 1.2.
          Hide
          Jörg Schaible added a comment -

          The current fail-fast implementation is exactly my problem, some components have been started already! Even if I catch the RTE from pico.start() I cannot stop those who have been started. Note, that I don't propose to continue after start, but I want/have to stop! And a failure at stop is a different case where fail-fast does not make necessarily sense.

          Show
          Jörg Schaible added a comment - The current fail-fast implementation is exactly my problem, some components have been started already! Even if I catch the RTE from pico.start() I cannot stop those who have been started. Note, that I don't propose to continue after start, but I want/have to stop! And a failure at stop is a different case where fail-fast does not make necessarily sense.
          Jörg Schaible made changes -
          Field Original Value New Value
          Link This issue is related to PICO-266 [ PICO-266 ]
          Jörg Schaible made changes -
          Component/s PicoContainer (Java) [ 10191 ]
          Description If a container with multiple components is started and the start of a component fails if others have been started already, there is currently no way to stop them again:
          - a user does not know, which have been started
          - calling pico.stop() throws an IllegalStateException (although it knows which ones have been initialized)
          If a container with multiple components is started and the start of a component fails if others have been started already, there is currently no way to stop them again:
          - a user does not know, which have been started
          - calling pico.stop() throws an IllegalStateException (although it knows which ones have been initialized)
          Hide
          Paul Hammant added a comment -

          One of the first implementation of the Monitor concept was for AltRMI. When there was an invocation failure across teh wire, the monitor could participate in the design to the extent that it could choose to cause the invocation (on the client side) to fail or not. I've put something similar into ComponentMonitor called lifecycleFailure(..)

          See if that's good enough for you Joerg.

          Show
          Paul Hammant added a comment - One of the first implementation of the Monitor concept was for AltRMI. When there was an invocation failure across teh wire, the monitor could participate in the design to the extent that it could choose to cause the invocation (on the client side) to fail or not. I've put something similar into ComponentMonitor called lifecycleFailure(..) See if that's good enough for you Joerg.
          Hide
          Jörg Schaible added a comment -

          > See if that's good enough for you Joerg.

          Sorry, to say, but no, there's no real difference. See, if a container starts and at a certain point started component throws, how can I stop the already started? It is still the same. Before and after your change I would have to install my own monitor, keep track of all components with an "invoked" event for my start method (that might be something completely different for a customized LC) and only then I can stop all those that have been started already. And in this scenario I do not even need the new lifecycleFailure event, because the exception is thrown up to start anyway and I am not interested in the failed component. What I wanna do is simply something like:

          try

          { pico.start(); ... }

          finally

          { pico.stop(); // Pico throws in IllegalStateExcpetion here! }
          Show
          Jörg Schaible added a comment - > See if that's good enough for you Joerg. Sorry, to say, but no, there's no real difference. See, if a container starts and at a certain point started component throws, how can I stop the already started? It is still the same. Before and after your change I would have to install my own monitor, keep track of all components with an "invoked" event for my start method (that might be something completely different for a customized LC) and only then I can stop all those that have been started already. And in this scenario I do not even need the new lifecycleFailure event, because the exception is thrown up to start anyway and I am not interested in the failed component. What I wanna do is simply something like: try { pico.start(); ... } finally { pico.stop(); // Pico throws in IllegalStateExcpetion here! }
          Hide
          Mauro Talevi added a comment -

          Seems to me the only way to achieve this is to keep track of the comps which have been started or not.

          Show
          Mauro Talevi added a comment - Seems to me the only way to achieve this is to keep track of the comps which have been started or not.
          Hide
          Jörg Schaible added a comment -

          But we have it! Isn't it just the instantiation order list?

          Show
          Jörg Schaible added a comment - But we have it! Isn't it just the instantiation order list?
          Hide
          Paul Hammant added a comment -

          I've done some more work.

          Its still in the Custom CM design, but the possibilities are closer to the problem your trying to solve :-

          try

          { pico.start(); compMgr.reThrowLifecycleExceptions(); }

          finally

          { pico.stop(); }

          Is this OK?

          You do have to have a custom CM (or use CollectingComponentManager), but you don't have to keep track of components or the stuff you were talking about.

          I've also added chaining capability to all the CMs. Its not supposed to be switchable hence DelegatingComponentMonitor still exists.

          Thoughts ?

          Show
          Paul Hammant added a comment - I've done some more work. Its still in the Custom CM design, but the possibilities are closer to the problem your trying to solve :- try { pico.start(); compMgr.reThrowLifecycleExceptions(); } finally { pico.stop(); } Is this OK? You do have to have a custom CM (or use CollectingComponentManager), but you don't have to keep track of components or the stuff you were talking about. I've also added chaining capability to all the CMs. Its not supposed to be switchable hence DelegatingComponentMonitor still exists. Thoughts ?
          Hide
          Mauro Talevi added a comment -

          I would have something like:

          public void rethrowLifecycleFailuresExceptions()

          { throw new PicoLifecycleException(lifecycleFailures)); }

          and have the PicoLifecycleException handle the formatting and returning of the lifecycle failures.

          Show
          Mauro Talevi added a comment - I would have something like: public void rethrowLifecycleFailuresExceptions() { throw new PicoLifecycleException(lifecycleFailures)); } and have the PicoLifecycleException handle the formatting and returning of the lifecycle failures.
          Hide
          Nick Sieger added a comment -

          Should pico track which components have started, but guard start() on each component such that if an exception is thrown, pico will go back and attempt to stop any already started components and then propagate the original component.start() exception? This would require a container start/stop template like this:

          pico.start();
          try

          { // do stuff with pico }

          finally

          { pico.stop(); }

          Thus, an exception thrown out of pico.start() would need to be handled at a higher level.

          Show
          Nick Sieger added a comment - Should pico track which components have started, but guard start() on each component such that if an exception is thrown, pico will go back and attempt to stop any already started components and then propagate the original component.start() exception? This would require a container start/stop template like this: pico.start(); try { // do stuff with pico } finally { pico.stop(); } Thus, an exception thrown out of pico.start() would need to be handled at a higher level.
          Hide
          peter royal added a comment -

          I agree with nick.

          If startup fails, components that have bee successfully started need to be stopped, and all instantiated components should be disposed (since instantiation is the equivalent of an initialize)

          Show
          peter royal added a comment - I agree with nick. If startup fails, components that have bee successfully started need to be stopped, and all instantiated components should be disposed (since instantiation is the equivalent of an initialize)
          Hide
          Jose Peleteiro added a comment -

          and what about if any component threw an exception when pico tryied to stop/dispose it? A PIE with multiple causes or throw just the last one?

          Show
          Jose Peleteiro added a comment - and what about if any component threw an exception when pico tryied to stop/dispose it? A PIE with multiple causes or throw just the last one?
          Hide
          Mauro Talevi added a comment -

          I committed a fix which satisfies Joerg's usecase, only attempting to stop the components which have been started.

          The CollectingCM is still useful IMO - but would rename it LifecycleCM.

          Show
          Mauro Talevi added a comment - I committed a fix which satisfies Joerg's usecase, only attempting to stop the components which have been started. The CollectingCM is still useful IMO - but would rename it LifecycleCM.
          Paul Hammant made changes -
          Assignee Joerg Schaible [ joehni ]
          Hide
          Jörg Schaible added a comment -

          Folks, I tested my app after the changes of Mauro ... and I have still my zombie. I've added the test case to DPCLicecylceTestCase. Reason is now, that the pico with the failing component has children and calling stop on the parent pico will cause again an IllegalStateEx in the child pico. Not sure how to address this one now properly.

          Show
          Jörg Schaible added a comment - Folks, I tested my app after the changes of Mauro ... and I have still my zombie. I've added the test case to DPCLicecylceTestCase. Reason is now, that the pico with the failing component has children and calling stop on the parent pico will cause again an IllegalStateEx in the child pico. Not sure how to address this one now properly.
          Jörg Schaible made changes -
          Assignee Joerg Schaible [ joehni ] Mauro Talevi [ maurotalevi ]
          Hide
          Mauro Talevi added a comment -

          I've checked in a fix which keeps track of the child containers' started status as well.
          Only the ones for which start is attempted - albeit not successfully perhaps - are allowed to be stopped.
          Test case now passes.

          Perhaps there is a case in PIco 1.3 or 2.0 to revisit the lifecycle status management,
          which will probably involve changes to the API interfaces.
          For the moment, I would limit ourselves to satisfying proven test cases.

          Show
          Mauro Talevi added a comment - I've checked in a fix which keeps track of the child containers' started status as well. Only the ones for which start is attempted - albeit not successfully perhaps - are allowed to be stopped. Test case now passes. Perhaps there is a case in PIco 1.3 or 2.0 to revisit the lifecycle status management, which will probably involve changes to the API interfaces. For the moment, I would limit ourselves to satisfying proven test cases.
          Mauro Talevi made changes -
          Assignee Mauro Talevi [ maurotalevi ] Joerg Schaible [ joehni ]
          Hide
          Jörg Schaible added a comment -

          Mauro's latest changes allow my app at least to shutdown. I think we agree all in a revisited LC status concept for the next Pico version.

          Show
          Jörg Schaible added a comment - Mauro's latest changes allow my app at least to shutdown. I think we agree all in a revisited LC status concept for the next Pico version.
          Jörg Schaible made changes -
          Resolution Fixed [ 1 ]
          Status Open [ 1 ] Closed [ 6 ]

            People

            • Assignee:
              Jörg Schaible
              Reporter:
              Jörg Schaible
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: