avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephen McConnell <mcconn...@osm.net>
Subject Re: Merlin's Fortress
Date Wed, 24 Jul 2002 03:04:18 GMT


Berin Loritsch wrote:

>>From: Stephen McConnell [mailto:mcconnell@osm.net] 
>>
>>Berin Loritsch wrote:
>>
>>
>>There is conceptual difference here about the role of the 
>>container in Merlin and Fortress (I think).  In Merlin the 
>>container handles the assembly of the components resulting 
>>in the establishment of a set of ResourceDesignator 
>>instances.  ResourceDesignators are supplied to a 
>>Component/ServiceManager in map, keyed by role name.  When 
>>a client invokes lookup the manager implementation invokes 
>>getInstance() on the ResourceDesignator - in the case of 
>>threadsafe component - if the instance has not been 
>>established, it uses a lifecycle helper, provider 
>>and meta-data reference to build the instance (including 
>>the supply of a compoent/service manager packaged with 
>>dependent ResorurceDesignators). 
>>
>
>In my mind, the container is very broad.  It is the set of code that
>manages the components--their loading policies, configuration, mapping,
>everything.  I think you limit the container to something within your
>concept of Merlin.
>

I agree with the defintion - the seperation I'm referring to is more 
implementation level.  In Merlin the DefaultContainer implementation 
handles assembly, startup and shutdown.  The ProfileDesignator (created 
by the container during assembly) is an implementation of 
ResourceDesignator that handles the configuration, context, servicing, 
initialization - i.e. all of the lifecycle stuff. From the outside - the 
Container is responsible for all - however, when we cet into the 
implementation archtecture of the container itself, and if we break out 
assembly, your left with the ResourceDesignator implementations, the 
DefaultProvider (which works hand-in-hand with the container), and the 
LifecycleHelper as the primary classes.

>
>
>>In effect, the container has nothing to do after 
>>initialization except handle the components that have a a
>>ctivation-on-startup policy, and any shutdown/disposal requests 
>>from its kernel.  This appears to be different in Fortress 
>>because the Fortress container plays an active runtime role 
>>(by runtime I mean post start).  My current thinking is 
>>that the dynamic aspects of the Fortress Container should be 
>>positioned within an ResoruceDesignator implemetation.  If you 
>>take a look at the source merlin.container.ProfileDesignator 
>>you will see that it basically doesn't do much more than 
>>delegate requests of to the lifecycle helper - the lifecycle 
>>helper then uses merlin.container.DefaultProvider to 
>>resolve context, depedecies and so forth, using the meta-data 
>>model as execution context. My feeling is that we can handle 
>>different "semantic" appraches through variations on 
>>ResourceDesignator implementations.
>>
>
>
>What about access/release based events?  In order to satisfy supporting
>the legacy Recyclable interface, we need to be able to recycle the
>component.  We also need to be able to destroy factory-based components.
>Fortress does this asyncronously, so the act of releasing a component
>has no appearent effect on the operation of the system.
>

My assumption is that this is not a concern for the client - its a 
concern related to an implementation of ResourceDescriptor. Presumably 
access and release events flow from a client components interaction with 
its component/service manager - the manager interacts with the resource 
and the resource implementation would handle any recyling.  

Am I on the right track here ?

>
>>Agreed - I guess this is a question for Markus - can you 
>>eliminate the necessity for the declaration in the code of the 
>>extension to an extension manager?  For example, in the Fortress 
>>example for the extensions - there is a container that is explicity 
>>declaring the extension to the manager.  It would be designable for 
>>a lifecycle handler to figure this out for itself based on interfaces 
>>implemented by looking at the component class?  If so, do you see 
>>any problems integrating extension support into the 
>>merlin.container.LifecycleHelper class?
>>
>
>The concept of Extensions as they are currently implemented is based
>on the fact that we know our container needs to support the new
>interfaces.  The important thing here is that we need to guarantee
>a consistent ordering of lifecycle events.  We cannot do that based
>on reflection alone.  For instance, if we have multiple extensions
>(which I personally think is a dubious requirement) we have to
>apply the extensions in the proper order.
>
>Extensions are inherently application specific, so setting up the
>container requires the forknowledge of setting the proper lifecycle
>interfaces.  We need to decide if that is something we want to
>dynamically coordinate (Merlin style) or explicitly set (Fortress
>style).
>

I've been digging through the lfecyle extension stuff.  There is no class
level association between a lifecycle interface and its manager which means
that reflection will not solve the problem.

Imagine a lifecycle interface called Exploitable:

   public interface Exploitable
   {
      public void exploit();
   }

The container cannot check the interfaces supported by a the component class
for an extension interface (because Exploitable does not extends a base
interface).  What is needed at the type (meta-info) level is a declaration
of the manager class.

Just for reference - here is my ExploitationManager:

    public class ExploitationManager extends AbstractLifecycleExtension
    {
        public void access( Object object, Context context )
        {
            ((Exploitable)object).exploit();
        }
    }

