Continue to Part 2
Overview
This post is all about back to basics with Servlets and Web Servers. Our scenario is very simple. Our user will request a given web page and if this is found then it will be returned. If it is not found, then the web page will be generated (if it should exist) and stored as the appropriate html page. The filter will then return to the user the correct page content without returning an error or a redirect.
Part 1 – Requirement
Our task is to create a simple Filter that will test for a 404 error that has been returned from the Web Server and replace it with the content “Your page could not be found so I have generated this” and Success.
Create the Project
- New
- Maven Project
- Next
- maven-archetype-webapp
- Group Id: com.skills421.examples.servlets
- ArtifactId: Filter404
- Finish
Edit the Pom
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.skills421.examples.servlets</groupId> <artifactId>Filter404</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Filter404 Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <servlet.version>3.1.0</servlet.version> <junit.version>4.11</junit.version> <httpclient.version>4.3.4</httpclient.version> <java.version>1.6</java.version> </properties> <dependencies> <!-- Javax Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <!-- Http Components --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> <scope>provided</scope> </dependency> <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <!-- build settings --> <build> <finalName>Filter404</finalName> <plugins> <!-- set the java version --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build> </project>
Run Maven Update
- Right-click Project
- Maven
- Update Project…
Add Folders
- Right-click src/main
- add folder java
- add folder resources
- resources
- Right-click src
- add folder test/java
- add folder test/resources
Add Source Folders
- Right-click project
- new -> Source Folder
- src/main/webapp
- new -> Source Folder
- src/test/resources

Your project should now look like this:
Run the Project on the Server
- Right-click project
- Run As -> Run on Server
- Select your server (or the default VMware vFrabric server if you are using STS)
- Finish
Navigate to Existing Page

In the browser enter the following url http://localhost:8080/Filter404/index.jsp
Navigate to Non-Existent Page

