avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephen McConnell <mcconn...@apache.org>
Subject Re: Merlin/Fortress update ?
Date Sat, 03 Aug 2002 00:58:18 GMT


Berin Loritsch wrote:

>>From: Stephen McConnell [mailto:mcconnell@osm.net] 
>>
>>The latest Merlin news is the completion of pluggable lifecycle 
>>extensions. 
>>    
>>
>
>
>Now that I have had time to read the message in its entirety, here
>are some observations:
>
>
>  
>
>>The extension framework is fully incorporated in the 
>>component model - 
>>components can declare a dependency on a lifecycle extension provider 
>>via a <phase> declaration in the component type model.  For example:
>>
>>   <component-info>
>>      <component>
>>        <name>my-component</name>
>>      </component>
>>
>>      <phases>
>>        <phase>
>>          <reference 
>>type="org.apache.excalibur.playground.Exploitable" 
>>version="1.0"/>
>>        </phase>
>>        <phase>
>>          <reference 
>>type="org.apache.excalibur.playground.Demonstratable"/>
>>        </phase>
>>      </phases>
>>
>>   </componenent-info>
>>
>>Declaration of a <phase/> is similar to the declaration of a service 
>>dependency in that phase providers are managed by the Merlin 
>>container 
>>as dependencies of the target component.  In the above example, two 
>>lifecycle extension dependencies are being declare.  The type 
>>attribute 
>>declares the lifecycle interface implemented by the component 
>>- its up 
>>to the container to resolve an appropriate lifecycle extension to 
>>provide this to the target component when handling component 
>>instantiation.
>>    
>>
>
>
>We can reduce the verbosity of the <component-info/> declaration by
>merging the <reference/> element with the <phase/> and <extension/>
>elements.  In essence, we are changing this:
>
><phases>
>  <phase>
>    <reference type="com.mycom.foobar.Demonstratable" version="1.0"/>
>  </phase>
>  <phase>
>    <reference type="com.mycom.foobar.Exploitable"/>
>  </phase>
></phases>
>
>to this:
>
><phases>
>  <phase reftype="com.mycom.foobar.Demonstratable" version="1.0"/>
>  <phase reftype="com.mycom.foobar.Exploitable"/>
></phases>
>
>And similarly with the extensions
>
><extension stage="ALL"
>           type="com.mycom.foobar.Demonstratable"
>           version="1.0">
>  <name>demonstrate</name>
>  <attributes>
>    <attribute key="status" value="experimental"/>
>  </attributes>
></extension>
>
>
>At least from an XML point of view, it simplifies what someone has
>to type.
>

It would be simpler but it would also be inconsitent with the rest of 
the XML declarations.  Merlin's XML schema is a superset of the 
containerkit XML schema.  It doesn't make sence to change this in one 
place and ignore the rest.  If you look at depednency declaration and 
service declarations its the same pattern.  One of the benefits of 
having a seperate <reference/> element is that is reusable across 
several areas of the model (refernce to service dependecy interfaces, 
reference to supplied service dependecies, reference to phase 
depedencies, etc.).  In turn the the <reference/> element get turned 
into a org.apache.excalibur.meta.info.ReferenceDescriptor instance which 
is used across the meta-ifo and meta-data model.  Finally, this is in 
meta-info land - so we don't see these declarations in kernel 
configurations (i.e. its developer only scope).

>>Lifecycle handlers are declared as extension of the "classic" 
>>component type definition.  Here is an example of a lifecycle 
>>handler.  It publishes its ability to handle a phase via an 
>><extension/> element.  The container is responsible for locating 
>>extension providers based on the matching of the <phase> type 
>>attribute with an <extension><reference/> type attribute.  
>>Selection of an extension handler is identical to the selection 
>>of a service dependency.  This means that multiple candidate 
>>extensions can exist within a singe classloader scope.
>>    
>>
>
>
>Honestly, I'm not sure if I like this.  I prefer lifecycle extension
>handlers being treated distinctly as such.  Maybe it would be better
>if it had its own markup like this:
>
><extension-info>
>  <!-- Declare everything else the same -->
></extension-info>
>

I tend to agree.  
(but I still thinking about it)