A type implementing Exploitable introduces obligations towards it 
container at two level - (a) that fact that it needs to be handled by an 
extension manager (e.g. LifecycleHelper), and (b) that it has context 
dependecies (i.e. the container has to populate the context entries with 
values.  Both of these characteristics are meta-info level stuff.  

At the type (meta-info) level we would be looking at something like:

<component-info>
   <component>
      <name="my-exploitable-component"/>
   </component>
   <extensions>
      <!-- order list of extensions -->
      <extension class="ExploitationManager" name="exploitable">
         <context>
           <!-- context constraints here -->
         </context>
      </extensions>
   </extensions>
</component-info>

Remember that the information is developer defined and cannot be 
modified by a configuration.

Next is the Profile (meta-data) where we are concerned with 
customization of the instantiation criteria.  In the case of an 
extension, we are concerned with declaring the context information to be 
supplied to the context instance used in lifecycle handling implied by 
the extension.

<component class="MyExploitableComponent">
   <extensions>
     <!-- extension establishment criteria -->
     <extension name="exploitable">
       <context>
         <!-- context import and creation directives here -->   
       </context>
     </extension>
   </extensions>
</component>


>
>>I've been thinking off-and-on about the hadler declaration and the 
>>handler types in Fortress.  They tend to reflect lifestyle 
>>concerns but at the same time they mix functional policy - let 
>>me explain - a component may be pooled and thread-safe - it may 
>>be pooled and non-thread safe.  Other aspect such as lazy or 
>>immediate activation are seperate from the issue of thread-safe - 
>>I guess I would like to see a breakout of the different *lifestyle* 
>>and the different *deployment* policies.  I've tried to break out 
>>a table isolating the notions of singeton, poolable, per-thead, 
>>pre-request, and mapping these against thread-dafe and 
>>non-thread-safe components but I havn't arrived at a clean 
>>seperation. Any thoughts on this ?  I guess my hidden agenda here 
>>is to eliminate the requirement for the declaration of the 
>>handler class in preference to the declaration of lifestyle 
>>policy(ies).
>>
>
>
>Hmm.  In my mind, I would not waste resources by pooling ThreadSafe
>components.  If they are ThreadSafe, only provide one.  By virtue
>of the fact that components are ThreadSafe they are fully re-entrant,
>re-usable, and provide a consistent environment no matter how many
>threads are accessing it simultaneously.
>
>I reserve pooling/per-thread lifestyles for components that are
>re-usable, even though they are not re-entrant or force an order
>of method invocations.  The exact choice depends on if I need a
>unique instance per request vs. a unique instance per thread.
>
>Lastly, the pure factory method is used if a component is not
>re-useable.  A component that is not re-usable is like a hamburger
>that is not edible IMNSHO.  It looks like a hamburger, but it
>causes more problems than it solves if you try to eat it.  Same
>with this type of component.
>
>I really haven't found a need beyond these four basic types of
>lifestyles.  Have you run across something that I haven't?
>

Before answering that I want to dig a little bit more.
In Fortress there are the handler dealing with the following lifestyles:

   singleton  -  (always returns the same instance)
   factory    -  (creates a new instance)
   thread     -  (provides new instance keyed by thread)
   pooled     -  (returns recyclable instances per request)
   
All of the above are constraints supplied by a developer relative to the 
type of component.  As such, this is meta-info and should appear via the 
Type class.  At the Profile level there is information concerning things 
like pool size - etc. (i.e. the deployment criteria).  At the type level 
I'm currently thinking about how lifestyle could be represented using 
component type attributes.  I'm assuming the following would be sufficient:

   <component-info>
      <component>
         <attributes>
            <attribute key="avalon:lifestyle" value="pooled"/>
         <attributes>
      </attributes>
   </component-info>

Where the "avalon:lifestyle" attribute value could be one of pooled, 
thread, singleton or factory.
In a component profile we need to be able to provide lifestyle parameters:

   <component class="MyExploitableComponent">

     <!-- declaration of context entries to be supplied a handler -->

     <lifestyle class="MyPoolManagerImpl">
        <entry key="initial" class="int">14</entry>
        <entry key="maximum" class="int">100</entry>
     </lifestyle>

   </component>

During validation, the container would have to check that the component 
lifestyle attribute in the meta-info model is consitent with the class 
supplied in the meta-data model.  In addition, for a clean defintion of 
this at meta-info and meta-data levels, we would need to get somewhat 
more rigorouse about the lifestyle meta-data context entries than what I 
have described above (but you get the idea).

>>Ok - this now makes sence - basically RoleManager is maintaining 
>>meta-data in the form of easily assecible infromation in the form of 
>>configuration framgments and enabling these fragments to be passed 
>>around as needed.  Merlin's apprach is to eliminate the configuration 
>>but sucking in the the configuration once, and building a 
>>formal model 
>>accessible using the merlin.model API.  
>>
>
>
>:)  Yep, you got it!
>
>

Do I get a prize?
;-)

>
>>On the subject of maintainability - the Merlin stuff is 
>>really easy to use - PROVIDING - the meta-info is documentated 
>>in an .xinfo.  It gets even easier if you use .xprofile which 
>>is a static defintion of a set of instantiation profiles.  I 
>>would be really interested to get a better picture of the 
>>service model used by Cocoon assuming formal dependecies 
>>were declared in advance - which will really help in sorting 
>>out the real needs for dynamic service lookup.
>>
>
>
>Is the "how-to"/example on the site?  I want to get a feel for it.
>
>As to Cocoon component models, I will help out where I can.  I will
>say that 90% of the time, what changes is the sitemap--the portion
>which details *which* component implementation/configuration I need
>to use to process a particular request.  It is rare that the components
>are actually changed.  In those events that the component map is
>changed, it is usually adding new components.
>
>However it is feasible and reasonable to assume is that role names
>(as you define them) will be changed at any time the sitemap is
>reloaded.
>

Ok - I've bitten the bullet and downloaded the Cocoon source 
distribution and I'm now looking at AbstractSitemap.  First impressions 
are that there is a lot that can be moved into meta-info service 
dependencies. Second impression - the sitemap smells and feels like a 
container (needs meta-data to function).  But that's after 10 mins.

Cheers, Steve.

-- 

Stephen J. McConnell

OSM SARL
digital products for a global economy
mailto:mcconnell@osm.net
http://www.osm.net




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