A component lifecycle deals with the series of actions that an object assumes that a container will apply following instantiation in order to bring the instance into a working state, and the corresponding actions dealing with instance decommissioning. In the examples presented in the tutorials we have leveraged the principal of constructor based injection of 'smart' implementations of component defined contracts that largely negate the need for supplimentarty deployment or decommissioning concerns. However - there are many components that use alternative containment models that depend on formal semantics. For example the Jetty package makes extensive use of start and stop lifecycle functions. Earlier container system such as Avalon made use of interfaces such as Startable and Executable to express implementation assumptions.
The Metro system includes a generic lifecycle description model that enables the declaration arbitarily complex deployment and decommissioning lifecycles expressed as state transitions and management operations. This tutorial present an example of the creation and usage of a state transition model.
The following lifecycle defintion constructs a formal state-transition graph for a component that is initialized via a start method invocation, resulting in the exposure of a stop management operation, and the assertion of a termination criteria involving the invocation of a stop method.
org/acme/Demo.xgraph
<state xmlns="dpml:state" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <trigger event="initialization"> <transition name="start" target="started"> <operation name="startup" method="start"/> </transition> </trigger> <state name="started"> <trigger event="termination"> <apply id="stop"/> </trigger> <transition name="stop" target="../stopped"> <operation name="stop" method="stop"/> </transition> </state> <state name="stopped"> <transition name="start" target="../started"> <operation name="start" method="start"/> </transition> </state> </state>
This above lifecycle graph declares a root state containing:
- An initialization trigger fired automaticaly following instantiation of the component instance - the trigger declares a state transition as the triggers action - the transition will move the active state of the object to started and the transition definition declares that the start operation shall be performed as a precondition to transition completion.
- The started state declaring the availability of the stop transition which is defined to chage the active state to stopped. In addition the started state declares a termination trigger which will be automatically fired if the component is terminated while in the started. The termination action involes the existing transition named stop.
- The stopped state declares a transition supporting migration to the started state and efficively dissables supplimentary termination actions.
During runtime the Metro container maintains a referrence to the active state. Any actions or transitions declared within the active state and any parent state of the active state become available management operation.
In this example the testcase simply deploys the component, releases its reference and invokes the garbage collector (triggering instance disposal). With logging for the demo component set to full trace mode we can see the additional container functionality dealing with the activation and deactivation lifecycle phases:
test: [junit] Executing forked test. [junit] Running org.acme.test.DemoTestCase [junit] [11050] [FINER ] (demo): creating new component handler [/demo] for class [org.acme.Demo] [junit] [11050] [FINER ] (demo): adding component model listener [component:/demo (org.acme.Demo)] [junit] [11050] [FINE ] (demo): established transient lifestyle handler for [org.acme.Demo] [junit] [11050] [FINER ] (demo): commissioning [junit] [11050] [FINER ] (demo): creating new provider [junit] [11050] [FINER ] (demo): provider instantiation [junit] [11050] [FINER ] (demo): instantiating [org.acme.Demo] [junit] [11050] [FINE ] (demo): instantiated [5503831] [junit] [11050] [FINER ] (demo): applying transition [start] to [5503831] [junit] [11050] [INFO ] (demo): startup [junit] [11050] [FINER ] (demo): transitioning from [root] to [root/started] in [5503831] [junit] [11050] [FINE ] (demo): activated [5503831] [junit] [11050] [FINER ] (demo): returning service instance [5503831] [junit] [11050] [FINER ] (demo): finalizing component handler [junit] [11050] [FINER ] (demo): initiating finalization in [5503831] [junit] [11050] [FINER ] (demo): initiating disposal of [5503831] [junit] [11050] [FINER ] (demo): applying transition [stop] to [5503831] [junit] [11050] [INFO ] (demo): shutdown [junit] [11050] [FINER ] (demo): transitioning from [root/started] to [root/stopped] in [5503831] [junit] [11050] [FINE ] (demo): instance disposal [5503831] [junit] [11050] [FINER ] (demo): finalization completed in [5503831] [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.984 sec
This tutorial has demonstrated the definition of a custom component lifecycle and the resulting impact on the component runtime during deployment and decommissioning phases. In addition the state graph provides support for the declaration of dynamic management operations, support for transition invocation my management systems and several other advanced features.