If you're like me you really like the new Servlet 3.0 spec that allows for annotated servlet classes. This approach along with the new ServletContainerInitializer interface potentially allows for code-based application configuration and deployment without an application deployment descriptor (web.xml) file.
One thing lacking in the new spec's annotations, is the ordering of the filter chain. This, IMO, is REALLY important. It allows the developer to ensure encoding filters or other types of "must happen first" filters are ahead of other filters in the chain. While the documentation states when using annotated filter classes the order is undetermined, my tests have shown the order is the order in which they appear in the class path. If all your annotated filter classes are in one package and named according to order (AFilter.class, BFilter.class, CFilter.class), then there is no problem. But this is unlikely. Also, libraries often come with non-annotated filter classes which must be programmatically included in the filter chain, or added via the web.xml file.
I have found I can annotate my classes - have them anywhere on the class path - and STILL achieve ordering by specifying only the class names in the web.xml file. The following is an example of how to order two annotated Servlet 3 filters that are on the class path:
<filter-mapping>
<filter-name>ZFilter</filter-name>
</filter-mapping>
<filter-mapping>
<filter-name>AFilter</filter-name>
</filter-mapping>
In my tests - this properly orders the filter chain so ZFilter is before AFilter. If there was another annotated filter class on the class path and NOT part of this mapping, it would be AFTER the filters in this mapping. E.g., ZFilter, AFilter, SomeOtherFilter. Removing these mappings returns the order to class path ordering: AFilter, SomeOtherFilter, ZFilter.
This approach allows one to embrace the new servlet spec - and have minimal configuration in the web.xml. The web.xml would also be used to set up non-Servlet 3 filters (E.g., Filters provided by libraries).
If you are pragmatically adding filters to the context in a ServletContainerInitializer then the order you add the filters is maintained - and the isMatchAfter parameter is honored.
context.addFilter("SomeFilter",SomeFilter.class)
.addMappingForUrlPatterns(null, true, "/*");
I have found I can use a combination of all three approaches, but understanding the order of operations is important:
- Ordering of web.xml definitions are processed first.
- Other annotated filters NOT in the web.xml will be NEXT in the chain.
- Filters added via the ServletContext addFilter() method are processed last, AND the value of isMatchAfter is honored. So you can add a filter using this method, and place it FIRST or NEXT in the filter chain.
Pretty cool. This has all been tested using Tomcat 7. Hope this all makes sense. Hope this helps.
Enjoy,
M