Update of /cvsroot/springnet/Spring.Net/doc/reference/src
In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv17458
Modified Files:
aop-aspect-library.xml
Log Message:
docs for retry and logging aspects.
mis code cleanup.
Index: aop-aspect-library.xml
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/doc/reference/src/aop-aspect-library.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** aop-aspect-library.xml 9 Aug 2007 18:51:40 -0000 1.5
--- aop-aspect-library.xml 11 Oct 2007 01:29:35 -0000 1.6
***************
*** 9,16 ****
popular of which is transactional advice, located in the Spring.Data
module. However, the aspects that are documented in this section are those
! contained within the Spring.Aop module itself. At the moment this consists
! of Caching and Exception Handling advice. Other traditional advice types,
! logging, performance counters, validation, security, retry, and thread
! management, will be included in the future.</para>
</sect1>
--- 9,16 ----
popular of which is transactional advice, located in the Spring.Data
module. However, the aspects that are documented in this section are those
! contained within the Spring.Aop module itself. The aspects in within
! Spring.Aop.dll are are Caching, Exception Handling, Logging, and Retry.
! Other traditional advice types such as validation, security, and thread
! management, will be included in a future release.</para>
</sect1>
***************
*** 25,30 ****
calls to retrieve that information from a lower, and more slow, layer such
as a database or a web service. Caching also can help in terms of
! application scalability, which is generally the more important concern.
! </para>
<para>The caching support in Spring.NET consists of base cache interfaces
--- 25,30 ----
calls to retrieve that information from a lower, and more slow, layer such
as a database or a web service. Caching also can help in terms of
! application scalability, which is generally the more important
! concern.</para>
<para>The caching support in Spring.NET consists of base cache interfaces
***************
*** 41,46 ****
<classname>Spring.Caching.NonExpiringCache</classname> that stores cache
entries in memory and never expires these entries. Custom implementation
! based on 3rd party implementations, such as Oracle Coherence, can be used
! by implementing the <literal>ICache</literal> interface.</para>
<para>The cache aspect is
--- 41,47 ----
<classname>Spring.Caching.NonExpiringCache</classname> that stores cache
entries in memory and never expires these entries. Custom implementation
! based on 3rd party implementations, such as Oracle Coherence, or
! memcached, can be used by implementing the <literal>ICache</literal>
! interface.</para>
<para>The cache aspect is
***************
*** 52,58 ****
like the transactional aspect. Future versions will allow for external
configuration of the behavior so you can apply caching to a code base
! without needing to use attributes in the code. </para>
! <para>The following attributes are available </para>
<itemizedlist>
--- 53,59 ----
like the transactional aspect. Future versions will allow for external
configuration of the behavior so you can apply caching to a code base
! without needing to use attributes in the code.</para>
! <para>The following attributes are available</para>
<itemizedlist>
***************
*** 74,83 ****
<listitem>
<para><literal>InvalidateCache</literal> - used to indicate one or
! more cache items should be invalidated. </para>
</listitem>
</itemizedlist>
! <para>Each CacheResult, CacheResultItems, and CacheParameter attributes
! define the following properties.</para>
<itemizedlist>
--- 75,86 ----
<listitem>
<para><literal>InvalidateCache</literal> - used to indicate one or
! more cache items should be invalidated.</para>
</listitem>
</itemizedlist>
! <para>Each <classname>CacheResult</classname>,
! <classname>CacheResultItems</classname>, and
! <classname>CacheParameter</classname> attributes define the following
! properties.</para>
<itemizedlist>
***************
*** 103,107 ****
--- 106,121 ----
should remain in the cache (in seconds).</para>
</listitem>
+ </itemizedlist>
+
+ <para>The <classname>InvalidateCache</classname> attribute has properties
+ for the CacheName, the Key as well as the Condition, with the same
+ meanings as listed previously.</para>
+
+ <para>Each <classname>ICache</classname> implementation will have
+ properties that are specific to a caching technology. In the case of
+ <classname>AspNetCache</classname>, the two important properties to
+ configure are:</para>
+ <itemizedlist>
<listitem>
<para><literal>SlidingExperation</literal> - If this property value is
***************
*** 115,118 ****
--- 129,137 ----
cache when the cache is being purged.</para>
</listitem>
+
+ <listitem>
+ <para><literal>TimeToLive</literal> - The amount of time an object
+ should remain in the cache (in seconds).</para>
+ </listitem>
</itemizedlist>
***************
*** 141,148 ****
</itemizedlist>
- <para>The invalidateCache attribute has properties for the CacheName, the
- Key as well as the Condition, with the same meanings as listed
- previously.</para>
-
<para>An important element of the applying these attributes is the use of
the expression language that allows for calling context information to
--- 160,163 ----
***************
*** 151,155 ****
interface with the method GetAirport(long id).</para>
! <programlisting> [CacheResult("AspNetCache", "'Airport.Id=' + #id", TimeToLive = 60, SlidingExpiration = true, Priority = CachePriority.Low)]
public Airport GetAirport(long id)
{
--- 166,170 ----
interface with the method GetAirport(long id).</para>
! <programlisting> [CacheResult("AspNetCache", "'Airport.Id=' + #id", TimeToLive = 60)]
public Airport GetAirport(long id)
{
***************
*** 158,173 ****
</programlisting>
! <para>The key used to cache the airport is a string expression that
! incorporates the argument passed into the method, the id. The method
! parameter names are exposed as variables to the key expression. If you do
! not specify a key, then all the parameter values will be used to cache the
! returned value. The expression may also call out to other objects in the
! spring container allowing for a more complex key algorithm to be
! encapsulated.</para>
<para>The configuration to enable the caching aspect is shown below</para>
<programlisting> <object id="CacheAspect" type="Spring.Aspects.Cache.CacheAspect, Spring.Aop"/>
! <object id="AspNetCache" type="Spring.Caching.AspNetCache, Spring.Web"/>
--- 173,195 ----
</programlisting>
! <para>The first parameter is the cache name. The second string parameter
! is the cache key and is a string expression that incorporates the argument
! passed into the method, the id. The method parameter names are exposed as
! variables to the key expression. If you do not specify a key, then all the
! parameter values will be used to cache the returned value. The expression
! may also call out to other objects in the spring container allowing for a
! more complex key algorithm to be encapsulated. The end result is that the
! Airport object is cached by id for 60 seconds in a cache named
! AspNetCache. The TimetoLive property could also havfe been specified on
! the configuration of the AspNetCache object.</para>
<para>The configuration to enable the caching aspect is shown below</para>
<programlisting> <object id="CacheAspect" type="Spring.Aspects.Cache.CacheAspect, Spring.Aop"/>
! <object id="AspNetCache" type="Spring.Caching.AspNetCache, Spring.Web">
! <property name="SlidingExpiration" value="true"/>
! <property name="Priority" value="CachePriority.Low"/>
! <property name="TimeToLive" value="120"/>
! </object>
***************
*** 187,193 ****
<para>in this example an ObjectNameAutoProxyCreator was used to apply this
! the cache aspect to objects that have Dao in their name, </para>
! <para> </para>
</sect1>
--- 209,215 ----
<para>in this example an ObjectNameAutoProxyCreator was used to apply this
! the cache aspect to objects that have Dao in their name,</para>
! <para></para>
</sect1>
***************
*** 233,237 ****
<property name="exceptionHandlers">
<list>
! <value><emphasis role="bold">on ArithmeticException wrap System.InvalidOperationException</emphasis></value>
</list>
</property>
--- 255,259 ----
<property name="exceptionHandlers">
<list>
! <value><emphasis role="bold">on exception name ArithmeticException wrap System.InvalidOperationException</emphasis></value>
</list>
</property>
***************
*** 243,256 ****
the message used in the newly thrown exception as shown below</para>
! <programlisting>on ArithmeticException wrap System.InvalidOperationException 'My Message'</programlisting>
<para>Similarly, if you would rather replace the exception, that is do not
nest one inside the other, you can use the following syntax</para>
! <programlisting>on ArithmeticException replace System.InvalidOperationException
or
! on ArithmeticException replace System.InvalidOperationException 'My Message'</programlisting>
<para>Both wrap and replace are special cases of the more general
--- 265,278 ----
the message used in the newly thrown exception as shown below</para>
! <programlisting>on exception name ArithmeticException wrap System.InvalidOperationException 'My Message'</programlisting>
<para>Similarly, if you would rather replace the exception, that is do not
nest one inside the other, you can use the following syntax</para>
! <programlisting>on exception name ArithmeticException replace System.InvalidOperationException
or
! on exception name ArithmeticException replace System.InvalidOperationException 'My Message'</programlisting>
<para>Both wrap and replace are special cases of the more general
***************
*** 258,262 ****
below</para>
! <para><programlisting>on ArithmeticException translate new System.InvalidOperationException('My Message, Method Name ' + #method.Name, #e)</programlisting>What
we see here after the translate keyword is text that will be passed into
Spring's expression language (SpEL) for evaluation. Refer to the chapter
--- 280,284 ----
below</para>
! <para><programlisting>on exception name ArithmeticException translate new System.InvalidOperationException('My Message, Method Name ' + #method.Name, #e)</programlisting>What
we see here after the translate keyword is text that will be passed into
Spring's expression language (SpEL) for evaluation. Refer to the chapter
***************
*** 295,299 ****
specific return value, for example</para>
! <programlisting>on ArithmeticException swallow
--- 317,321 ----
specific return value, for example</para>
! <programlisting>on exception name ArithmeticException swallow
***************
*** 301,316 ****
! on ArithmeticException return 12</programlisting>
<para>You may also simply log the exception</para>
! <programlisting>on ArithmeticException log 'My Message, Method Name ' + #method.Name</programlisting>
! <para>Logging is performed using Commons.Logging that provides an
! abstraction over the underlying logging implementation. Logging is
! currently at the debug level with a logger name of "LogExceptionHandler"
! The ability to specify these values will be a future enhancement and
! likely via a syntax resembling a constructor for the action, i.e.
! log(Debug,"LoggerName").</para>
<para>Multiple exception handling statements can be specified within the
--- 323,341 ----
! on exception name ArithmeticException return 12</programlisting>
<para>You may also simply log the exception</para>
! <programlisting>on exception name ArithmeticException,ArgumentException log 'My Message, Method Name ' + #method.Name</programlisting>
! <para>Here we see that a comma delimited list of exception names can be
! specified.</para>
!
! <para>The logging is performed using the Commons.Logging library that
! provides an abstraction over the underlying logging implementation.
! Logging is currently at the debug level with a logger name of
! "LogExceptionHandler" The ability to specify these values will be a future
! enhancement and likely via a syntax resembling a constructor for the
! action, i.e. log(Debug,"LoggerName").</para>
<para>Multiple exception handling statements can be specified within the
***************
*** 329,342 ****
which is then thrown.</para>
<para>While the examples given above are toy examples, they could just as
! easily be changed to convert your application specific exceptions.</para>
<sect2>
! <title>Reference</title>
<para>The general syntax of the language is</para>
! <para>on [ExceptionName1,ExceptionName2,...] [action] [SpEL
! expression]</para>
<para>The exception names are requires as well as the action. The valid
--- 354,392 ----
which is then thrown.</para>
+ <para>The exception handling DSL also supports the the ability to provide
+ a SpEL boolean expression to determine if the advice will apply instead of
+ just filtering by the expression name. For example, the following is the
+ equivalent to the first example based on exception names but compares the
+ specific type of the exception thrown</para>
+
+ <programlisting><emphasis role="bold">on exception (#e is T(System.ArithmeticException))</emphasis> wrap System.InvalidOperationException</programlisting>
+
+ <para>The syntax use is 'on exception (SpEL boolean expression)' and
+ inside the expression you have access to the variables of the calling
+ context listed before, i.e. method, args, target, and e. This can be
+ useful to implement a small amount of conditional logic, such as checking
+ for a specific error number in an exception, i.e. <literal>(#e is
+ T(System.Data.SqlException) && #e.Errors[0].Number in
+ {156,170,207,208})</literal>, to catch and translate bad grammer codes in
+ a SqlException.</para>
+
<para>While the examples given above are toy examples, they could just as
! easily be changed to convert your application specific exceptions. If you
! find yourself pushing the limits of using SpEL expressions, you will
! likely be better off creating your own custom aspect class instead of a
! scripting approach.</para>
<sect2>
! <title>Language Reference</title>
<para>The general syntax of the language is</para>
! <para><literal>on exception name [ExceptionName1,ExceptionName2,...]
! [action] [SpEL expression]</literal></para>
!
! <para>or</para>
!
! <para><literal>on exception (SpEL boolean expression) [action] [SpEL
! expression]</literal></para>
<para>The exception names are requires as well as the action. The valid
***************
*** 384,387 ****
--- 434,604 ----
<sect1>
+ <title>Logging</title>
+
+ <para>The logging advice lets you log the information on method entry,
+ exit and thrown exception (if any). The implementation is based on the
+ logging library, <link linkend="???">Common.Logging</link>, that provides
+ portability across different logging libraries. There are a number of
+ configuration options available, listed below</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>LogUniqueIdentifier</para>
+ </listitem>
+
+ <listitem>
+ <para>LogExecutionTime</para>
+ </listitem>
+
+ <listitem>
+ <para>LogMethodArguments</para>
+ </listitem>
+
+ <listitem>
+ <para>Separator</para>
+ </listitem>
+
+ <listitem>
+ <para>LogLevel</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>You declare the logging advice in IoC container with the following
+ XML fragment. Alternatively, you can use the class
+ <classname>SimpleLoggingAdvice</classname> progammatically. </para>
+
+ <programlisting><object name="exceptionHandlingAdvice" type="Spring.Aspects.Logging.SimpleLoggingAdvice, Spring.Aop">
+ <property name="logUniqueIdentifier" value="true"/>
+ <property name="logExecutionTime" value="true"/>
+ <property name="logMethodArguments" value="true"/>
+ <property name="Separator" value=";"/>
+ <property name="LogLevel" value="LogLevel.Debug"/>
+ </object></programlisting>
+
+ <para>The default values for LogUniqueIdentifier, LogExecutionTime, and
+ LogMethodArguments are false. The default separator value is ", " and the
+ default log level is Common.Logging's LogLevel.Trace. </para>
+
+ <para>You can subclass SimpleLoggingAdvice and override the methods
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>string GetEntryMessage(IMethodInvocation invocation,
+ string idString)</literal></para>
+ </listitem>
+
+ <listitem>
+ <para><literal>string GetExceptionMessage(IMethodInvocation
+ invocation, Exception e, TimeSpan executionTimeSpan, string
+ idString)</literal></para>
+ </listitem>
+
+ <listitem>
+ <para><literal>string GetExitMessage(IMethodInvocation invocation,
+ object returnValue, TimeSpan executionTimeSpan, string
+ idString)</literal></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The default implementation to calculate a unique identifer is to use
+ a Guid. You can alter this behavior by overriding the method
+ <literal>string CreateUniqueIdentifier()</literal>.</para>
+ </sect1>
+
+ <sect1>
+ <title>Retry</title>
+
+ <para>When making a distributed call it is oftena common requirement to be
+ able to retry the method invocation if there was an exception. Typically
+ the exception will be due to a communication issue that is intermitent and
+ a retrying over a period of time will likely result in a successful
+ invocation. When applying retry advice it is important to know if making
+ two calls to the remote service will cause side effects. Genreally
+ speaking, the method being invoked should be <ulink
+ url="http://en.wikipedia.org/wiki/Idempotent#Computer_Science">idempotent</ulink>,
+ that is, it is safe to call multiple times.</para>
+
+ <para>The retry advice is specified using a little language, i.e a DSL. A
+ simple example is shown below</para>
+
+ <programlisting>on exception name ArithmeticException retry 3x delay 1s</programlisting>
+
+ <para>The meaning is: when an exception that has 'ArithmeticException' in
+ its classname is thrown, retry the invocaiton up to 3 times and delay for
+ 1 second in between each retry event. </para>
+
+ <para>You can also provide a SpEL (Spring Expression Language) expression
+ that calculates the time interval to sleep between each retry event. The
+ syntax for this is shown below</para>
+
+ <programlisting>on exception name ArithmeticException retry 3x rate (1*#n + 0.5)</programlisting>
+
+ <para>As with the exception handling advice, you may also specify a
+ boolean SpEL that must evaluate to true in order for the advice to apply.
+ For example</para>
+
+ <programlisting>on exception (#e is T(System.ArithmeticException)) retry 3x delay 1s
+
+
+ on exception (#e is T(System.ArithmeticException)) retry 3x rate (1*#n + 0.5)</programlisting>
+
+ <para>The time specified after the delay keyword is converted to a
+ TimeSpan object using Spring's TimeSpanConverter. This supports setting
+ the time as an integer + time unit. Time units are (d, h, m, s, ms)
+ representing (days, hours, minutes, seconds, and milliseconds). For
+ example; 1d = 1day, 5h = 5 hours etc. You can not specify a string such as
+ '1d 5h'. The value that is calculated from the expression after the rate
+ keyword is interpreted as a number of seconds. The power of using SpEL for
+ the rate expression is that you can easily specify some exponential retry
+ rate (a bigger delay for each retry attempt) or call out to a custom
+ function developed for this purpose. </para>
+
+ <para>When using a SpEL expression for the filter condition or for the
+ rate expression, the following variable are available</para>
+
+ <para><itemizedlist>
+ <listitem>
+ <para>method - the MethodInfo object corresponding to the method
+ that threw the exception</para>
+ </listitem>
+
+ <listitem>
+ <para>args - the argument array to the method that threw the
+ exception, signature is object[]</para>
+ </listitem>
+
+ <listitem>
+ <para>target - the AOP target object instance.</para>
+ </listitem>
+
+ <listitem>
+ <para>e - the thrown exception</para>
+ </listitem>
+ </itemizedlist>You declare the advice in IoC container with the
+ following XML fragment. Alternatively, you can use the
+ <classname>RetryAdvice</classname> class progammatically. </para>
+
+ <programlisting><object name="exceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop">
+ <property name="retryExpression" value="<emphasis role="bold">on exception name ArithmeticException retry 3x delay 1s</emphasis>"/>
+ </object></programlisting>
+
+ <sect2>
+ <title>Language Reference</title>
+
+ <para>The general syntax of the languae is</para>
+
+ <para><literal>on exception name [ExceptionName1,ExceptionName2,...]
+ retry [number of times]x [delay|rate] [delay time|SpEL rate
+ expression]</literal></para>
+
+ <para>or</para>
+
+ <para><literal>on exception (SpEL boolean expression) retry [number of
+ times]x [delay|rate] [delay time|SpELrate expression]</literal></para>
+ </sect2>
+ </sect1>
+
+ <sect1>
<title>Transactions</title>
|