In the browser enter the following url http://localhost:8080/Filter404/xxx.html
Create the Filter (first attempt)
We want to create a Filter that is going to intercept all incoming and outgoing requests and responses to and from the server and catch a 404 not found error and handle it. To start off, let’s create the PageNotFound filter and a TestResponseWrapper to double-check the calls on the Response object that will be made by the Web Server.
create PageNotFoundFilter.java
package com.skills421.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletResponse; import com.skills421.filter.wrapper.TestResponse; /** * Servlet Filter implementation class PageNotFoundFilter */ @WebFilter(filterName = "PageNotFoundFilter", urlPatterns = {"/*"}) public class PageNotFoundFilter implements Filter { /** * Default constructor. */ public PageNotFoundFilter() { } /** * @see Filter#destroy() */ public void destroy() { } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("PageNotFound-Filter"); HttpServletResponse httpResponse = (HttpServletResponse) response; TestResponse testResponse = new TestResponse(httpResponse); System.out.println("*** PageNotFound-Filter - before chain ***"); chain.doFilter(request, testResponse); System.out.println("*** PageNotFound-Filter - after chain ***"); System.out.println(testResponse.isCommitted()); System.out.println(testResponse.getStatus()); if (testResponse.getStatus() == HttpServletResponse.SC_NOT_FOUND) { System.out.println("Intercepted 404"); httpResponse.getWriter().write("404 Error Successfully Intercepted"); httpResponse.setStatus(HttpServletResponse.SC_OK); System.out.format("testResponse: %s",testResponse); } } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { } }
Create TestResponse.java
package com.skills421.filter.wrapper; import java.io.IOException; import java.io.PrintWriter; import java.util.Collection; import java.util.Locale; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class TestResponse extends HttpServletResponseWrapper { @Override public void addCookie(Cookie cookie) { System.out.println("TestResponse.addCookie"); super.addCookie(cookie); } @Override public boolean containsHeader(String name) { System.out.println("TestResponse.containsHeader"); return super.containsHeader(name); } @Override public String encodeURL(String url) { System.out.println("TestResponse.encodeURL"); return super.encodeURL(url); } @Override public String encodeRedirectURL(String url) { System.out.println("TestResponse.encodeRedirectURL"); return super.encodeRedirectURL(url); } @Override public String encodeUrl(String url) { System.out.println("TestResponse.encodeUrl"); return super.encodeUrl(url); } @Override public String encodeRedirectUrl(String url) { System.out.println("TestResponse.encodeRedirectUrl"); return super.encodeRedirectUrl(url); } @Override public void sendError(int sc, String msg) throws IOException { System.out.println("TestResponse.sendError"); super.sendError(sc, msg); } @Override public void sendError(int sc) throws IOException { System.out.println("TestResponse.sendError"); super.sendError(sc); } @Override public void sendRedirect(String location) throws IOException { System.out.println("TestResponse.sendRedirect"); super.sendRedirect(location); } @Override public void setDateHeader(String name, long date) { System.out.println("TestResponse.setDateHeader"); super.setDateHeader(name, date); } @Override public void addDateHeader(String name, long date) { System.out.println("TestResponse.addDateHeader"); super.addDateHeader(name, date); } @Override public void setHeader(String name, String value) { System.out.println("TestResponse.setHeader"); super.setHeader(name, value); } @Override public void addHeader(String name, String value) { System.out.println("TestResponse.addHeader"); super.addHeader(name, value); } @Override public void setIntHeader(String name, int value) { System.out.println("TestResponse.setIntHeader"); super.setIntHeader(name, value); } @Override public void addIntHeader(String name, int value) { System.out.println("TestResponse.addIntHeader"); super.addIntHeader(name, value); } @Override public void setStatus(int sc) { System.out.println("TestResponse.setStatus"); super.setStatus(sc); } @Override public void setStatus(int sc, String sm) { System.out.println("TestResponse.setStatus"); super.setStatus(sc, sm); } @Override public int getStatus() { System.out.println("TestResponse.getStatus"); return super.getStatus(); } @Override public String getHeader(String name) { System.out.println("TestResponse.getHeader"); return super.getHeader(name); } @Override public Collection getHeaders(String name) { System.out.println("TestResponse.getHeaders"); return super.getHeaders(name); } @Override public Collection getHeaderNames() { System.out.println("TestResponse.getHeaderNames"); return super.getHeaderNames(); } @Override public ServletResponse getResponse() { System.out.println("TestResponse.getResponse"); return super.getResponse(); } @Override public void setResponse(ServletResponse response) { System.out.println("TestResponse.setResponse"); super.setResponse(response); } @Override public void setCharacterEncoding(String charset) { System.out.println("TestResponse.setCharacterEncoding"); super.setCharacterEncoding(charset); } @Override public String getCharacterEncoding() { System.out.println("TestResponse.getCharacterEncoding"); return super.getCharacterEncoding(); } @Override public ServletOutputStream getOutputStream() throws IOException { System.out.println("TestResponse.getOutputStream"); return super.getOutputStream(); } @Override public PrintWriter getWriter() throws IOException { System.out.println("TestResponse.getWriter"); return super.getWriter(); } @Override public void setContentLength(int len) { System.out.println("TestResponse.setContentLength"); super.setContentLength(len); } @Override public void setContentLengthLong(long len) { System.out.println("TestResponse.setContentLengthLong"); super.setContentLengthLong(len); } @Override public void setContentType(String type) { System.out.println("TestResponse.setContentType"); super.setContentType(type); } @Override public String getContentType() { System.out.println("TestResponse.getContentType"); return super.getContentType(); } @Override public void setBufferSize(int size) { System.out.println("TestResponse.setBufferSize"); super.setBufferSize(size); } @Override public int getBufferSize() { System.out.println("TestResponse.getBufferSize"); return super.getBufferSize(); } @Override public void flushBuffer() throws IOException { System.out.println("TestResponse.flushBuffer"); super.flushBuffer(); } @Override public boolean isCommitted() { System.out.println("TestResponse.isCommitted"); return super.isCommitted(); } @Override public void reset() { System.out.println("TestResponse.reset"); super.reset(); } @Override public void resetBuffer() { System.out.println("TestResponse.resetBuffer"); super.resetBuffer(); } @Override public void setLocale(Locale loc) { System.out.println("TestResponse.setLocale"); super.setLocale(loc); } @Override public Locale getLocale() { System.out.println("TestResponse.getLocale"); return super.getLocale(); } @Override public boolean isWrapperFor(ServletResponse wrapped) { System.out.println("TestResponse.isWrapperFor"); return super.isWrapperFor(wrapped); } @Override public boolean isWrapperFor(Class<?> wrappedType) { System.out.println("TestResponse.isWrapperFor"); return super.isWrapperFor(wrappedType); } public TestResponse(HttpServletResponse response) { super(response); System.out.println("TestResponse()"); } }
Filtering Page Found – the output
Now let’s run the project on the server and navigate to the following page: http://localhost:8080/Filter404/index.jsp
The output we see is as follows:
PageNotFound-Filter TestResponse() *** PageNotFound-Filter - before chain *** TestResponse.setContentType TestResponse.getWriter *** PageNotFound-Filter - after chain *** TestResponse.isCommitted false TestResponse.getStatus 200 TestResponse.getStatus
The methods that the WebServer calls on the Response Wrapper for a page that exists are as follows:
- setContentType
- getWriter
- getStatus
Note that the response is NOT committed
Filtering Page Not Found – the output
Now let’s run the project on the server and navigate to the following page: Now let’s run the project on the server and navigate to the following page: http://localhost:8080/Filter404/xxx.html
The output we see is as follows:
PageNotFound-Filter TestResponse() *** PageNotFound-Filter - before chain *** TestResponse.sendError *** PageNotFound-Filter - after chain *** TestResponse.isCommitted true TestResponse.getStatus 404 TestResponse.getStatus Intercepted 404 testResponse: com.skills421.filter.wrapper.TestResponse@18879c56
The methods that the WebServer calls on the Response Wrapper for a page that does NOT exist are as follows:
- sendError
- getStatus
Note that the response IS committed for a page not found error (404)
Create our PageNotFoundResponse
Create PageNotFoundResponse.java
package com.skills421.filter.wrapper; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class PageNotFoundResponse extends HttpServletResponseWrapper { public PageNotFoundResponse(HttpServletResponse response) { super(response); } @Override public void sendError(int sc,String msg) throws IOException { this.setStatus(sc); } }
Modify PageFilter
Modify PageFilter.java
package com.skills421.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletResponse; import com.skills421.filter.wrapper.PageNotFoundResponse; /** * Servlet Filter implementation class PageNotFoundFilter */ @WebFilter(filterName = "PageNotFoundFilter", urlPatterns = {"/*"}) public class PageNotFoundFilter implements Filter { /** * Default constructor. */ public PageNotFoundFilter() { } /** * @see Filter#destroy() */ public void destroy() { } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; PageNotFoundResponse pageNotFoundResponse = new PageNotFoundResponse(httpResponse); chain.doFilter(request, pageNotFoundResponse); if (pageNotFoundResponse.getStatus() == HttpServletResponse.SC_NOT_FOUND) { httpResponse.getWriter().write("404 Error Successfully Intercepted"); httpResponse.setStatus(HttpServletResponse.SC_OK); } } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { } }
Run the Code
Now, let’s run the code on the server and we can see the following output:


http://localhost:8080/Filter404/index.jsp http://localhost:8080/Filter404/xxx.html We have successfully created the code to intercept a 404 Page Not Found error message from the Server and replace the page with a success status and our custom content.
Part 2 – Generating Page Content
Continue to Part 2
Download the Source
The source for this example can be downloaded from Github at https://github.com/skills421Training/Filter404/tree/Part-1
[…] This post follows on from Part 1 […]