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: 001-project

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 002-pagefound

Navigate to Non-Existent Page

In the browser enter the following url http://localhost:8080/Filter404/xxx.html 003-notfound

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 002-pagefound http://localhost:8080/Filter404/xxx.html 004-404handled 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

Advertisements

One thought on “A Simple Page Not Found (404) Filter – Part 1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s