avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject cvs commit: avalon-site/xdocs/developing decomposing.xml framework.xml
Date Sun, 14 Mar 2004 11:54:40 GMT
niclas      2004/03/14 03:54:40

  Modified:    xdocs/developing decomposing.xml framework.xml
  Log:
  Developing With Avalon saga continues...
  
  Revision  Changes    Path
  1.3       +4 -4      avalon-site/xdocs/developing/decomposing.xml
  
  Index: decomposing.xml
  ===================================================================
  RCS file: /home/cvs/avalon-site/xdocs/developing/decomposing.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- decomposing.xml	14 Mar 2004 09:42:53 -0000	1.2
  +++ decomposing.xml	14 Mar 2004 11:54:40 -0000	1.3
  @@ -333,14 +333,14 @@
           <p>
             The DocumentStore is the main persistence handler in the repository.
             It is this component that implements the external DocumentRepository
  -          interface, as a <em>Aggregated Component</em> can not implement any
  +          interface, as an <em>Aggregated Component</em> can not implement any
             code by itself.
           </p>
         </subsection>
         
         <subsection name="DataSourceComponent">
           <p>
  -          The DataSourceComponent is supplied by Avalon Components.  It is our
  +          The DataSourceComponent is a manager of database connections. It is our
             method of retrieving valid JDBC Connection objects for our use.
           </p>
         </subsection>
  @@ -349,13 +349,13 @@
             The Cache is a short-term memory-based storage facility.  The
             DocumentRepository will use it to store Document objects referenced
             by a hash algorithm.  In order to promote the reusability of the
  -          Cache Component, the stored object must implement a Cacheable
  +          Cache component, the stored object must implement a Cacheable
             interface.
           </p>
         </subsection>
         <subsection name="Guardian">
           <p>
  -          The Guardian Component is used to manage permissions based on the
  +          The Guardian component is used to manage permissions based on the
             Principal.  The Guardian will load its permission sets from a
             database.  The Guardian will use the standard Java security model to
             enforce access to the specific Document objects.
  
  
  
  1.2       +175 -503  avalon-site/xdocs/developing/framework.xml
  
  Index: framework.xml
  ===================================================================
  RCS file: /home/cvs/avalon-site/xdocs/developing/framework.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- framework.xml	2 Nov 2003 11:10:48 -0000	1.1
  +++ framework.xml	14 Mar 2004 11:54:40 -0000	1.2
  @@ -4,6 +4,7 @@
     <properties>
       <author email="hammant@apache.org">Paul Hammant</author>
       <author email="bloritsch@apache.org">Berin Loritsch</author>
  +    <author email="niclas@apache.org">Niclas Hedhman</author>
       <title>Framework and Foundations</title>
     </properties>
   
  @@ -14,349 +15,196 @@
       understand the contracts and constructs defined in the framework, you can
       understand anything that uses it.  Remember the principles and patterns we
       have already discussed so far.  In this section, we will expound on how the
  -    Role concept works practically, the lifecycle of Components, and how the
  +    Role concept works practically, the lifecycle of components, and how the
       interfaces work.
     </p>
     </section>
  -  <section name="Defining the Component's Role">
  +  <section name="Defining the Service Interface">
       <p>
  -      In Avalon, all Components have a role.  The reason is that you retrieve
  -      your Components by role.  At this stage, the only concern area we are
  -      using is the signature of the role.  If you recall in the second section,
  -      we defined a Component as "the combination of a work interface and the
  -      implementation of the interface".  That work interface is your role.
  +      In Avalon, all components implements a Service, so we need to define
  +      the <em>Service Interface</em> and the associated semantic contract.
       </p>
  -    <subsection name="Creating the Role's Interface">
  +    <subsection name="Creating the Service Interface">
         <p>
           Below you will find an example interface, followed by some best
           practices along with their reasoning.
         </p>
         <source>
   <![CDATA[
  -package org.apache.bizserver.docs;
  +package org.apache.avalon.bizserver.docrepository;
   
  +/** Interface to store and retrieve arbitrary Documents in a persisted store.
  + *
  + * The DocumentRepository is responsible to store Documents, create a reference
  + * identity and be able to retrieve the same document at any point later in 
  + * time using the document identity returned in the <code>storeDocument()</code>
  + * method call.
  + */
   public interface DocumentRepository
   {
  -    String ROLE = DocumentRepository.class.getName();
  -
  -    Document getDocument(Principal requestor, int refId);
  +    /** Retrieves a Document from the persisted document store.
  +     *
  +     * @return Document of the previously stored Document or null if not
  +     * found.
  +     * @throw SecurityException if the Principal is not authorized to 
  +     * retrieve that document.
  +     */
  +    Document retrieveDocument(Principal requestor, int refId)
  +        throws SecurityException;
  +    
  +    /** Store a Document into the persisted store.
  +     *
  +     * @return A Unique Document Identity, to be used later to retrieve the
  +     * same document.
  +     * @throw SecurityException if the Principal is not allowed to store
  +     * documents in the persisted store.
  +     */
  +    int storeDocument( Principal requestor, Document doc )
  +        throws SecurityException;
   }
   ]]>
         </source>
         <subsection name="Best Practices">
           <ol>
             <li>
  -            <p>
  -              Include a String called "ROLE" that has the role's official name.
  -              That name is the same as the fully qualified name for the work
  -              interface.  This helps later on when we need to get an instance
  -              of the Component later.
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              Do extend the Component interface if possible.  This makes it easier
  -              on you when it is time to release your Component.  If you are not
  -              in control of the work interface, then you do not have this option.
  -              It is not the end of the world, as you can recast the instance to
  -              <code>Component</code> when it is time to release it.
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              Do one thing and do it well.  A Component should have the simplest
  -              interface possible, When your work interface extends several other
  -              interfaces, you muddy the contract for this Component.  An old
  +              Do NOT extend the any life cycle interfaces in your service 
  +              interface.
  +          </li>
  +          <li>
  +            Document as much semantic rules (implicit or explicit) as possible.
  +            This will limit the possibilities of misunderstanding between the
  +            people who define the <em>Service Contract</em> and the implementing
  +            developer. Even if that is today the same person, the Service may
  +            be re-implemented in the future by someone else. Also, additional
  +            clients shouldn't have to understand the implementation, and 
  +            everything should be 100% clear from the service documentation.
  +          </li>
  +          <li>
  +              Do one thing and do it well.  A Service should have the simplest
  +              interface possible, When your service interface extends several 
  +              other interfaces, you muddy the contract for this Service. An old
                 American acronym helps define this pattern: Keep It Simple, Stupid
  -              (KISS).  It's not hard to outsmart yourself -- I've done it
  -              a number of times myself.
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              Only specify the methods you need.  The client should have no
  -              knowledge of implementation details, and too many alternative
  -              methods only introduce unneeded complexity.  In other words pick
  -              an approach and stick with it.
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              Don't let your Role's interface extend any lifecycle or lifestyle
  -              interfaces.  By implementing any of those classes of interfaces, you
  -              are tying an implementation to the specification.  This is a
  -              bad pattern and this will only lead to debugging and implementation
  -              problems later.
  -            </p>
  +              (KISS).  It's not hard to outsmart yourself -- We do it all the 
  +              time.
  +          </li>
  +          <li>
  +              Only specify the methods that are needed in the Service interface. 
  +              It is important to realize that the Service interface is used
  +              by client code. Within the component, you probably need additional
  +              methods between the classes. These methods should be package
  +              protected and NOT exposed in the Service interface. This increase
  +              understandability and the possibility to exchange the component
  +              in the future.
             </li>
           </ol>
         </subsection>
  -      <subsection name="Choosing the Role's Name">
  -        <p>
  -          In Avalon, every Role has a name. It is how you get references to
  -          other Components in the system.  The Avalon team has outlined some
  -          idioms to follow for the naming of your role.
  -        </p>
  -        <subsection name="Naming Idioms">
  -          <ol>
  -            <li>
  -              <p>
  -                The fully qualified name of the work interface is usually the
  -                role name.  The exceptions are listed after this general rule.
  -                Using this example, our theoretical Component's name would be
  -                "org.apache.bizserver.docs.DocumentRepository".  This is the
  -                name that would be included in your interface's "ROLE"
  -                property.
  -              </p>
  -            </li>
  -            <li>
  -              <p>
  -                If we obtain the reference to this Component through a
  -                Component Selector, we usually take the role name derived from
  -                the first rule and append the word "Selector" to the end.  The
  -                result of this naming rule would be
  -                "org.apache.bizserver.docs.DocumentRepositorySelector".  You
  -                can use the shorthand
  -                <parameter>DocumentRepository.ROLE + "Selector"</parameter>.
  -              </p>
  -            </li>
  -            <li>
  -              <p>
  -                If we have multiple Components that implement the same work
  -                interface, but are used for different purposes, we have
  -                separate roles.  A Role is the Component's purpose in the
  -                system.  Each role name will start with the original role
  -                name, but the purpose name of the role will be appended
  -                with a <parameter>/${purpose}</parameter>.  By example
  -                we could have the following purposes for our
  -                DocumentRepository: PurchaseOrder and Bill.  Our two roles
  -                would be expressed as
  -                <parameter>DocumentRepository.ROLE + "/PurchaseOrder"</parameter>
  -                and <parameter>DocuementRepository.ROLE + "/Bill"</parameter>,
  -                respectively.
  -              </p>
  -            </li>
  -          </ol>
  -        </subsection>
  -      </subsection>
       </subsection>
     </section>
     <section name="Overview of Framework Interfaces">
       <p>
  -      The entire Avalon Framework can be divided into seven main categories (as
  -      is the API): Activity, Service, Configuration, Context, Logger,
  -      Parameters, Thread, and Miscellany.  Each of those categories (except
  -      Miscellany) represents a unique concern area.  It is common for a
  -      Component to implement several interfaces to identify all the concern
  -      areas that the Component is worried about.  This will allow the
  -      Component's container to manage each Component in a consistent manner.
  +      The entire Avalon Framework can be divided into 5 main categories (as
  +      is the API): Activity, Service, Configuration, Context, Logger.  Each of 
  +      those categories represents a unique concern area.  It is common for a
  +      component to implement several interfaces to identify all the concern
  +      areas that the component is concerned about.  This will allow the
  +      component's container to manage each component in a consistent manner.
       </p>
       <subsection name="Lifecycle for Avalon Interfaces">
         <p>
           When a framework implements several interfaces to separate the concerns
  -        of the Component, there is potential for confusion over the order of
  -        method calls.  Avalon Framework realizes this, and so we developed the
  -        contract for lifecycle ordering of events.  If your Component does not
  -        implement the associated Interface, then simply skip to the next event
  -        that will be called.  Because there is a correct way to create and
  -        prepare Components, you can set up your Components as you receive
  -        events.
  +        of the component, there is potential for confusion over the order of
  +        method calls.  Avalon Framework realizes this, so we developed the
  +        contract for lifecycle ordering of events.  If your component does not
  +        implement the associated Interface, then simply skip to the next
  +        that will be called. The lifecycle order makes it easy to setup and
  +        prepare the component for use, in each of the lifecycle methods.
         </p>
         <p>
  -        The Lifecycle of a Component is split into three phases:
  +        The Lifecycle of a component is split into three phases:
           Initialization, Active Service, and Destruction.  Because these phases
  -        are sequential, we will discuss the events in order.  In addition, the
  +        are sequential, we will discuss them in that order. 
  +        The Active Service phase is outside the concern of the container, and
  +        basically consists of other components calling the methods in the 
  +        Service interface.
  +        In addition, the
           act of Construction and Finalization is implicit due to the Java
           language, so they will be skipped.  The steps will list the method
           name, and the required interface.  Within each phase, there will be a
           number of stages identified by method names.  Those stages are executed
  -        if your Component extends the associated interface specified in
  +        if your component extends the associated interface specified in
           parenthesis.
         </p>
         <subsection name="Initialization">
           <p>
             This list of stages occurs in this specific order, and occurs only
  -          once during the life of the Component.
  +          once during the life of the component.
           </p>
           <ul>
             <li>
  -            <p>
                 <code>enableLogging</code>
                 [<code>LogEnabled</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>contextualize</code>
                 [<code>Contextualizable</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>compose</code>
                 [<code>Composeable</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>service</code>
                 [<code>Serviceable</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>configure</code>
                [<code>Configurable</code>]
                 <em>or</em>
                 <code>parameterize</code>
                [<code>Parameterizable</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>initialize</code>
                 [<code>Initializable</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>start</code>
                 [<code>Startable</code>]
  -            </p>
  -          </li>
  -        </ul>
  -      </subsection>
  -      <subsection name="Active Service">
  -        <p>
  -          This list of stages occurs in this specific order, but may occur
  -          multiple times during the life of the Component.  Please note that
  -          should you choose to not implement the Suspendable interface, it is
  -          up to your Component to ensure proper functionality while executing
  -          any of the Re* stages.
  -        </p>
  -        <ul>
  -          <li>
  -            <p>
  -              <code>suspend</code>
  -              [<code>Suspendable</code>]
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              <code>recontextualize</code>
  -              [<code>Recontextualizable</code>]
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              <code>recompose</code>
  -              [<code>Recomposable</code>]
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              <code>reconfigure</code>
  -              [<code>Reconfigurable</code>]
  -            </p>
  -          </li>
  -          <li>
  -            <p>
  -              <code>resume</code>
  -              [<code>Suspendable</code>]
  -            </p>
             </li>
           </ul>
         </subsection>
         <subsection name="Destruction">
           <p>
             This list of stages occurs in the order specified, and occurs only
  -          once during the life of the Component.
  +          once during the life of the component.
           </p>
           <ul>
             <li>
  -            <p>
                 <code>stop</code>
                 [<code>Startable</code>]
  -            </p>
             </li>
             <li>
  -            <p>
                 <code>dispose</code>
                 [<code>Disposable</code>]
  -            </p>
             </li>
           </ul>
         </subsection>
       </subsection>
       <subsection name="Avalon Framework Contracts">
         <p>
  -        In this section, we will cover all the sections alphabetically with
  -        the exception of the most important concern area: Component.
  +        In this section, we will cover all the sections alphabetically.
         </p>
  -      <table>
  -        <tr><th>A Word About Containers</th></tr>
  -        <tr><td>
  -          When I use the word "container" or "contains" when describing
  -          Components, I have a very specific meaning.  I am referring to child
  -          Components that the parent Component has instantiated and controls.
  -          I am not referring to Components obtained through a ServiceManager or
  -	  ServiceSelector.  Furthermore, some Avalon stages
  -	  received by a
  -          container must be propagated to all of its children implementing the
  -          appropriate interface.  The specific interfaces in question are
  -          Initializable, Startable, Suspendable, and Disposable.  The reasoning
  -          for this contract is that these particular interfaces have specific
  -          execution contracts.
  -        </td></tr>
  -      </table>
  -      <subsection name="Service">
  -        <p>
  -	  This is the core of Avalon Framework. Any interface defined in this concern
  -	  area will throw ServiceException.
  -        </p>
  -        <subsection>
  -          <title>Serviceable</title>
  -          <p>
  -            A Component that uses other Components needs to implement either this
  -	    interface or the old Composable interface. The new interface is the
  -	    preferred way of doing things.  The interface has only one method
  -            <code>service</code> with a
  -            <code>ServiceManager</code> passed in as the only
  -            parameter.
  -          </p>
  -          <p>
  -            The contract surrounding this interface is that the
  -            <code>service</code> is called once and only once during
  -            the lifetime of this Component.
  -          </p>
  -          <p>
  -            This interface along with any other interface that has methods
  -            specified uses the Inversion of Control pattern.  It is called by
  -            the Component's container, and only the Components that this
  -            Component needs should be present in the
  -            <code>ServiceManager</code>.
  -          </p>
  -        </subsection>
  -        <subsection name="Reserviceable?">
  -          <p>
  -            The Recomposable interface has no replacement in the Serviceable
  -	    package. Use of Recomposable has been extremely rare, and many
  -	    applications that use avalon do not provide support for it.
  -          </p>
  -        </subsection>
  -      </subsection>
  -
         <subsection name="Activity">
           <p>
             This group of interfaces refers to contracts for the life cycle of
  -          the Component.  If there is an error during any method call with this
  -          group of interfaces, then you can throw a generic Exception.
  +          the component. Each method allows the generic 
  +          <code>java.lang.Exception</code> to be thrown in any case of error.
           </p>
           <subsection name="Disposable">
             <p>
               The <code>Disposable</code> interface is used by any
  -            Component that wants a structured way of knowing it is no longer
  -            needed.  Once a Component is disposed of, it can no longer be used.
  +            component that wants a structured way of knowing it is no longer
  +            needed.  Once a component is disposed of, it can no longer be used.
               In fact, it should be awaiting garbage collection.  The interface
               only has one method <code>dispose</code> that has no
               parameters.
  @@ -364,74 +212,66 @@
             <p>
               The contract surrounding this interface is that the
               <code>dispose</code> method is called once and the method
  -            is the last one called during the life of the Component.  Further
  -            implications include that the Component will no longer be used,
  -            and all resources held by this Component must be released.
  +            is the last one called during the life of the component.  Further
  +            implications include that the component will no longer be used,
  +            and all resources held by this component must be released. In a way,
  +            it is a replacement of <code>finalize()</code>, which has very 
  +            complicated semantics, that doesn't apply to <code>dispose()</code>.
             </p>
           </subsection>
           <subsection name="Initializable">
             <p>
               The <code>Initializable</code> interface is used by any
  -            Component that needs to create Components or perform
  -            initializations that take information from other initialization
  -            steps.  The interface only has one method
  +            component that needs to perform initializations that take information
  +            from other initialization steps.  It is more natural to place all
  +            the initialization in the <code>intialize()</code> method, and only
  +            gather the required pieces in the preceeding lifecycle methods.
  +            The interface only has one method
               <code>initialize</code> that has no parameters.
             </p>
             <p>
               The contract surrounding this interface is that the
               <code>initialize</code> method is called once and the
               method is the last one called during the initialization sequence.
  -            Further implications include that the Component is now live, and it
  -            can be used by other Components in the system.
  +            Further implications include that the component is now live, and it
  +            can be used by other components in the system.
             </p>
           </subsection>
           <subsection name="Startable">
             <p>
               The <code>Startable</code> interface is used by any
  -            Component that is constantly running for the duration of its life.
  +            component that is constantly running for the duration of its life.
               The interface defines two methods: <code>start</code> and
               <code>stop</code>.  Neither method has any parameters.
             </p>
             <p>
               The contract surrounding this interface is that the
               <code>start</code> method is called once after the
  -            Component is fully initialized, and the <code>stop</code>
  -            method is called once before the Component is disposed of.  Neither
  +            component is fully initialized, and the <code>stop</code>
  +            method is called once before the component is disposed of.  Neither
               method will be called more than once, and <code>start</code>
               will always be called before <code>stop</code>.
  +            Furthermore, the method must return, it can not go into a endless
  +            loop. From this follows that the component should create a thread
  +            and call the <code>Thread.start()</code> method inside this
  +            method to ctart the continous processing.
  +            The <code>stop()</code> method should interrupt the thread in a
  +            safe manner. This should be done by variables and the 
  +            <code>Thread.interrupt()</code> method, slightly depending on how
  +            the thread is operating.
               Implications of using this interface require that the
               <code>start</code> and <code>stop</code> methods be
               conducted safely (unlike the <code>Thread.stop</code>
               method) and not render the system unstable.
             </p>
           </subsection>
  -        <subsection name="Suspendable">
  -          <p>
  -            The <code>Suspendable</code> interface is used by any
  -            Component that is running for the duration of its life that permits
  -            itself to be suspended.  While it is most commonly used in
  -            conjunction with the <code>Startable</code> interface, it
  -            is not required to do so.  The interface defines two methods:
  -            <code>suspend</code> and <code>resume</code>.
  -            Neither method has any parameters.
  -          </p>
  -          <p>
  -            The contract surrounding this interface is that
  -            <code>suspend</code> and <code>resume</code> may be
  -            called any number of times, but never before the Component is
  -            initialized and started or after the Component is stopped and
  -            disposed.  Calls to <code>suspend</code> when the system is
  -            already suspended should have no effect as well as calls to
  -            <code>resume</code> when the system is already running.
  -          </p>
  -        </subsection>
         </subsection>
         <subsection name="Configuration">
           <p>
             This group of interfaces describes the concern area of configuration.
             If there are any problems, such as required
             <code>Configuration</code> elements that are missing, then
  -          you may throw a <code>ConfigurationException</code>.
  +          the component may throw a <code>ConfigurationException</code>.
           </p>
           <subsection name="Configurable">
             <p>
  @@ -445,7 +285,7 @@
             <p>
               The contract surrounding this interface is that the
               <code>configure</code> method is called once during the
  -            life of the Component.  The <code>Configuration</code>
  +            life of the component.  The <code>Configuration</code>
               object passed in <em>must not be null</em>.
             </p>
           </subsection>
  @@ -470,38 +310,33 @@
               true -- if there are any children, there should be no value.
             </p>
             <p>
  +            To simplify the code, the method calls <code>getChild()</code>
  +            and <code>getChildren()</code> will always return Configuration
  +            and never null.
  +          </p>
  +          <p>
               You will notice that you may not get parent
               <code>Configuration</code> objects.  This is by design.
               To reduce the complexity of the <code>Configuration</code>
               system, containers will most likely pass child configuration
  -            objects to child Components.  The child Components should not have
  +            objects to child components.  The child components should not have
               any access to parent configuration values.  This approach might
               provide a little inconvenience, but the Avalon team opted for
               security by design in every instance where there was a tradeoff.
             </p>
           </subsection>
  -        <subsection name="Reconfigurable">
  -          <p>
  -            Components that implement this interface behave very similar to
  -            <code>Recomposable</code> Components.  It's only method
  -            is named <code>reconfigure</code>.  This design decision is
  -            used to minimize the learning curve of the Re* interfaces.
  -            <code>Reconfigurable</code> is to
  -            <code>Configurable</code> as
  -            <code>Recomposable</code> is to
  -            <code>Composable</code>.
  -          </p>
  -        </subsection>
         </subsection>
         <subsection name="Context">
           <p>
             The concept of the <code>Context</code> in Avalon arose
  -          from the need to provide a mechanism to pass simple objects from a
  -          container to a Component.  The exact protocol and binding names are
  -          purposely left undefined to provide the greatest flexibility to
  -          developers.  The contracts surrounding the use of the
  -          <code>Context</code> object are left for you to define in
  -          your system, however the mechanism is the same.
  +          from the need to provide a mechanism to pass simple objects
  +          (i.e. non-components) from a container to a component.  
  +          This has since then grown into a very powerful mechanism in
  +          Avalon Merlin, where you can create your own Context entries,
  +          as well as extend the Context instance itself with your own
  +          implementation.
  +          See the Avalon Merlin documentation for details on how to define
  +          custom context entries.
           </p>
           <subsection name="Context">
             <p>
  @@ -509,14 +344,13 @@
               method <code>get</code>.  It has an
               <code>Object</code> for a parameter, and it returns an
               object based on that key.  The <code>Context</code> is
  -            populated by the container, and passed to the child Component who
  -            only has access to <em>read</em> the
  -            <code>Context</code>.
  +            populated by the container, and passed to the child component who
  +            only has access to <em>read</em> the <code>Context</code>.
             </p>
             <p>
               There is no set contract with the <code>Context</code>
               other than it should always be <em>read-only</em> by
  -            the child Component.  If you extend Avalon's
  +            the child component.  If you extend Avalon's
               <code>Context</code>, please respect that contract.  It
               is part of the Inversion of Control pattern as well as security by
               design.  In addition, it is a bad idea to pass a reference to the
  @@ -526,7 +360,7 @@
           </subsection>
           <subsection name="Contextualizable">
             <p>
  -            A Component that wishes to receive the container's
  +            A component that wishes to receive the container's
               <code>Context</code> will implement this interface.  It
               has one method named <code>contextualize</code> with the
               parameter being the container's <code>Context</code>
  @@ -535,247 +369,85 @@
             <p>
               The contract surrounding this interface is that the
               <code>contextualize</code> method is called once during the
  -            life of a Component, after <code>LogEnabled</code> but
  +            life of a component, after <code>LogEnabled</code> but
               before any other initialization method.
             </p>
           </subsection>
  -        <subsection name="Recontextualizable">
  -          <p>
  -            Components that implement this interface behave very similar to
  -            <code>Recomposable</code> Components.  It's only method
  -            is named <code>recontextualize</code>.  This design
  -            decision is used to minimize the learning curve of the Re*
  -            interfaces.  <code>Recontextualizable</code> is to
  -            <code>Contextualizable</code> as
  -            <code>Recomposable</code> is to
  -            <code>Composable</code>.
  -          </p>
  -        </subsection>
  -        <subsection name="Resolvable">
  -          <p>
  -            The Resolvable interface is used to mark objects that need to be
  -            resolved in some particular context.  An example might be an object
  -            that is shared by multiple <code>Context</code> objects,
  -            and modifies its behavior based on a particular
  -            <code>Context</code>.  The <code>resolve</code>
  -            method is called by the <code>Context</code> before the
  -            object is returned.
  -          </p>
  -        </subsection>
         </subsection>
         <subsection name="Logger">
           <p>
  -          Every system needs the ability to log events.  Avalon uses its
  -          LogKit project internally.  While LogKit does have ways of accessing
  -          a Logger instance statically, the Framework wishes to use the
  -          Inversion of Control pattern.
  +          Every system needs the ability to log events.  Avalon Merlin 
  +          uses a subsystem called <em>Avalon Logging</em> which is capable
  +          of logger subsystem plug-ins. Currently, it supports Apache Log4J
  +          and the original Avalon LogKit. Expect more systems to follow soon.
  +          Also, it is fairly easy to create a new Avalon Logging Plug-In,
  +          in case you need to access a custom logging system.
  +        </p>
  +        <p>
  +          Logging is often done by statically addressing some factory method
  +          in the Logging subsystem. Avalon always tries to apply Inversion
  +          of Control, which means that the component should not try to 
  +          figure out how to obtain a Logger instance, it should be given one
  +          by the container. The container can then be configured with the
  +          most suitable Logging system for the application, without any 
  +          changes to the components.
           </p>
           <subsection name="LogEnabled">
             <p>
  -            Every Component that needs a Logger instance implements this
  +            Every component that needs a Logger instance implements this
               interface.  The interface has one method named
               <code>enableLogging</code> and passes Avalon Framework's
  -            <code>Logger</code> instance to the Component.
  +            <code>Logger</code> instance to the component.
             </p>
             <p>
               The contract surrounding this method is that it is called only
  -            once during the Component's lifecycle before any other
  +            once during the component's lifecycle before any other
               initialization step.
             </p>
           </subsection>
           <subsection name="Logger">
             <p>
               The <code>Logger</code> interface is used to abstract
  -            away the differences in logging libraries.  It provides only a
  -            client API.  Avalon Framework provides three wrapper classes that
  -            implement this interface: <code>LogKitLogger</code> for
  -            LogKit, <code>Log4jLogger</code> for Log4J, and
  -            <code>Jdk14Logger</code> for JDK 1.4 logging.
  -          </p>
  -        </subsection>
  -      </subsection>
  -      <subsection name="Parameters">
  -        <p>
  -          Avalon realizes that the Configuration object hierarchy can be
  -          heavy in many circumstances.  Therefore, we came up with a
  -          <code>Parameters</code> object that captures the
  -          convenience of <code>Configuration</code> objects with a
  -          simple name and value pair.
  -        </p>
  -        <subsection name="Parameterizable">
  -          <p>
  -            Any Component that wants to use <code>Parameters</code>
  -            instead of <code>Configuration</code> objects will
  -            implement this interface.  <code>Parameterizable</code>
  -            has one method named <code>parameterize</code> with the
  -            parameter being the <code>Parameters</code> object.
  -          </p>
  -          <p>
  -            The contract is that this is called once during the lifecycle of
  -            the Component.  This interface is not compatible with the
  -            <code>Configurable</code> interface.
  -          </p>
  -        </subsection>
  -        <subsection name="Parameters">
  -          <p>
  -            The <code>Parameters</code> object provides a mechanism
  -            to obtain a value based on a <code>String</code> name.
  -            There are convenience methods that allow you to use defaults if the
  -            value does not exist, as well as obtain the value in any of the
  -            same formats that are in the <code>Configurable</code>
  -            interface.
  -          </p>
  -          <p>
  -            While there are similarities between the
  -            <code>Parameters</code> object and the
  -            <code>java.util.Property</code> object, there are some
  -            important semantic differences.  First,
  -            <code>Parameters</code> are
  -            <em>read-only</em>. Second,
  -            <code>Parameters</code> are easily derived from
  -            <code>Configuration</code> objects.  Lastly, the
  -            <code>Parameters</code> object is derived from XML
  -            fragments that look like this:
  +            away the differences in logging systems.  It provides only a
  +            client API, and a fairly simple API that is.
             </p>
  -          <source>
  -<![CDATA[
  -<parameter name="param-name" value="param-value"/>
  -]]>
  -          </source>
           </subsection>
         </subsection>
  -      <subsection name="Component">
  +      <subsection name="Service">
           <p>
  -	  This used to be the core of Avalon Framework. The Component interface
  -	  and it friends have been deprecated in favor of the Service package,
  -	  which is exactly the same, except that the service package uses
  -	  java.lang.Object in place of the Component interface.
  -          Any interface defined in this
  -          concern area will throw ComponentException.
  +          This is the core of Avalon Framework. Any interface defined in this
  +          concern area will throw ServiceException.
           </p>
  -        <subsection name="Component">
  -          <p>
  -            Before the service package was put in place, every Avalon Component
  -	    had to implement the Component interface. We have removed this restriction
  -	    in the service package.
  -	    The Component Manager and Component Selector only handle Components.
  -	    There are no methods associated with this interface.  It is only used as
  -	    a marker interface.
  -          </p>
  -	  <p>
  -	    For maximum backward compatibility with existing applications, it can still
  -	    be useful to implement the Component interface as older applications may
  -	    depend on it being available.
  -	  </p>
  -          <p>
  -            Any Component must use default no parameter constructors.  All
  -            configurations are done with the
  -            <code>Configurable</code> or
  -            <code>Parameterizable</code> interfaces.
  -          </p>
  -        </subsection>
  -        <subsection name="Composable">
  +        <subsection name="Serviceable" >
             <p>
  -            A Component that uses other Components needs to implement either this
  -	    interface or the new Serviceable interface. The new interface is the
  -	    preferred way of doing things.  The interface has only one method
  -            <code>compose</code> with a
  -            <code>ComponentManager</code> passed in as the only
  +            A component that uses other components (what we call a 
  +            <em>Dependency</em> ) needs to implement this interface. The 
  +            interface has only one method <code>service</code> with a
  +            <code>ServiceManager</code> passed in as the only
               parameter.
             </p>
             <p>
               The contract surrounding this interface is that the
  -            <code>compose</code> is called once and only once during
  -            the lifetime of this Component.
  -          </p>
  -          <p>
  -            This interface along with any other interface that has methods
  -            specified uses the Inversion of Control pattern.  It is called by
  -            the Component's container, and only the Components that this
  -            Component needs should be present in the
  -            <code>ComponentManager</code>.
  -          </p>
  -        </subsection>
  -        <subsection name="Recomposable">
  -          <p>
  -            On rare occasions, a Component will need a new
  -            <code>ComponentManager</code> with new Component role
  -            mappings.  For those occasions, implement the recomposable
  -            interface.  It has a separate method from Composable called
  -            <code>recompose</code>.
  -          </p>
  -          <p>
  -            The contract surrounding the interface states that the
  -            <code>recompose</code> method can be called any number of
  -            times, but never before the Component is fully initialized.  When
  -            this method is called, the Component must update itself in a safe
  -            and consistent manner.  Usually this means all processing that the
  -            Component is performing must stop before the update and resume
  -            after the update.
  -          </p>
  -        </subsection>
  -      </subsection>
  -      <subsection name="Thread">
  -        <p>
  -          The thread marker interfaces are used to signal to the container
  -          essential semantic information regarding the Component use.  They
  -          mark a component implementation in regards to thread safety.  It is
  -          a best practice to delay implementing these interfaces until the
  -          final Component implementation class.  This avoids complications
  -          when an implementation is marked <code>ThreadSafe</code>,
  -          but a component that extends that implementation is not.  The
  -          interfaces defined in this package comprise part of what I call
  -          the <em>LifeStyle</em> interfaces.  There is one more
  -          <em>LifeStyle</em> interface that is part of the
  -          Excalibur package -- so it is an extension to this core
  -          set -- <code>Poolable</code> that is defined in
  -          Excalibur's pool implementations.
  -        </p>
  -        <subsection name="Single Threaded">
  -         <p>
  -            is that the interface or the implementation precludes this
  -            Component being accessed by several threads simultaneously.  Each
  -            thread needs its own instance of the Component.  Alternatively, you
  -            may use Component pooling instead of creating a new instance for
  -            every request for the Component.  In order to use pooling, you will
  -            need to implement Avalon Excalibur's <code>Poolable</code>
  -            interface instead of this one.
  -          </p>
  -        </subsection>
  -        <subsection name="ThreadSafe">
  -          <p>
  -            The contract with <code>ThreadSafe</code> Components is
  -            that both their interface and their implementation function
  -            correctly no matter how many threads access the Component
  -            simultaneously.  While this is generally a lofty design goal,
  -            sometimes it is simply not possible due to the technologies you are
  -            using.  A Component that implements this interface will generally
  -            only have one instance available in the system, and other
  -            Components will use that one instance.
  +            <code>service</code> is called once and only once during
  +            the lifetime of this component.
             </p>
           </subsection>
  -      </subsection>
  -      <subsection name="Miscellany">
  -        <p>
  -          The classes and interfaces in the root package for Avalon Framework
  -          incorporates Cascading Exceptions, and a couple of generic utilities.
  -          However, one class deserves mention beyond the others.
  -        </p>
  -        <subsection name="Version">
  -          <p>
  -            Java versioning techniques are entries in
  -            the manifest file in a jar.  The problem is, when the jar is
  -            unpacked you lose the versioning information, and the versioning
  -            is in an easily modified text file.  When you couple this with a
  -            higher learning curve, detecting Component or Interface versions
  -            is difficult.
  -          </p>
  +        <subsection name="ServiceManager">
             <p>
  -            The Avalon team came up with the Version object to allow you to
  -            have easily determined versions, and to compare versions.  You may
  -            implement the <code>Version</code> object in your
  -            Components and your tests for the proper Component or minimum
  -            version level will be much easier.
  +            The <code>ServiceManager</code> is passed to the components that
  +            implements the <code>Serviceable</code> interface in the 
  +            <code>service</code> method. The <code>ServiceManager</code> has
  +            a single method, <code>lookup</code>, which is used by the 
  +            component to locate its dependencies. It does this by passing a
  +            key in the moethod call and the <code>ServiceManager</code> will
  +            hand back a component reference of the requested <em>Service</em>.
  +            I.e. The component requests a <em>Service</em>, but doesn't need
  +            to be concerned about which implementation, and safely cast the
  +            returned object to the <em>Service Interface</em>.
  +            The component must declare which dependencies it has, and can
  +            explicitly also declare the key that will be used in the 
  +            <code>lookup</code> method call. If no key is defined, the 
  +            <em>Service Interface</em> name must be used.
             </p>
           </subsection>
         </subsection>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org


Mime
View raw message