leosimons    2002/11/22 13:47:21

  Added:       interceptor/src/xdocs interceptor.xml
  Log:
  Some initial thoughts on interceptor architecture. Submitted by Peter Donald
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/interceptor/src/xdocs/interceptor.xml
  
  Index: interceptor.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" 
"document-v11.dtd">
        <document> 
          <header> 
            <title>Dynamic Interceptor Chains</title> 
          </header> 
          <body> 
            <section>
              <title>Introduction</title>
              <p>
                Interceptors are objects that sit between the implementation of a 
method 
                and the interface via which that method is called. is An Interceptor 
is a 
                component through which a call to a method will pass. The method 
invocation 
                will first pass from Caller to the Interceptor and then from the 
Interceptor 
                to the Target method and then back through the Interceptor to the 
Caller. 
              </p>
              <p>
                An Interceptor Chain or Stack is a series of interceptors through 
which 
                an invocation will pass on way down to the method. After the method 
                completes the invocation will pass back through the chain of 
Interceptors 
                in the reverse order of which they were called. 
              </p>
              <p>
                Figure 1 displays such a situation. The Caller invokes a method, it 
                passes through several Interceptors before invoking the Target method 
and 
                then it passes back through all the Interceptors to the Caller.
              </p>
              <figure src="images/interceptor.png" 
                      alt="An Interceptor Chain" 
                      width="454" height="340"/>
              <p>
                An Interceptor can be called simultaneously by multiple threads and by 
                multiple clients. Thus information pertaining to the particular call 
                needs to be stored either in ThreadLocal variables (if it does not 
need 
                to be shared) or in the InvocationContext (if it may need to be 
accessed 
                by other Interceptors). The InvocationContext is where all the 
                information relating to a particular call is stored. The Context may 
also
                give access to information in different scopes (such as per object or
                per session).
              </p>
            </section>
            <section>
              <title>Basic Example</title>
              <p>
                A basic Interceptor is shown in figure 2. It gets the time before and 
                after the call and displays the duration of the call to standard 
output. 
                It demonstrates the basic format of an Interceptor. Usually an 
                Interceptor will execute some operations before a call is made on 
Target 
                method and after a call is made.
              </p>
              <source>
  public class MyTimingInterceptor 
    implements Interceptor
  {
    public Object invoke( Invocation invocation, 
                          InvocationContext ctx, 
                          InvocationChain chain )
    {
      final long start = System.currentTimeInMillis();
      final Object result = chain.invokeNext( invocation, ctx );
      final long end = System.currentTimeInMillis();
      System.out.println( "Invocation duration: " + (end - start) );
  
      return result;
    }
  }
              </source>
            </section>
            <section>
              <title>Context Using Example</title>
              <p>
                Another example is shown in figure 2. It sets the ContextClassLoader 
                prior to calling the method and then resets it to original value 
before 
                returning to caller. Note that this assumes that the Target method is 
in 
                the same thread as the Interceptor which will be the case unless a 
                Interceptor later in the chain changes threads. This Interceptor also 
                demonstrates that values can be retrieved from the InvocationContext. 
The 
                specific values that are available to an Interceptor are determined by 
                the host application server. In the case of Phoenix see X.
              </p>
              <source>
  public class MyClassLoaderInterceptor 
    implements Interceptor
  {
    public Object invoke( Invocation invocation, 
                          InvocationContext ctx, 
                          InvocationChain chain )
    {
      //Retrieve the ClassLoader object from context. 
      //Note that the set of keys and values in context is 
      //container dependent. See Container documentation for relevent 
      //set of attributes that are valid
      final ClassLoader classLoader = 
            (ClassLoader)ctx.get( "classLoader" );
      final ClassLoader oldClassLoader = 
          Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader( classLoader );
  
      final Object result = chain.invokeNext( invocation, ctx );
  
      Thread.currentThread().setContextClassLoader( oldClassLoader );
  
      return result;
    }
  }
              </source>
            </section>
            <section>
              <title>Constructing Interceptor Chains</title>
              <p>
                There are numerous policies via which Interceptor chains could be 
created.
                One such mechanism is to construct an interceptor chain based on 
particular
                objects <link href="attribute.html">Attributes</link>. Other policies 
include
                constructing chains in preconfigured arrangments or by using 
configuration 
                files such as;
              </p>
              <source><![CDATA[
  <interceptor-chains>
  
  <intercetor-chain name="MyInterceptorChain">
  
    <!-- Log the call for debugging purposes -->
    <interceptor type="org.apache.avalon.LogInterceptor"/>
  
    <!-- Make sure the call is authorized to execute method 
         and that correct principle has been setup. -->
    <interceptor type="org.apache.avalon.AuthorizeInterceptor"/>
  
    <!-- Charge caller for use of the service -->
    <interceptor type="org.apache.avalon.AccountingInterceptor">
      <!-- configuration passed to the Interceptor. It costs 
           2c per call -->
      <cost>0.02</cost>
    </interceptor>
  
    <!-- Make sure the ThreadContext data (like ContextClassLoader) 
         is setup properly -->
    <interceptor type="org.apache.avalon.ThreadContextInterceptor"/>
  
   </intercetor-chain>
  
  </interceptor-chains>
              ]]></source>
            </section>
            <section>
              <title>Example Interceptors</title>
              <p>
                <strong>Transaction</strong>: Manage transaction state in a way 
similar to EJB
                declarative transaction "attributes". May have mandatory, incompatible 
etc and 
                can result in commit or rollback on failure etc.
              </p>
              <p>
                <strong>Security</strong>: Make sure the caller has the right 
permissions,
                the caller has principle correctly setup and the method is invoked as 
correct subject.
              </p>
              <p>
                <strong>Audit</strong>: Record who, when, what and where a method is 
called.
              </p>
              <p>
                <strong>Application Isolation</strong>: Make sure caller context does 
not interfere with
                context of called method. This includes managing things like thread 
names, ContextClassLoader 
                etc.
              </p>
              <p>
                <strong>Stale References</strong>: Make sure stale references are not 
used. ie If an object has 
                been disposed of make sure that no one trys to call the object again.
              </p>
              <p>
                <strong>Pool Objects</strong>: Objects may be pooled with a particular 
policy. ie The target object 
                may be retrieved from a pool prior to method invocation and then 
returned to pool after invocation.
              </p>
              <p>
                <strong>Passivate/Activate Objects</strong>: Objects may be passivated 
(serialized to disk) if not used
                recently and then activated (deserialized from disk) when needed.
              </p>
              <p>
                <strong>Lazy Creation</strong>: Make sure objects are created and 
properly initialized before 
                they can be accessed.
              </p>
              <p>
                <strong>Binding Objects</strong>: Bind objects into a name service or 
registry (ie JMX, JNDI, LDAP, 
                RMI registry etc) the first time they are accessed.
              </p>
              <p>
                <strong>Remoting Objects</strong>: Make sure object is remoted via 
RMI, SOAP, AltRMI.
              </p>
              <p>
                <strong>Sub-Component Activator</strong>: Make sure that the first 
time a component is accessed,
                that all it's sub-components are activated.
              </p>
            </section>
          </body>
      </document>
  
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to