avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From blorit...@apache.org
Subject cvs commit: jakarta-avalon/src/documentation/xdocs/developing implementing.xml
Date Tue, 30 Oct 2001 14:01:18 GMT
bloritsch    01/10/30 06:01:18

  Modified:    src/documentation/xdocs/developing implementing.xml
  Log:
  remove tabs
  
  Revision  Changes    Path
  1.5       +476 -476  jakarta-avalon/src/documentation/xdocs/developing/implementing.xml
  
  Index: implementing.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon/src/documentation/xdocs/developing/implementing.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- implementing.xml	2001/10/29 13:32:04	1.4
  +++ implementing.xml	2001/10/30 14:01:18	1.5
  @@ -41,51 +41,51 @@
         <title>Choosing the Concern Areas</title>
         <para>
           We have already defined the Role and the Interface for our
  -	DocumentRepository Component in the last chapter, we are ready to
  -	create the implementation.  Because the interface for the
  -	DocumentRepository only defines one method, we have an opportunity to
  -	create a thread-safe Component.  This is the most desired type of
  -	component because it allows for the least amount of resource
  -	utilization.  In order for our implementation to be thread-safe, we do
  -	need to be careful about how we implement the Component.  Since all of
  -	our documents are stored in a database, and we desire to use an
  -	external Guardian Component, we will need access to other Components.
  -	As responsible developers, we will want to log messages that will help
  -	us debug our component, and track down what is going on internally.
  -	The beauty of the Avalon Framework is that you only implement the
  -	interfaces you need, and ignore the ones you don't.  This is where
  -	Separation of Concerns pays off.  As you find you need a new concern
  -	area addressed, you merely implement the associated interface, and
  -	incorporate the new functionality.  To the client of your Component,
  -	there is no difference.
  +        DocumentRepository Component in the last chapter, we are ready to
  +        create the implementation.  Because the interface for the
  +        DocumentRepository only defines one method, we have an opportunity to
  +        create a thread-safe Component.  This is the most desired type of
  +        component because it allows for the least amount of resource
  +        utilization.  In order for our implementation to be thread-safe, we do
  +        need to be careful about how we implement the Component.  Since all of
  +        our documents are stored in a database, and we desire to use an
  +        external Guardian Component, we will need access to other Components.
  +        As responsible developers, we will want to log messages that will help
  +        us debug our component, and track down what is going on internally.
  +        The beauty of the Avalon Framework is that you only implement the
  +        interfaces you need, and ignore the ones you don't.  This is where
  +        Separation of Concerns pays off.  As you find you need a new concern
  +        area addressed, you merely implement the associated interface, and
  +        incorporate the new functionality.  To the client of your Component,
  +        there is no difference.
         </para>
         <para>
           Since it is a design goal to be thread-safe, we already know that we
  -	need to implement the ThreadSafe interface.  The DocumentRepository
  -	interface only has one method, so the use of the Component's work
  -	interface is compatible with that requirement.  Furthermore, we know
  -	that a Component will not be used before it is fully initialized, nor
  -	will it be used once it is destroyed.
  +        need to implement the ThreadSafe interface.  The DocumentRepository
  +        interface only has one method, so the use of the Component's work
  +        interface is compatible with that requirement.  Furthermore, we know
  +        that a Component will not be used before it is fully initialized, nor
  +        will it be used once it is destroyed.
         </para>
         <para>
           There are a couple of implicit interfaces that we need to implement to
  -	accomplish the design.  We want our solution to be as secure as
  -	possible and explicitly track whether the Component is fully
  -	initialized or not.  To accomplish this goal, we will implement the
  -	Initializable and Disposable interfaces.  Since specific information
  -	about our environment may change, or may need to be customized, we need
  -	to make our DocumentRepository Configurable.  Our Component makes use
  -	of other Components, and they method that Avalon provides to get
  -	instances of the required Component is by using a ComponentManager.  We
  -	will need to implement the Composable interface to get an instance of
  -	the ComponentManager.
  +        accomplish the design.  We want our solution to be as secure as
  +        possible and explicitly track whether the Component is fully
  +        initialized or not.  To accomplish this goal, we will implement the
  +        Initializable and Disposable interfaces.  Since specific information
  +        about our environment may change, or may need to be customized, we need
  +        to make our DocumentRepository Configurable.  Our Component makes use
  +        of other Components, and they method that Avalon provides to get
  +        instances of the required Component is by using a ComponentManager.  We
  +        will need to implement the Composable interface to get an instance of
  +        the ComponentManager.
         </para>
         <para>
           Because the DocumentRepository accesses the documents in the database,
  -	we need to make a decision.  Do we want to take advantage of the Avalon
  -	Excalibur DataSourceComponent, or do we want to implement our own
  -	Connection management code.  For the sake of this paper, we will use
  -	the DataSourceComponent.
  +        we need to make a decision.  Do we want to take advantage of the Avalon
  +        Excalibur DataSourceComponent, or do we want to implement our own
  +        Connection management code.  For the sake of this paper, we will use
  +        the DataSourceComponent.
         </para>
         <para>
           At this point, our skeleton class looks like this:
  @@ -116,12 +116,12 @@
       public final void configure(Configuration conf)
       throws ConfigurationException {
           if (initialized || disposed) {
  -	
  +        
               throw new IllegalStateException ("Illegal call");
           }
   
           if (null == this.dbResource) {
  -		    this.dbResource = conf.getChild("dbpool").getValue();
  +                    this.dbResource = conf.getChild("dbpool").getValue();
               getLogger().debug("Using database pool: " + this.dbResource);
               // Notice the getLogger()?  This is from AbstractLoggable
               // which I extend for just about all my components.
  @@ -145,11 +145,11 @@
       }
   
       public final void initialize() throws Exception {
  -	     if (null == this.manager) throw new IllegalStateException("Not Composed");
  +             if (null == this.manager) throw new IllegalStateException("Not Composed");
           if (null == this.dbResource)
  -		     throw new IllegalStateException("Not Configured");
  +                     throw new IllegalStateException("Not Configured");
   
  -		 if (disposed) throw new IllegalStateException("Already disposed");
  +                 if (disposed) throw new IllegalStateException("Already disposed");
   
           this.initialized = true;
       }
  @@ -170,56 +170,56 @@
         </programlisting>
         <para>
           You will notice some constructs in the above code.  When you are
  -	designing with security in mind, you should explicitly enforce every
  -	contract on your Component.  Security is only as strong as the weakest
  -	link.  You should only use a Component when you are certain it is fully
  -	initialized, and never use it when it is disposed of.  I placed the
  -	logic that you would need in this skeleton class because that way you
  -	can adopt the same practices in classes that you write.
  +        designing with security in mind, you should explicitly enforce every
  +        contract on your Component.  Security is only as strong as the weakest
  +        link.  You should only use a Component when you are certain it is fully
  +        initialized, and never use it when it is disposed of.  I placed the
  +        logic that you would need in this skeleton class because that way you
  +        can adopt the same practices in classes that you write.
         </para>
       </section>
       <section>
         <title>Instantiating and Managing Components</title>
         <para>
           In order for you to understand how the Container/Component relationship
  -	works, we will first discuss the manual method of managing Components.
  -	Next, we will discuss how Avalon's Excalibur Component infrastructure
  -	hides the complexity from you.  You will still find times when you
  -	would rather manage components yourself.  Most of the time the power
  -	and flexibility of Excalibur is just what you need.
  +        works, we will first discuss the manual method of managing Components.
  +        Next, we will discuss how Avalon's Excalibur Component infrastructure
  +        hides the complexity from you.  You will still find times when you
  +        would rather manage components yourself.  Most of the time the power
  +        and flexibility of Excalibur is just what you need.
         </para>
         <section>
           <title>The Manual Method</title>
  -	<para>
  -	  All of Avalon's Components are created somewhere.  The code that
  -	  creates the Component is that Component's Container.  The Container
  -	  is responsible for managing the Component's lifecycle from
  -	  construction through destruction.  A Container can be the static
  -	  "main" method called from a command line, or it can be another
  -	  Component.  Remember the Inversion of Control pattern when you
  -	  design your Containers.  Information and method calls should only
  -	  flow from the Container to the Component.
  -	</para>
  -	<warning>
  -	  <title>Subversion of Control</title>
  -	  <para>
  -	    Subversion of Control is the anti-pattern to Inversion of Control.
  -	    Subversion of control is done when you pass a reference to a
  -	    Component's Container to the Component.  It is also done when you
  -	    have a Component manage it's own lifecycle.  Code that operates in
  -	    this manner should be considered defective.  The interactions that
  -	    happen when you confuse the Container/Component relationship make
  -	    the system harder to debug and security harder to audit.
  -	  </para>
  -	</warning>
  -	<para>
  -	  In order to manage the child Components, you need to keep a reference
  -	  to them for their entire lifetime.  Before the Container or any other
  -	  Component can use the child Component, it must go through the
  -	  initialization phase of its lifecycle.  For our DocumentRepository,
  -	  the code will look something like the following:
  -	</para>
  -	<programlisting>
  +        <para>
  +          All of Avalon's Components are created somewhere.  The code that
  +          creates the Component is that Component's Container.  The Container
  +          is responsible for managing the Component's lifecycle from
  +          construction through destruction.  A Container can be the static
  +          "main" method called from a command line, or it can be another
  +          Component.  Remember the Inversion of Control pattern when you
  +          design your Containers.  Information and method calls should only
  +          flow from the Container to the Component.
  +        </para>
  +        <warning>
  +          <title>Subversion of Control</title>
  +          <para>
  +            Subversion of Control is the anti-pattern to Inversion of Control.
  +            Subversion of control is done when you pass a reference to a
  +            Component's Container to the Component.  It is also done when you
  +            have a Component manage it's own lifecycle.  Code that operates in
  +            this manner should be considered defective.  The interactions that
  +            happen when you confuse the Container/Component relationship make
  +            the system harder to debug and security harder to audit.
  +          </para>
  +        </warning>
  +        <para>
  +          In order to manage the child Components, you need to keep a reference
  +          to them for their entire lifetime.  Before the Container or any other
  +          Component can use the child Component, it must go through the
  +          initialization phase of its lifecycle.  For our DocumentRepository,
  +          the code will look something like the following:
  +        </para>
  +        <programlisting>
   <![CDATA[
   class ContainerComponent implements Component, Initializable, Disposable {
       DocumentRepository docs = new DatabaseDocumentRepository();
  @@ -251,136 +251,136 @@
       }
   }
   ]]>
  -	</programlisting>
  -	<para>
  -	  For the sake of brevity, I removed all the explicit checking from the
  -	  above code.  You can see that manually creating and managing
  -	  Components is very detailed.  If you forget to do one step in the
  -	  life of a Component, you will see bugs.  This also requires intimate
  -	  knowledge of the Components you are instantiating.  An alternate
  -	  approach would be to add a couple methods to the above
  -	  ContainerComponent that handles the initialization of the components
  -	  dynamically.
  -	</para>
  +        </programlisting>
  +        <para>
  +          For the sake of brevity, I removed all the explicit checking from the
  +          above code.  You can see that manually creating and managing
  +          Components is very detailed.  If you forget to do one step in the
  +          life of a Component, you will see bugs.  This also requires intimate
  +          knowledge of the Components you are instantiating.  An alternate
  +          approach would be to add a couple methods to the above
  +          ContainerComponent that handles the initialization of the components
  +          dynamically.
  +        </para>
         </section>
         <section>
           <title>Automated Autonomy</title>
  -	<para>
  -	  Developer's are naturally lazy, so they would spend the time to write
  -	  a specialized ComponentManager that became the Container for all of
  -	  their Components in the system.  That way they would not have to be
  -	  bothered with intimately knowing the interfaces of all the Components
  -	  in a system.  That can be a daunting task.  The Avalon developers
  -	  have created just such a beast.  Avalon Excalibur's Component
  -	  architecture includes a ComponentManager that is controlled by
  -	  configuration files written in XML.
  -	</para>
  -	<para>
  -	  There is a tradeoff when you relinquish the responsibility of
  -	  managing a Component to Excalibur's ComponentManager.  You relinquish
  -	  the fine control over what Components are included in the
  -	  ComponentManager.  However, if you have a large system, you will find
  -	  that manual control is a daunting task.  In that case, it is better
  -	  for the stability of the system for one entity to centrally manage
  -	  all the Components in a system.
  -	</para>
  -	<para>
  -	  Since there are varying levels of integration you want to achieve
  -	  with Excalibur's Component Architecture, we will start with the
  -	  lowest level.  Excalibur has a group of ComponentHandler objects that
  -	  act as individual Containers for one type of Component.  They manage
  -	  the complete life of your Component.  Let me introduce the concept of
  -	  lifestyle interfaces.  A lifestyle interface describes how the system
  -	  treats a Component.  Since the lifestyle of a component has impact on
  -	  the running of a system, we need to discuss the implications of the
  -	  current lifestyle interfaces:
  -	</para>
  -	<itemizedlist>
  -	  <listitem>
  -	    <para>org.apache.avalon.framework.thread.SingleThreaded</para>
  -	    <itemizedlist>
  -	      <listitem>
  -	        <para>
  -		  Not thread-safe or reusable.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -		  When no lifestyle interface is supplied, this is assumed.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -		  A brand new instance is created every time the Component is
  -		  requested.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -		  Creation and initialization is delayed until you request the
  -		  Component.
  -		</para>
  -	      </listitem>
  -	    </itemizedlist>
  -	  </listitem>
  -	  <listitem>
  -	    <para>org.apache.avalon.framework.thread.Threadsafe</para>
  -	    <itemizedlist>
  -	      <listitem>
  -	        <para>
  -		  Component is fully reentrant, and complies with all
  -		  principles of thread safety.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -		  One instance is created and shared with all Composables that
  -		  request it.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -			Creation and initialization is done when ComponentHandler is
  -		  created.
  -		</para>
  -	      </listitem>
  -	    </itemizedlist>
  -	  </listitem>
  -	  <listitem>
  -	    <para>org.apache.avalon.excalibur.pool.Poolable</para>
  -	    <itemizedlist>
  -	      <listitem>
  -	        <para>
  -		  Not thread-safe, but is fully reusable.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -		  A pool of instances is created and the free instances are
  -		  returned to Composables that request it.
  -		</para>
  -	      </listitem>
  -	      <listitem>
  -	        <para>
  -			Creation and initialization is done when ComponentHandler is
  -		  created.
  -		</para>
  -	      </listitem>
  -	    </itemizedlist>
  -	  </listitem>
  -	</itemizedlist>
  -	<para>
  -	  The ComponentHandler interface is very simple to deal with.  You
  -	  initialize the Constructor with the Java class, the Configuration
  -	  object, the ConfigurationManager, a Context object, and a
  -	  RoleManager.  If you know that your Component will not need any of
  -	  the aforementioned items, you can pass a null in its place.  After
  -	  that, when you need a reference to the Component, you call the "get"
  -	  method.  After you are done with it, you call the "put" method and
  -	  pass the Component back to the ComponentHandler.  The following code
  -	  will make it easier to understand.
  -	</para>
  -	<programlisting>
  +        <para>
  +          Developer's are naturally lazy, so they would spend the time to write
  +          a specialized ComponentManager that became the Container for all of
  +          their Components in the system.  That way they would not have to be
  +          bothered with intimately knowing the interfaces of all the Components
  +          in a system.  That can be a daunting task.  The Avalon developers
  +          have created just such a beast.  Avalon Excalibur's Component
  +          architecture includes a ComponentManager that is controlled by
  +          configuration files written in XML.
  +        </para>
  +        <para>
  +          There is a tradeoff when you relinquish the responsibility of
  +          managing a Component to Excalibur's ComponentManager.  You relinquish
  +          the fine control over what Components are included in the
  +          ComponentManager.  However, if you have a large system, you will find
  +          that manual control is a daunting task.  In that case, it is better
  +          for the stability of the system for one entity to centrally manage
  +          all the Components in a system.
  +        </para>
  +        <para>
  +          Since there are varying levels of integration you want to achieve
  +          with Excalibur's Component Architecture, we will start with the
  +          lowest level.  Excalibur has a group of ComponentHandler objects that
  +          act as individual Containers for one type of Component.  They manage
  +          the complete life of your Component.  Let me introduce the concept of
  +          lifestyle interfaces.  A lifestyle interface describes how the system
  +          treats a Component.  Since the lifestyle of a component has impact on
  +          the running of a system, we need to discuss the implications of the
  +          current lifestyle interfaces:
  +        </para>
  +        <itemizedlist>
  +          <listitem>
  +            <para>org.apache.avalon.framework.thread.SingleThreaded</para>
  +            <itemizedlist>
  +              <listitem>
  +                <para>
  +                  Not thread-safe or reusable.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                  When no lifestyle interface is supplied, this is assumed.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                  A brand new instance is created every time the Component is
  +                  requested.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                  Creation and initialization is delayed until you request the
  +                  Component.
  +                </para>
  +              </listitem>
  +            </itemizedlist>
  +          </listitem>
  +          <listitem>
  +            <para>org.apache.avalon.framework.thread.Threadsafe</para>
  +            <itemizedlist>
  +              <listitem>
  +                <para>
  +                  Component is fully reentrant, and complies with all
  +                  principles of thread safety.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                  One instance is created and shared with all Composables that
  +                  request it.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                        Creation and initialization is done when ComponentHandler is
  +                  created.
  +                </para>
  +              </listitem>
  +            </itemizedlist>
  +          </listitem>
  +          <listitem>
  +            <para>org.apache.avalon.excalibur.pool.Poolable</para>
  +            <itemizedlist>
  +              <listitem>
  +                <para>
  +                  Not thread-safe, but is fully reusable.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                  A pool of instances is created and the free instances are
  +                  returned to Composables that request it.
  +                </para>
  +              </listitem>
  +              <listitem>
  +                <para>
  +                        Creation and initialization is done when ComponentHandler is
  +                  created.
  +                </para>
  +              </listitem>
  +            </itemizedlist>
  +          </listitem>
  +        </itemizedlist>
  +        <para>
  +          The ComponentHandler interface is very simple to deal with.  You
  +          initialize the Constructor with the Java class, the Configuration
  +          object, the ConfigurationManager, a Context object, and a
  +          RoleManager.  If you know that your Component will not need any of
  +          the aforementioned items, you can pass a null in its place.  After
  +          that, when you need a reference to the Component, you call the "get"
  +          method.  After you are done with it, you call the "put" method and
  +          pass the Component back to the ComponentHandler.  The following code
  +          will make it easier to understand.
  +        </para>
  +        <programlisting>
   <![CDATA[
   class ContainerComponent implements Component, Initializable, Disposable {
       ComponentHandler docs = null;
  @@ -417,20 +417,20 @@
       }
   }
   ]]>
  -	</programlisting>
  -	<para>
  -	  At this point, we only saved ourselves a few lines of code.  We still
  -	  manually created our Configuration object, we still had to set the
  -	  Logger, and we still had to initialize and dispose of the
  -	  ComponentHandler objects.  What we did at this point is simply protect
  -	  ourselves from changing interfaces.  You may find it better for your
  -	  code to use this approach.  Excalibur went further though.  Most
  -	  complex systems have configuration files, and they allow an
  -	  administrator to alter vital Configuration information.  Excalibur
  -	  can read a configuration file in the following format, and build the
  -	  Components in a system from it.
  -	</para>
  -	<programlisting>
  +        </programlisting>
  +        <para>
  +          At this point, we only saved ourselves a few lines of code.  We still
  +          manually created our Configuration object, we still had to set the
  +          Logger, and we still had to initialize and dispose of the
  +          ComponentHandler objects.  What we did at this point is simply protect
  +          ourselves from changing interfaces.  You may find it better for your
  +          code to use this approach.  Excalibur went further though.  Most
  +          complex systems have configuration files, and they allow an
  +          administrator to alter vital Configuration information.  Excalibur
  +          can read a configuration file in the following format, and build the
  +          Components in a system from it.
  +        </para>
  +        <programlisting>
   <![CDATA[
   <my-system>
     <component
  @@ -440,7 +440,7 @@
          class="org.apache.avalon.excalibur.datasource.JdbcDataSource">
            <pool-controller min="5" max="10"/>
            <auto-commit>false</auto-commit>
  -	 <driver>org.mysql.MySqlDriver</driver>
  +         <driver>org.mysql.MySqlDriver</driver>
            <dburl>jdbc:mysql:localhost/mydb</dburl>
            <user>test</user>
            <password>test</password>
  @@ -449,7 +449,7 @@
           class="org.apache.avalon.excalibur.datasource.JdbcDataSource">
            <pool-controller min="5" max="10"/>
            <auto-commit>false</auto-commit>
  -	 <driver>org.mysql.MySqlDriver</driver>
  +         <driver>org.mysql.MySqlDriver</driver>
            <dburl>jdbc:mysql:localhost/myotherdb</dburl>
            <user>test</user>
            <password>test</password>
  @@ -468,32 +468,32 @@
     </component>
   </my-system>
   ]]>
  -	</programlisting>
  -	<para>
  -	  The root element can be anything you want.  You will notice that we
  -	  now have several Components defined.  We have our familiar
  -	  DocumentRepository class and GuardianComponent class, as well as a
  -	  couple of Excalibur DataSourceComponent classes.  In addition, now we
  -	  have some specific configuration information for our Guardian
  -	  Component.  In order to read that information into your system,
  -	  Avalon Framework provides some conveniences for you:
  -	</para>
  -	<programlisting>
  +        </programlisting>
  +        <para>
  +          The root element can be anything you want.  You will notice that we
  +          now have several Components defined.  We have our familiar
  +          DocumentRepository class and GuardianComponent class, as well as a
  +          couple of Excalibur DataSourceComponent classes.  In addition, now we
  +          have some specific configuration information for our Guardian
  +          Component.  In order to read that information into your system,
  +          Avalon Framework provides some conveniences for you:
  +        </para>
  +        <programlisting>
   <![CDATA[
   DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
   Configuration systemConf = builder.buildFromFile("/path/to/file.xconf");
   ]]>
  -	</programlisting>
  -	<para>
  -	  This does simplify all the code we had for hand-building the
  -	  Configuration element earlier, and it limits the amount of
  -	  information we need to implicitly know right away.  We will take one
  -	  last look at our Container class and see if we really have some
  -	  savings.  Keep in mind that we have five components specified (a
  -	  ComponentSelector counts as a Component), and configurations for
  -	  each of them.
  -	</para>
  -	<programlisting>
  +        </programlisting>
  +        <para>
  +          This does simplify all the code we had for hand-building the
  +          Configuration element earlier, and it limits the amount of
  +          information we need to implicitly know right away.  We will take one
  +          last look at our Container class and see if we really have some
  +          savings.  Keep in mind that we have five components specified (a
  +          ComponentSelector counts as a Component), and configurations for
  +          each of them.
  +        </para>
  +        <programlisting>
   <![CDATA[
   class ContainerComponent implements Component, Initializable, Disposable {
       ExcaliburComponentManager manager = new ExcaliburComponentManager();
  @@ -514,38 +514,38 @@
       }
   }
   ]]>
  -	</programlisting>
  -	<para>
  -	  Isn't this amazing?  We have more than twice the number Components
  -	  initialized and ready for use with less than half the code (six lines
  -	  of code instead of thirteen lines of code).  There is the drawback of
  -	  the Configuration file looking somewhat crazy, but it minimizes the
  -	  amount of code you have to write.
  -	</para>
  -	<para>
  -	  There is a lot of activity happening under the hood of the
  -	  ExcaliburComponentManager.  For each "component" element in the
  -	  configuration file, Excalibur creates a ComponentHandler for each
  -	  class entry and maps it to the role entry.  The "component" element
  -	  and all it's child elements are used for the Configuration of the
  -	  Component.  When the Component is an ExcaliburComponentSelector, the
  -	  Excalibur reads each "component-instance" element and performs the
  -	  same type of operation as before-this time mapping to the hint entry.
  -	</para>
  -	<section>
  -	  <title>Making the Configuration Pretty</title>
  -	  <para>
  -	    We can manage the configuration file's appearance with the use of
  -	    aliases.  Excalibur uses a RoleManager to provide aliases for the
  -	    configuration system.  A RoleManager can either be a dedicated
  -	    class that you create, or you can use the DefaultRoleManager and
  -	    pass in a Configuration object.  If I use the DefaultRoleManager, I
  -	    will hide the role configuration file inside the jar with the rest
  -	    of the system.  This is because the role configuration file is only
  -	    going to be altered by developers.  Below is the interface for the
  -	    RoleManager:
  -	  </para>
  -	  <programlisting>
  +        </programlisting>
  +        <para>
  +          Isn't this amazing?  We have more than twice the number Components
  +          initialized and ready for use with less than half the code (six lines
  +          of code instead of thirteen lines of code).  There is the drawback of
  +          the Configuration file looking somewhat crazy, but it minimizes the
  +          amount of code you have to write.
  +        </para>
  +        <para>
  +          There is a lot of activity happening under the hood of the
  +          ExcaliburComponentManager.  For each "component" element in the
  +          configuration file, Excalibur creates a ComponentHandler for each
  +          class entry and maps it to the role entry.  The "component" element
  +          and all it's child elements are used for the Configuration of the
  +          Component.  When the Component is an ExcaliburComponentSelector, the
  +          Excalibur reads each "component-instance" element and performs the
  +          same type of operation as before-this time mapping to the hint entry.
  +        </para>
  +        <section>
  +          <title>Making the Configuration Pretty</title>
  +          <para>
  +            We can manage the configuration file's appearance with the use of
  +            aliases.  Excalibur uses a RoleManager to provide aliases for the
  +            configuration system.  A RoleManager can either be a dedicated
  +            class that you create, or you can use the DefaultRoleManager and
  +            pass in a Configuration object.  If I use the DefaultRoleManager, I
  +            will hide the role configuration file inside the jar with the rest
  +            of the system.  This is because the role configuration file is only
  +            going to be altered by developers.  Below is the interface for the
  +            RoleManager:
  +          </para>
  +          <programlisting>
   <![CDATA[
   interface RoleManager {
       String getRoleForName( String shorthandName );
  @@ -553,26 +553,26 @@
       String getDefaultClassNameForHint( String hint, String shorthand );
   }
   ]]>
  -	  </programlisting>
  -	  <para>
  -	    Let's take a look at how Excalibur uses the RoleManager in our
  -	    scheme.  First, Excalibur will cycle through all the elements that
  -	    are direct children of the root element.  This includes all
  -	    "component" elements like before, but this time when Excalibur
  -	    doesn't recognize an element name, it asks the RoleManager which
  -	    role we should use for this Component.  If the RoleManager returns
  -	    null, the element and all it's child elements are ignored.  Next,
  -	    Excalibur derives the class name from the role name.  The last
  -	    method is to dynamically map a class name to a ComponentSelector's
  -	    child type.
  -	  </para>
  -	  <para>
  -	    Excalibur provides a default implementation of the RoleManager that
  -	    is configured with an XML configuration file.  The markup is very
  -	    simple, and it hides all the extra information you don't want your
  -	    administrator to see.
  -	  </para>
  -	  <programlisting>
  +          </programlisting>
  +          <para>
  +            Let's take a look at how Excalibur uses the RoleManager in our
  +            scheme.  First, Excalibur will cycle through all the elements that
  +            are direct children of the root element.  This includes all
  +            "component" elements like before, but this time when Excalibur
  +            doesn't recognize an element name, it asks the RoleManager which
  +            role we should use for this Component.  If the RoleManager returns
  +            null, the element and all it's child elements are ignored.  Next,
  +            Excalibur derives the class name from the role name.  The last
  +            method is to dynamically map a class name to a ComponentSelector's
  +            child type.
  +          </para>
  +          <para>
  +            Excalibur provides a default implementation of the RoleManager that
  +            is configured with an XML configuration file.  The markup is very
  +            simple, and it hides all the extra information you don't want your
  +            administrator to see.
  +          </para>
  +          <programlisting>
   <![CDATA[
   <role-list>
     <role
  @@ -594,18 +594,18 @@
       "org.apache.bizserver.docs.DocumentGuardianComponent"/>
   </role-list>
   ]]>
  -	  </programlisting>
  -	  <para>
  -	    In order to use the RoleManager, you do need to alter the
  -	    "initialize" method of our Container class.  You are using the
  -	    configuration builder to build a Configuration tree from this
  -	    file.  Please remember, if you are going to use a RoleManager, you
  -	    must call the "setRoleManager" method <emphasis>before</emphasis>
  -	    the "configure" method.  To demonstrate how you would retrieve this
  -	    XML file from the class loader, I will demonstrate the technique
  -	    below:
  -	  </para>
  -	  <programlisting>
  +          </programlisting>
  +          <para>
  +            In order to use the RoleManager, you do need to alter the
  +            "initialize" method of our Container class.  You are using the
  +            configuration builder to build a Configuration tree from this
  +            file.  Please remember, if you are going to use a RoleManager, you
  +            must call the "setRoleManager" method <emphasis>before</emphasis>
  +            the "configure" method.  To demonstrate how you would retrieve this
  +            XML file from the class loader, I will demonstrate the technique
  +            below:
  +          </para>
  +          <programlisting>
   <![CDATA[
   DefaultConfigurationBuilder builder =
               new DefaultConfigurationBuilder();
  @@ -624,12 +624,12 @@
   this.manager.configure(sysConfig);
   this.manager.initialize();
   ]]>
  -	  </programlisting>
  -	  <para>
  -	    Since we added six more lines of code, we need to see what it
  -	    bought us.  Our final configuration file can be written like this:
  -	  </para>
  -	  <programlisting>
  +          </programlisting>
  +          <para>
  +            Since we added six more lines of code, we need to see what it
  +            bought us.  Our final configuration file can be written like this:
  +          </para>
  +          <programlisting>
   <![CDATA[
   <my-system>
     <datasources>
  @@ -657,13 +657,13 @@
     </guardian>
   </my-system>
   ]]>
  -	  </programlisting>
  -	  <para>
  -	    As you can see, this is much more readable than how we started.
  -	    Now we can add any number of components to our system, and we won't
  -	    have to write any more code to support them.
  -	  </para>
  -	</section>
  +          </programlisting>
  +          <para>
  +            As you can see, this is much more readable than how we started.
  +            Now we can add any number of components to our system, and we won't
  +            have to write any more code to support them.
  +          </para>
  +        </section>
         </section>
       </section>
     </section>
  @@ -683,25 +683,25 @@
         <title>Rules for Using the Component Management Infrastructure</title>
         <para>
           The Component management infrastructure requires that you release any
  -	Component for which you have obtained a reference.  The reason for this
  -	restriction is so that the Component's resources can be properly
  -	managed.  A ComponentManager is designed for instances when you have
  -	multiple types of Components with distinct roles.  A ComponentSelector
  -	is designed for instances when you have multiple types of Components
  -	with the same role.  Another unique aspect of the ComponentSelector is
  -	that it is a Component by design.  This enables us to get a
  -	ComponentSelector from a ComponentManager.
  +        Component for which you have obtained a reference.  The reason for this
  +        restriction is so that the Component's resources can be properly
  +        managed.  A ComponentManager is designed for instances when you have
  +        multiple types of Components with distinct roles.  A ComponentSelector
  +        is designed for instances when you have multiple types of Components
  +        with the same role.  Another unique aspect of the ComponentSelector is
  +        that it is a Component by design.  This enables us to get a
  +        ComponentSelector from a ComponentManager.
         </para>
         <para>
           There are two valid approaches for handling references to external
  -	Components.  You can obtain your references during initialization, and
  -	release them during disposal.  You may also encapsulate the Component
  -	handling in a try/catch/finally block.  Each has its advantages and
  -	disadvantages.
  +        Components.  You can obtain your references during initialization, and
  +        release them during disposal.  You may also encapsulate the Component
  +        handling in a try/catch/finally block.  Each has its advantages and
  +        disadvantages.
         </para>
         <section>
           <title>Initialization and Disposal Approach</title>
  -	<programlisting>
  +        <programlisting>
   <![CDATA[
   class MyClass implements Component, Composable, Disposable {
       ComponentManager manager;
  @@ -736,44 +736,44 @@
       }
   }
   ]]>
  -	</programlisting>
  -	<para>
  -	  As you can see by the sample code, this is easy to follow.  The
  -	  object gets a reference to a Guardian Component when it first
  -	  receives the ComponentManager.  If you could be guaranteed that the
  -	  Guardian Component was ThreadSafe, then this is all that is
  -	  necessary.  Unfortunately, you cannot guarantee this for the long
  -	  term.  To properly manage resources, we must release the Component
  -	  when we are done with it.  That's why we kept a reference to the
  -	  ComponentManager.
  -	</para>
  -	<para>
  -	  The main disadvantage of this approach comes into play when you are
  -	  dealing with pooled Components.  The reference of the Component is
  -	  kept for the life of this object.  It might not be a problem if the
  -	  object had a short life span, but if it was a Component managed by
  -	  the Excalibur component management architecture, its life span is as
  -	  long as the Component whose reference it has.  What this means is
  -	  that we are essentially turning the Component's pool into a Factory.
  -	</para>
  -	<para>
  -	  The main advantage of this approach is that the code is very clear on
  -	  how a Component is obtained and released.  You don't have to have any
  -	  understanding of exception handling.
  -	</para>
  -	<para>
  -	  One other nuance is that you are tying the existence of the Guardian
  -	  to the ability to initialize this object.  Once an Exception is
  -	  thrown during the initialization phase of an object, you must assume
  -	  that the object is not valid.  Sometimes you want to fail if a
  -	  required Component does not exist so this is not a problem.  You do
  -	  need to be aware of this implication when you are designing your
  -	  Components though.
  -	</para>
  +        </programlisting>
  +        <para>
  +          As you can see by the sample code, this is easy to follow.  The
  +          object gets a reference to a Guardian Component when it first
  +          receives the ComponentManager.  If you could be guaranteed that the
  +          Guardian Component was ThreadSafe, then this is all that is
  +          necessary.  Unfortunately, you cannot guarantee this for the long
  +          term.  To properly manage resources, we must release the Component
  +          when we are done with it.  That's why we kept a reference to the
  +          ComponentManager.
  +        </para>
  +        <para>
  +          The main disadvantage of this approach comes into play when you are
  +          dealing with pooled Components.  The reference of the Component is
  +          kept for the life of this object.  It might not be a problem if the
  +          object had a short life span, but if it was a Component managed by
  +          the Excalibur component management architecture, its life span is as
  +          long as the Component whose reference it has.  What this means is
  +          that we are essentially turning the Component's pool into a Factory.
  +        </para>
  +        <para>
  +          The main advantage of this approach is that the code is very clear on
  +          how a Component is obtained and released.  You don't have to have any
  +          understanding of exception handling.
  +        </para>
  +        <para>
  +          One other nuance is that you are tying the existence of the Guardian
  +          to the ability to initialize this object.  Once an Exception is
  +          thrown during the initialization phase of an object, you must assume
  +          that the object is not valid.  Sometimes you want to fail if a
  +          required Component does not exist so this is not a problem.  You do
  +          need to be aware of this implication when you are designing your
  +          Components though.
  +        </para>
         </section>
         <section>
           <title>Exception Handling Approach</title>
  -	<programlisting>
  +        <programlisting>
   <![CDATA[
   class MyClass implements Composable, Disposable {
       ComponentManager manager;
  @@ -816,72 +816,72 @@
       }
   }
   ]]>
  -	</programlisting>
  -	<para>
  -	  As you can see, the code is a bit more complex.  In order to
  -	  understand it, you have to understand Exception handling.  This is
  -	  not necessarily a problem, because most Java developers know how to
  -	  handle them.  You don't have to worry so much about the Component
  -	  life style with this approach, because we are releasing it as soon
  -	  as we no longer need it.
  -	</para>
  -	<para>
  -	  The main disadvantage of this approach is the added complexity of the
  -	  exception handling code.  In order to minimize the complexity and
  -	  make the code more maintainable, we extracted the working code into
  -	  another method.  Keep in mind that we can get the reference to as
  -	  many Components as we possibly want inside the try block.
  -	</para>
  -	<para>
  -	  The main advantage of this approach is that you are managing your
  -	  Component references more efficiently.  Again, there is no real
  -	  difference if you are using ThreadSafe Components, but it makes a
  -	  real difference when you have pooled Components.  There is a slight
  -	  overhead dealing with getting a new reference every time you use a
  -	  Component, but the likelihood of being forced to create a new
  -	  instance of the Component is minimized.
  -	</para>
  -	<para>
  -	  Just like the Initialization and Disposal Approach, you have to
  -	  understand a subtle nuance.  The Exception Handling Approach does not
  -	  fail on initialization if the Component is missing from the manager.
  -	  As mentioned before, this is not entirely bad.  Many times, you want
  -	  an object to exist, but it is not a failure if a required Component
  -	  is missing.
  -	</para>
  +        </programlisting>
  +        <para>
  +          As you can see, the code is a bit more complex.  In order to
  +          understand it, you have to understand Exception handling.  This is
  +          not necessarily a problem, because most Java developers know how to
  +          handle them.  You don't have to worry so much about the Component
  +          life style with this approach, because we are releasing it as soon
  +          as we no longer need it.
  +        </para>
  +        <para>
  +          The main disadvantage of this approach is the added complexity of the
  +          exception handling code.  In order to minimize the complexity and
  +          make the code more maintainable, we extracted the working code into
  +          another method.  Keep in mind that we can get the reference to as
  +          many Components as we possibly want inside the try block.
  +        </para>
  +        <para>
  +          The main advantage of this approach is that you are managing your
  +          Component references more efficiently.  Again, there is no real
  +          difference if you are using ThreadSafe Components, but it makes a
  +          real difference when you have pooled Components.  There is a slight
  +          overhead dealing with getting a new reference every time you use a
  +          Component, but the likelihood of being forced to create a new
  +          instance of the Component is minimized.
  +        </para>
  +        <para>
  +          Just like the Initialization and Disposal Approach, you have to
  +          understand a subtle nuance.  The Exception Handling Approach does not
  +          fail on initialization if the Component is missing from the manager.
  +          As mentioned before, this is not entirely bad.  Many times, you want
  +          an object to exist, but it is not a failure if a required Component
  +          is missing.
  +        </para>
         </section>
       </section>
       <section>
         <title>Getting Components from a ComponentSelector</title>
         <para>
           For most operations, you will only need the ComponentManager.  Since we
  -	decided that we needed multiple instances of the DataSourceComponent,
  -	we need to know how to get the instance we want.  ComponentSelectors
  -	are a little trickier than ComponentManagers because we are dealing
  -	with hints to get the reference we need.  A Component has a specific
  -	Role, and this contract is well documented.  However, sometimes we need
  -	to select one of many Components for a Role.  A ComponentSelector uses
  -	an arbitrary object for the hint.  Most of the time, the object is a
  -	String, although you might want to use a Locale object to get a proper
  -	internationalization Component.
  +        decided that we needed multiple instances of the DataSourceComponent,
  +        we need to know how to get the instance we want.  ComponentSelectors
  +        are a little trickier than ComponentManagers because we are dealing
  +        with hints to get the reference we need.  A Component has a specific
  +        Role, and this contract is well documented.  However, sometimes we need
  +        to select one of many Components for a Role.  A ComponentSelector uses
  +        an arbitrary object for the hint.  Most of the time, the object is a
  +        String, although you might want to use a Locale object to get a proper
  +        internationalization Component.
         </para>
         <para>
           In our system we have set up, we chose to use Strings to select the
  -	correct instance of the DataSourceComponent.  We even gave ourselves a
  -	Configuration element that references the exact string we need to get
  -	the right Component.  This is a good practice to follow, as it makes it
  -	easier on administrators of a system.  It is easier for an
  -	administrator to see a reference to another Component than it is for
  -	them to remember magic values for the configuration.
  +        correct instance of the DataSourceComponent.  We even gave ourselves a
  +        Configuration element that references the exact string we need to get
  +        the right Component.  This is a good practice to follow, as it makes it
  +        easier on administrators of a system.  It is easier for an
  +        administrator to see a reference to another Component than it is for
  +        them to remember magic values for the configuration.
         </para>
         <para>
           Conceptually, getting a Component from a ComponentSelector is no
  -	different than getting a Component from a ComponentManager.  You just
  -	have one more step.  Remember that a ComponentSelector is a Component.
  -	The ComponentManager will be set up to return the ComponentSelector
  -	when you lookup its role.  You then need to select the component from
  -	the selector.  To demonstrate, I will extend the code from the
  -	Exception Handling Approach discussed previously.
  +        different than getting a Component from a ComponentManager.  You just
  +        have one more step.  Remember that a ComponentSelector is a Component.
  +        The ComponentManager will be set up to return the ComponentSelector
  +        when you lookup its role.  You then need to select the component from
  +        the selector.  To demonstrate, I will extend the code from the
  +        Exception Handling Approach discussed previously.
         </para>
         <programlisting>
   <![CDATA[
  @@ -911,17 +911,17 @@
         </programlisting>
         <para>
           As you can see, we got the reference to the ComponentSelector using the
  -	Role specified for the Component.  We followed the Role naming
  -	guidelines outlined in a previous chapter by adding the "Selector"
  -	suffix to the Role name.  It is also perfectly acceptable to use a
  -	static interface for all the Role names in your system to minimize the
  -	number of String concatenation in your code.
  +        Role specified for the Component.  We followed the Role naming
  +        guidelines outlined in a previous chapter by adding the "Selector"
  +        suffix to the Role name.  It is also perfectly acceptable to use a
  +        static interface for all the Role names in your system to minimize the
  +        number of String concatenation in your code.
         </para>
         <para>
           Next, we obtained the reference to the DataSourceComponent from the
  -	ComponentSelector.  Our sample code assumed that we had already pulled
  -	the required information from the Configuration object and placed it in
  -	a class variable named "useDb".
  +        ComponentSelector.  Our sample code assumed that we had already pulled
  +        the required information from the Configuration object and placed it in
  +        a class variable named "useDb".
         </para>
       </section>
     </section>
  @@ -940,90 +940,90 @@
         <title>Command Line Interface (CLI)</title>
         <para>
           The CLI utilities are used by a number of projects including Avalon
  -	Phoenix and Apache Cocoon to process command line arguments.  It
  -	provides facilities to print help responses, and to process options by
  -	either a short name or a long name.
  +        Phoenix and Apache Cocoon to process command line arguments.  It
  +        provides facilities to print help responses, and to process options by
  +        either a short name or a long name.
         </para>
       </section>
       <section>
         <title>Collection Utilities</title>
         <para>
           The collection utilities provide some enhancements to the 
  -	<trademark>Java</trademark> Collections API.  Among them is the ability
  -	to find the intersections between two lists and a
  -	<classname>PriorityQueue</classname> that is an enhancement to
  -	<classname>Stack</classname> to allow the priority of objects override
  -	the simple first in/last out <classname>Stack</classname>
  -	implementation.
  +        <trademark>Java</trademark> Collections API.  Among them is the ability
  +        to find the intersections between two lists and a
  +        <classname>PriorityQueue</classname> that is an enhancement to
  +        <classname>Stack</classname> to allow the priority of objects override
  +        the simple first in/last out <classname>Stack</classname>
  +        implementation.
         </para>
       </section>
       <section>
         <title>Component Management</title>
         <para>
           We already discussed the use of this in the previous section.  This is
  -	Excalibur's most complex beast, but it provides a lot of functionality
  -	in just a few classes.  It will make one distinction more than simple
  -	<classname>SingleThreaded</classname> or
  -	<classname>ThreadSafe</classname> for managing a component type:
  -	<classname>Poolable</classname>.  If a Component implements Excalibur's
  -	<classname>Poolable</classname> interface instead of the
  -	<classname>SingleThreaded</classname> interface, it will maintain a
  -	pool of Components and reuse instances.  Most of the time this works
  -	great.  For those last remaining times where a Component cannot be
  -	reused, use the <classname>SingleThreaded</classname> interface.
  +        Excalibur's most complex beast, but it provides a lot of functionality
  +        in just a few classes.  It will make one distinction more than simple
  +        <classname>SingleThreaded</classname> or
  +        <classname>ThreadSafe</classname> for managing a component type:
  +        <classname>Poolable</classname>.  If a Component implements Excalibur's
  +        <classname>Poolable</classname> interface instead of the
  +        <classname>SingleThreaded</classname> interface, it will maintain a
  +        pool of Components and reuse instances.  Most of the time this works
  +        great.  For those last remaining times where a Component cannot be
  +        reused, use the <classname>SingleThreaded</classname> interface.
         </para>
       </section>
       <section>
         <title>Thread Utilities</title>
         <para>
           The <emphasis>concurrent</emphasis> package contains several classes
  -	to assist in multithreaded programming: <classname>Lock</classname>
  -	(a mutex implementation), <classname>DjikstraSemaphore</classname>,
  -	<classname>ConditionalEvent</classname>, and
  -	<classname>ThreadBarrier</classname>.
  +        to assist in multithreaded programming: <classname>Lock</classname>
  +        (a mutex implementation), <classname>DjikstraSemaphore</classname>,
  +        <classname>ConditionalEvent</classname>, and
  +        <classname>ThreadBarrier</classname>.
         </para>
       </section>
       <section>
         <title>Datasources</title>
         <para>
           This is modeled after the <classname>javax.sql.DataSource</classname>
  -	class, but simplified.  There are two implementations of the
  -	<classname>DataSourceComponent</classname>: one that pools JDBC
  -	connections explicitly, and one that uses a J2EE application server's
  -	<classname>javax.sql.DataSource</classname> class.
  +        class, but simplified.  There are two implementations of the
  +        <classname>DataSourceComponent</classname>: one that pools JDBC
  +        connections explicitly, and one that uses a J2EE application server's
  +        <classname>javax.sql.DataSource</classname> class.
         </para>
       </section>
       <section>
         <title>Input/Output (IO) Utilities</title>
         <para>
           The IO utilties provide a number of <classname>FileFilter</classname>s
  -	and other <classname>File</classname> and IO specific utilities.
  +        and other <classname>File</classname> and IO specific utilities.
         </para>
       </section>
       <section>
         <title>Pool Implementations</title>
         <para>
           The Pool implementations provide a <classname>Pool</classname> for
  -	every occasion.  You have an implementation that is blazingly fast, but
  -	only usable in one thread&mdash;which should be ok for implementing a
  -	FlyWeight pattern.  You also have <classname>DefaultPool</classname>,
  -	which does not manage the number of objects in its pool.
  -	<classname>SoftResourceManagingPool</classname> decommissions objects
  -	that exceed a threshold when they are returned.  Lastly,
  -	<classname>HardResourceManagingPool</classname> throws an exception
  -	when you have reached the maximum number of objects.  The last three
  -	pools are all <classname>ThreadSafe</classname>.
  +        every occasion.  You have an implementation that is blazingly fast, but
  +        only usable in one thread&mdash;which should be ok for implementing a
  +        FlyWeight pattern.  You also have <classname>DefaultPool</classname>,
  +        which does not manage the number of objects in its pool.
  +        <classname>SoftResourceManagingPool</classname> decommissions objects
  +        that exceed a threshold when they are returned.  Lastly,
  +        <classname>HardResourceManagingPool</classname> throws an exception
  +        when you have reached the maximum number of objects.  The last three
  +        pools are all <classname>ThreadSafe</classname>.
         </para>
       </section>
       <section>
         <title>Property Utilities</title>
         <para>
           The property utilities are used in conjunction with Context objects.
  -	They give you the ability to expand "variables" in your
  -	<classname>Resolvable</classname> object.  It works like this:
  -	<parameter>"${resource}"</parameter> will look for a Context value
  -	named <parameter>"resource"</parameter> and substitute its value
  -	for the symbol.
  +        They give you the ability to expand "variables" in your
  +        <classname>Resolvable</classname> object.  It works like this:
  +        <parameter>"${resource}"</parameter> will look for a Context value
  +        named <parameter>"resource"</parameter> and substitute its value
  +        for the symbol.
         </para>
       </section>
     </section>
  
  
  

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


Mime
View raw message