I took out a servlet filter that had no filter-mapping from a web.xml of a (very old) web-app, and - BOOM! - the app did not work any more.
One would assume that a filter without filter-mapping should be ignored by the web-container, but I could not verify this in the servlet 4.0 specification. I couldn't believe that removing a filter without filter-mapping can affect a web-app in any way, so I wrote a minimal servlet application to try this out. Environment was Tomcat 9, Servlet 4.0, Maven 3.6.3.
Objectives of this article are
- showing how a minimal Java servlet looks like
- trying out whether a filter without filter-mapping is applied or ignored by the web-container.
Application Specification
The servlet outputs ">Hallo Welt<" into the browser, where "Hallo" is determined by one filter, and "Welt" by another filter. So, if I remove the filter-mapping of the "Welt" filter, the output should be ">Hallo null<". This has to be proven.
Maven Project
I recommend to first create the directories and files of the project, then compile it with Maven, then import it as "Maven Project" into Eclipse.
I named the Maven artifact testServlet40, which designates the servlet's context-path. I also named the root directory of the project testServlet40. Thus the web-app is available in a web-browser using this address:
- http://localhost:8080/testServlet40
The file pom.xml describes the Maven project object model (dependencies).
The file web.xml is the Servlet deloyment descriptor
that controls the interaction between
the servlet-container (Tomcat, Jetty, ...) and the web-app (servlet).
Following are the project folders and source files. Click on the expand controls to see collapsed sources.
testServlet40
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>fri</groupId> <artifactId>testServlet40</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>Minimal Servlet 4.0 Example3</name> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <!-- without this, Eclipse complains about "Dynamic Web Module 4.0 requires Java 1.8 or newer" --> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> </dependencies> </project>
src
main
java
fri
testServlet40
HelloWorldServlet.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package fri.testServlet40; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloWorldServlet extends HttpServlet { public static final String HELLO_ATTRIBUTENAME = "hello"; public static final String WORLD_ATTRIBUTENAME = "world"; @Override protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.err.println("HelloWorldServlet start request on contextPath '"+request.getContextPath()+"'"); final Object hello = request.getAttribute(HELLO_ATTRIBUTENAME); final Object world = request.getAttribute(WORLD_ATTRIBUTENAME); final PrintWriter out = response.getWriter(); out.println(">"+hello+" "+world+"<"); out.close(); System.err.println("HelloWorldServlet end request on contextPath '"+request.getContextPath()+"'"); } } |
HelloFilter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package fri.testServlet40; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloFilter implements Filter { @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.err.println("HelloFilter start"); request.setAttribute(HelloWorldServlet.HELLO_ATTRIBUTENAME, "Hallo"); chain.doFilter(request, response); System.err.println("HelloFilter end"); } } |
WorldFilter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package fri.testServlet40; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class WorldFilter implements Filter { @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.err.println("WorldFilter start"); request.setAttribute(HelloWorldServlet.WORLD_ATTRIBUTENAME, "Welt"); chain.doFilter(request, response); System.err.println("WorldFilter end"); } } |
webapp
WEB-INF
web.xml
<?xml version="1.0"?> <web-app version="4.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"> <servlet> <servlet-name>helloworld-servlet</servlet-name> <servlet-class>fri.testServlet40.HelloWorldServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloworld-servlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <!-- Filters are called in the order they appear here --> <filter> <filter-name>world-filter</filter-name> <filter-class>fri.testServlet40.WorldFilter</filter-class> </filter> <filter> <filter-name>hello-filter</filter-name> <filter-class>fri.testServlet40.HelloFilter</filter-class> </filter> <filter-mapping> <filter-name>world-filter</filter-name> <servlet-name>helloworld-servlet</servlet-name> </filter-mapping> <filter-mapping> <filter-name>hello-filter</filter-name> <servlet-name>helloworld-servlet</servlet-name> </filter-mapping> </web-app>
Running the Application
You can compile and pack the web-application by this Maven commandline:
cd testServlet40 mvn install
Then deploy the created testServlet40-0.0.1-SNAPSHOT.war file into your favorite web-server and call the URL
- http://localhost:8080/testServlet40
in your favorite web-browser.
On the server console you will see this:
WorldFilter start HelloFilter start HelloWorldServlet start request on contextPath '/testServlet40' HelloWorldServlet end request on contextPath '/testServlet40' HelloFilter end WorldFilter end
This proves that filters are called in the order they appear in web.xml: first WorldFilter, then HelloFilter. Then the servlet is called, and afterwards the filters can do cleanup, but in reverse order.
Note that any filter can prevent the execution of other filters and the servlet by not calling
chain.doFilter(request, response)
.
Result
In the browser I can see the expected result:
>Hallo Welt<
When I remove the filter-mapping of WorldFilter in web.xml and pack and deploy the web-app again, the output changes:
>Hallo null<
Thus it is true that a filter without filter-mapping is ignored.
Keine Kommentare:
Kommentar veröffentlichen