>>Other important points are that a extension provider can 
>>declare its own phase dependencies and also classic service 
>>dependencies.  Merlin will take care of the ordering of 
>>component establishment based on the phase and service 
>>dependencies that the component publishes. 
>>
>>Extension providers must implement the following interface:
>>
>>    org.apache.excalibur.merlin.assembly.resource.Extension
>>
>>The interface declares the operation "extend( int stage, 
>>Object object, Context context ) which will be invoked by 
>>the Merlin container during the appropriate stages.  Merlin 
>>defines a number of stages that can be associated with an 
>>extension provider.  Merlin will only invoke extend 
>>if the provider declares that it supports the particular stage.
>>
>>Standard stages include the following:
>>
>>   CREATE    invoked immediately before initialization
>>   ACCESS    invoked immediate before lookup
>>   RELEASE   invoked immediately before release
>>   DESTROY   invoked immediately before dispose
>>   INNER     equivalent to ACCESS + RELEASE
>>   OUTER     equivalinet to CREATE + DESTROY
>>   ALL       equivalent to INNER + OUTER
>>    
>>
>
>
>:/
>
>I kind of like Marcus' solution a bit better.  We have simple
>methods that have a specific meaning.  If a lifecycle event happens
>on more than one type of use (create/destroy/access/release),
>the implementor has the freedom to use OO principles more clearly
>by encapsulating the common elements in a separate method.
>
>More often then not, we are not processing the same method even
>if we are processing the same interface.  Take for instance the
>following:
>
>interface PersistantConfigurable
>{
>    void configure(Configuration conf);
>
>    Configuration saveConfiguration();
>}
>
>
>Which is more clear?
>
>Marcus solution:
>------------------------------------------------------------------------
>--
>
>class PersistantConfigurableHandler extends AbstractExtension
>{
>     void create( Object component, Context context )
>     throws Exception
>     {
>         if ( component instanceof PersistantConfigurable )
>         {
>             ((PersistantConfigurable) component)
>                 .configure( (Configuration) context.get(
>"configuration" ) );
>         }
>     }
>
>     void destroy( Object component, Context context )
>     throws Exception
>     {
>         if ( component instanceof PersistantConfigurable )
>         {
>             Configuration config = ((PersistantConfigurable) component)
>                 .saveConfiguration();
>
>             // perform config persistence here.
>         }
>     }
>}
>
>-----------------------------------------------------------------
>
>Your solution:
>
>-----------------------------------------------------------------
>
>class PersistantConfigurableHandler implements LifecycleExtension
>{
>     void stage( int stage, Object component, Context context )
>     throws Exception
>     {
>         if ( component instanceof PersistantConfigurable )
>         {
>             switch(stage)
>             {
>                 case CREATE:
>                     ((PersistantConfigurable) component)
>                         .configure( (Configuration) context.get(
>"configuration" ) );
>                     break;
>
>                 case DESTROY:
>                     Configuration config = ((PersistantConfigurable)
>component)
>                         .saveConfiguration();
>
>                     // perform config persistence here.
>                     break;
>             }
>         }
>     }
>}
>
>---------------------------------------------------------------
>
>
>I like having separate and distinct methods that do one thing, and
>do not change behavior based on a value passed in.
>
>The stage(...) solution gets much more complicated when you have more
>than one interface you are supporting.
>

I agree that Marcus' solution is cleaner  - the reason I moved away from 
that was that my experience in CORBA land (where extensions have a very 
big part in systems deployment) is that you don't need all of the 
interception points. In particular, the extension implementation should 
be controlling when it is requested. I think Leo has the right idea in 
terms of seperating the extension stage interfaces.  But I'll address 
that in more detail when I reply to Leo's email.

>>Demonstration of extension declaration and phase declaration 
>>is included in the org.apache.excalibur.playground package (see 
>>assembly/demo) - in particular, the DemoManager, 
>>ExpliotationManager (both examples of extension providers), and 
>>SimpleComponent - a multi-phase phase consumer.
>>    
>>
>
>
>I will check your example to see if I completely missed what
>I think you were saying here, but I don't think I'm that far
>off.
>

Your on track!
Basically - I agree that some degree of simplification can be achieved 
on the interface side.  I don't agree about the simplification of the 
XML mainly becuase this is inside the meta-info structure and can be 
generated by tools.  I do agree that it could be preferable to introduce 
an seperate <XXXX-info> element for component that are providing 
extensions - but I still thinking about it.

Cheers, Steve.



--
To unsubscribe, e-mail:   <mailto:avalon-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@jakarta.apache.org>


Mime
View raw message