diff --git a/doc/docbook/acegi.xml b/doc/docbook/acegi.xml
index 61b6cc18a9..d54a7f08f1 100644
--- a/doc/docbook/acegi.xml
+++ b/doc/docbook/acegi.xml
@@ -193,7 +193,8 @@
-
@@ -344,7 +345,8 @@
-
+
@@ -1716,7 +1718,8 @@ public boolean supports(Class clazz);
-
@@ -3795,7 +3798,8 @@ $CATALINA_HOME/bin/startup.sh
-
+
@@ -4156,6 +4160,99 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);
WebApplicationContextUtils.getWebApplicationContext(ServletContext),
so you should configure a ContextLoaderListener in
web.xml.
+
+ There is a lifecycle issue to consider when hosting
+ Filters in an IoC container instead of a servlet
+ container. Specifically, which container should be responsible for
+ calling the Filter's "startup" and "shutdown"
+ methods? It is noted that the order of initialization and destruction
+ of a Filter can vary by servlet container, and this
+ can cause problems if one Filter depends on
+ configuration settings established by an earlier initialized
+ Filter. The Spring IoC container on the other hand
+ has more comprehensive lifecycle/IoC interfaces (such as
+ InitializingBean,
+ DisposableBean, BeanNameAware,
+ ApplicationContextAware and many others) as well as
+ a well-understood interface contract, predictable method invocation
+ ordering, autowiring support, and even options to avoid implementing
+ Spring interfaces (eg the destroy-method attribute
+ in Spring XML). For this reason we recommend the use of Spring
+ lifecycle services instead of servlet container lifecycle services
+ wherever possible. By default FilterToBeanProxy
+ will not delegate init(FilterConfig) and
+ destroy() methods through to the proxied bean. If
+ you do require such invocations to be delegated, set the
+ lifecycle initialization parameter to
+ servlet-container-managed.
+
+
+
+ FilterChainProxy
+
+ Whilst FilterToBeanProxy is a very useful
+ class, the problem is that the lines of code required for
+ <filter> and
+ <filter-mapping> entries in
+ web.xml explodes when using more than a few
+ filters. To overcome this issue, Acegi Security provides a
+ FilterChainProxy class. It is wired using a
+ FilterToBeanProxy (just like in the example above),
+ but the target class is
+ net.sf.acegisecurity.util.FilterChainProxy. The
+ filter chain is then declared in the application context, using code
+ such as this:
+
+ <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
+ <property name="filterInvocationDefinitionSource">
+ <value>
+ CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
+ PATTERN_TYPE_APACHE_ANT
+ /webServices/**=basicProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter
+ /**=authenticationProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter
+ </value>
+ </property>
+</bean>
+
+ You may notice similarities with the way
+ SecurityEnforcementFilter is declared. Both regular
+ expressions and Ant Paths are supported, and the most specific URIs
+ appear first. At runtime the FilterChainProxy will
+ locate the first URI pattern that matches the current web request.
+ Each of the corresponding configuration attributes represent the name
+ of a bean defined in the application context. The filters will then be
+ invoked in the order they are specified, with standard
+ FilterChain behaviour being respected (a
+ Filter can elect not to proceed with the chain if
+ it wishes to end processing).
+
+ As you can see, FitlerChainProxy requires the
+ duplication of filter names for different request patterns (in the
+ above example, httpSessionIntegrationFilter and
+ securityEnforcementFilter are duplicated). This
+ design decision was made to enable FilterChainProxy
+ to specify different Filter invocation orders for
+ different URI patterns, and also to improve both the expressiveness
+ (in terms of regular expressions, Ant Paths, and any custom
+ FilterInvocationDefinitionSource implementations)
+ and clarity of which Filters should be
+ invoked.
+
+ In relation to lifecycle issues, the
+ FilterChainProxy will always delegate
+ init(FilterConfig) and destroy()
+ methods through to the underlaying Filters if such
+ methods are called against FilterChainProxy itself.
+ In this case, FilterChainProxy guarantees to only
+ initialize and destroy each Filter once,
+ irrespective of how many times it is declared by the
+ FilterInvocationDefinitionSource. You control the
+ overall choice as to whether these methods are called or not via the
+ lifecycle initialization parameter of the
+ FilterToBeanProxy that proxies
+ FilterChainProxy. As discussed above, by default
+ any servlet container lifecycle invocations are not delegated through
+ to FilterChainProxy.
@@ -4201,8 +4298,13 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);
All of the above filters use
- FilterToBeanProxy, which is discussed in the
- previous section.
+ FilterToBeanProxy or
+ FilterChainProxy, which is discussed in the
+ previous sections. It is recommended that a single
+ FilterToBeProxy proxy through to a single
+ FilterChainProxy for each application, with that
+ FilterChainProxy defining all of the Acegi Security
+ Filters.
If you're using SiteMesh, ensure the Acegi Security filters
execute before the SiteMesh filters are called. This enables the