2
votes

Well, straight to the point: i created - with Eclipse - two filters (Filter1 and Filter2) and a servlet(DisplayHeader) to see the filter order of execution. I used Tomcat 8.5 as target runtime.

New/Dynamic Web Project/ with Context root / and checked the "Generate web.xml delpoyment descriptor"

Filter1 prints "I'm Filter 1" when it's executed, and i "linked" it to a specific servlet "DisplayHeader". Filter2 it's the twin brother with 2 instead of 1. DisplayHeader servlet is mapped to /DisplayHeader.

Below is Filter1 code for clarity

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;

@WebFilter(
        urlPatterns = {"/Filter1"}, 
        servletNames = {"DisplayHeader"}
        )
public class Filter1 implements Filter {

    /**
     * Default constructor. 
     */
    public Filter1() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here
        System.out.println("I'm Filter 1");

        // pass the request along the filter chain
        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

Well, when i run the servlet on Tomcat (Tomcat v8.5) it prints

I'm Filter 1
I'm Filter 2

which means that Filter1 is executed before Filter2.

I read that filter's order of execution comes from the mapping order in the web.xml file, so i expected to find somewhere in the web.xml file something like

<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/DisplayHeader</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/DisplayHeader</url-pattern>
</filter-mapping>

which i should reverse in order...

The problem is: when i open the web.xml of my project (from the project explorer, see figure below) file i just see this:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>SetFilterOrder</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

web.xml location in the explorer

am i just missing the right web.xml file path or this web.xml is the result of using the "Generate web.xml delpoyment descriptor" option?

2

2 Answers

0
votes

From the reading I have done it does not look like Servlet 3.0 provides a way to define the order via annotations. So to define the order you will have to use web.xml. The order that it may be using could be alphabetical or it could just be dumb luck, which classes show up first when it does the annotation scan. You can test this out be messing around with the filter names or filter class names. Ultimately you cannot rely on this. To be certain it seems like you will have to revert to the web.xml.

References:
How to define servlet filter order of execution using annotations in WAR

http://www.concretepage.com/java-ee/jsp-servlet/how-to-use-filter-in-servlet-3-with-webfilter-annotation

http://javabycode.com/java-frameworks/servlet-jsp/filter-servlet-3-using-webfilter-annotation-example.html

1
votes

In my experience the filter chain works its way up from the root.

Say you have:

domain.com/loggedInArea/UserProfile/Address.jsp. 

If you have a filter for each level, they will be executed starting from the "shortest" URL to the "longest":

@WebFilter("/*")
@WebFilter("/loggedInArea/*")
@WebFilter("/loggedInArea/UserProfile/*")
@WebFilter("/loggedInArea/UserProfile/Address.jsp")

You can't really use URL filter wildcards as you can use them in, for example, search for file names. So, you can search for

Addr*.jsp

but you can't use that to specify a WebFilter URL

If I understand correctly, the example you mentioned is just something you created to practice WebFilters - absolutely fine - rather than the requirements of a project you are working on. I can't think of a real life example in which you need to determine the order in which the filters are executed rather than by URL level.

You can't have

@WebFilter("/loggedInArea/UserProfile/Address.*p")
@WebFilter("/loggedInArea/UserProfile/Addr*sp")

because you will have to use specific file names and they will be mutually exclusive.

If you have two different filters with same URL

@WebFilter("/loggedInArea/UserProfile/*")
@WebFilter("/loggedInArea/UserProfile/*")

( Tomcat might even refuse to start up if you have this, not sure ) then it all should certainly be condensed into one single filter, and you can control the flow from within that.