A Simple Page Not Found (404) Filter – Part 2


This post follows on from Part 1

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.

Part 2 – Requirement

Take the code from Part 1 and modify it so that any request for a page of the format content01.html – content09.html will return that page if it exists and create the page if it does not exist.

If the page is created, the content will be as follows:

The page created on the server will contain the following information:

  • Content xx (title)
  • This is the content for page x (paragraph)
  • previous – next links (hyperlinks from pages 1 – 9)

The user making the call that creates the page (for the first time) will in addition see a message on the page letting them know that the page has been generated.

If any other page is requested, that does not exist, the default 404 page not found page will be returned.

Modify the PageNotFoundFilter

We are going to modify the PageNotFoundFilter to do the following:

if we have NOT requested content01.html – content09.html

process the page using the default mechanism

if we HAVE requested content01.html – content09.html

process the page as follows:

if the page does it

  • return the existing page

if the page does not exist

  • generate the content
  • store the content as an html page on the server content01.html – content09.html
  • append GENERATED CONTENT to the content in memory
  • reset the page status to Success (200) instead of Not Found (404)
  • return the content in memory to the user

edit PageNotFoundFilter.java

package com.skills421.filter;

import java.io.FileWriter;
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.HttpServletRequest;
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
{
	private void writeFile(String fullpath, String content) throws IOException
	{
		FileWriter fw = new FileWriter(fullpath);
		fw.write(content);
		fw.flush();
		fw.close();
	}

	private String buildPageBody(int contentNo)
	{
		StringBuilder htmlContentSB = new StringBuilder();
		htmlContentSB
		.append("<h2>Content 0")
		.append(contentNo)
		.append("</h2>")
		.append("<p>")
		.append("This is the content for page ")
		.append(contentNo)
		.append("</p>")
		.append("<p>");

		if(contentNo>1)
		{
			htmlContentSB
			.append("<a href='content0")
			.append(contentNo-1)
			.append(".html'>");
		}

		htmlContentSB.append("previous");

		if(contentNo>1)
		{
			htmlContentSB.append("</a>");
		}

		htmlContentSB.append(" - ");

		if(contentNo<9)
		{
			htmlContentSB
			.append("<a href='content0")
			.append(contentNo+1)
			.append(".html'>");
		}

		htmlContentSB.append("next");

		if(contentNo<9)
		{
			htmlContentSB.append("</a>");
		}

		htmlContentSB
		.append("</p>");

		return htmlContentSB.toString();
	}

	/**
	 * 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
	{
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;

		String path = httpRequest.getServletPath();

		//
		// -- if we don't have page content01.html - content09.html
		// -- then process the page using the default mechanism
		//

		if(!path.matches("/content0[1-9].html"))
		{
			chain.doFilter(request, response);
			return;
		}

		//
		// -- we have a valid content page so we need to wrap the response
		// -- incase the page cannot be found and we need to modify the response
		// -- ourselves on the way back from the Server

		PageNotFoundResponse pageNotFoundResponse = new PageNotFoundResponse(httpResponse);

		//
		// -- pass the request up the chain
		//

		chain.doFilter(request, pageNotFoundResponse);

		//
		// -- now we are processing the response
		// -- coming back from the server
		//

		//
		// -- if the page has not been found we need to generate it
		//

		if (pageNotFoundResponse.getStatus() == HttpServletResponse.SC_NOT_FOUND)
		{

			//
			// -- determine the content number of the page (01 to 09)
			//

			int startIdx = path.indexOf("content")+"content".length();
			int endIdx = startIdx +2;

			int contentNo = Integer.parseInt(path.substring(startIdx,endIdx));

			//
			// -- build the content and write the page contentxx.html
			//

			StringBuilder htmlContentSB = new StringBuilder();
			htmlContentSB
			.append("<html><body>")
			.append(this.buildPageBody(contentNo))
			.append("</body> </html>");

			String pagename = String.format("/content0%d.html", contentNo);
			String fullpath = httpRequest.getServletContext().getRealPath(pagename);

			this.writeFile(fullpath, htmlContentSB.toString());

			//
			// -- return to the customer a slightly different content
			// -- to that we wrote to contentxx.html
			// -- this content tells the user the content is GENERATED CONTENT
			//

			htmlContentSB = new StringBuilder();
			htmlContentSB
			.append("<html><body>")
			.append(this.buildPageBody(contentNo))
			.append("<p><strong>GENERATED CONTENT</strong></p>")
			.append("</body> </html>");

			//
			// -- set the response content
			// -- set the page status from 404 (not found) to 200 (OK)
			//

			httpResponse.getWriter().write(htmlContentSB.toString());
			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/content03.html

010generatedcontent03

Now refresh the page and you will see:

011storedcontent03

Download the Source

The source for this example can be downloaded from Github at https://github.com/skills421Training/Filter404/tree/Part-2

 

Advertisements

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

  1. Pingback: A Simple Page Not Found (404) Filter – Part 1 | Skills421

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