Archive for the 'Design Pattern' Category

Using Filters for relief

Level: Intermediate

Technology: JSP

Suppose we are developing a web-app with directory structure as:

  • index.jsp
  • login.jsp
  • /private
    • index.jsp

To enter the ‘private’ directory, login is required. A trivial approach would be as following:

index.jsp
<form method=”post” action=”login.jsp”><%if (session.getAttribute(“logged_in”) != null

&& session.getAttribute(“logged_in”).toString().equals(

“true”)) {

out.println(“Welcome “

+ session.getAttribute(“user_name”).toString());

out

.println(“<input name=’logout’ type=’submit’ value=’Logout’ />”);

} else {

out.println(“Please login.”);

out

.println(“<input name=’login’ type=’submit’ value=’Login’ />”);

}

%>

<br/>

<a href=”private/”> Go to private area</a>

</form>

login.jsp
<%if (request.getParameter(“login”) != null) {session.setAttribute(“logged_in”, “true”);

session.setAttribute(“user_name”, “Authenticated User”);

} else if (request.getParameter(“logout”) != null) {

session.removeAttribute(“logged_in”);

session.removeAttribute(“user_name”);

}

response.sendRedirect(“index.jsp”);

%>

private/index.jsp
<%if (session.getAttribute(“logged_in”) == null|| session.getAttribute(“logged_in”).toString().equals(

“true”) == false) {

response.sendError(403, “Login required before access.”);

}

%>

<h1 style=”color: #ff0000″>This is private page</h1>

<form method=”post” action=”../login.jsp”>

<input name=’logout’ type=’submit’ value=’LogOut’ />

</form>

The shortcoming of this approach can be noticed very clearly. If there are 50 pages inside the private directory, we need to add the session-attribute check in every 50 pages. After the user clicks logout button in the private/index.jsp page, he is redirected to index.jsp. If at that moment, he clicks back button of his browser, he is shown the cached private/index.jsp page. To remedy this, we need to add no-cache header to every 50 pages again. Any change in the session-check or cache-handling requires changing every 50 pages.

This is where ‘Filters’ come to help. A filter dynamically intercepts requests and responses to transform or use the information contained in the requests or responses. They provide the ability to encapsulate recurring tasks in reusable units. Let’s see how we can improve the previous design with ‘Filters’

private/index.jsp
<h1 style=”color: #ff0000″>This is private page</h1><form method=”post” action=”../login.jsp”><input name=’logout’ type=’submit’ value=’LogOut’ />

</form>

com.filters.TestFilter
…public class TestFilter implements Filter {…

@Override

public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {

if (arg0 instanceof HttpServletRequest) {

HttpServletRequest httpRequest = (HttpServletRequest) arg0;

HttpServletResponse httpResponse = (HttpServletResponse) arg1;

HttpSession httpSession = httpRequest.getSession();

httpResponse.setDateHeader(“Expires”, 0);

httpResponse.setHeader(“Pragma”, “no-cache”);

if (httpRequest.getProtocol().equals(“HTTP/1.1″)) {

httpResponse.setHeader(“Cache-Control”, “no-cache”);

}

if (httpSession.getAttribute(“logged_in”) == null || httpSession.getAttribute(“logged_in”).toString().equals(“true”) == false) {

httpResponse.sendError(403, “Filter says: Login required before access.”);

}

}

arg2.doFilter(arg0, arg1);

}

}

web.xml
<filter><filter-name>testFilter</filter-name>

<filter-class>com.filters.TestFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>testFilter</filter-name>

<url-pattern>/private/*</url-pattern>

</filter-mapping>

Useful Links:

http://java.sun.com/products/servlet/Filters.html