You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by le...@apache.org on 2002/11/22 22:47:21 UTC

cvs commit: jakarta-avalon-excalibur/interceptor/src/xdocs interceptor.xml

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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>