AOP-style programming for Web applications

Dmitry Namiot
dnamiot@servletsuite.com

In this article we are demonstrating the usage of Java Servlets filters. Servlet filters are a new addition to the Servlet 2.3 specification. Filters are Java classes that can intercept requests from a client before they access a resource. Filters let you manipulate requests from clients, intercept responses from resources before they are sent back to the client and manipulate responses before they are sent to the client.

In other words filters let you preprocess and postprocess requests from clients. The typical examples are: authentication (check some conditions during the preprocessing), encryption and XSLT transformation (do some postprocessing) etc. Technically speaking any filter is simply a Java class that implements the javax.servlet.Filter interface. The main method in javax.servlet.Filter is

public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)

Actually this method does all the tasks. The typical code for filter looks so:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import java.io.IOException;
import javax.servlet.ServletException;

public class SimpleFilter implements Filter
{
  public void doFilter (ServletRequest request,
             ServletResponse response,
             FilterChain chain) throws IOException, ServletException
  {

	// do some preprocessing
	// (filtering the Request)

	// execute request
	chain.doFilter (request, response);

	// do some postprocessing
	// (filtering the Response)

  }
  ...
}

Notice that doFilter() can be separated into two sections: filtering the request (preprocessing) and filtering the response (postprocessing). These two sections are separated by a call doFilter() method from the javax.servlet.FilterChain object. This call passes request to the next object in the chain, which could be the target resource (servlet, jsp page etc.) or another filter. The deployment for filters described in web.xml file (the way is similar to servlets deployment).

That is the basic. And what are we going to demonstrate in this article? Sure, it is possible to add new filters for some custom pre or post processing in your web application. But what if this deal could be done without Java programming and without updating web.xml file? More precisely we are going to use plain JSP files for our custom actions. So our actions in this case could be updated without the recompilation and redeployment for Java classes and custom JSP taglibs will open the way for writing such actions by non-programmers.

The main idea is very straightforward. Look at the above mentioned code example. That is the pattern that should be repeated from filter to filter. So we will just extract the reused part of this code and wrap it as a standard package.

Preprocessing. As a preprocessor we will use Generic preprocessor filter from Coldbeans: http://www.servletsuite.com/servlets/genericflt.htm

This filter lets you preprocess incoming requests right in JSP pages. So each incoming request will be forwarded to some JSP page (provided as a parameter for this filter) and that JSP page will play a role of preprocessor.

The usage for this filter is very simple:

a) download .jar file with filter’s code and save it in WEB-INF/lib
b) describe this filter in web.xml. Initial parameter preprocessor describes your JSP page for preprocessing. For example:

<filter> 
  <filter-name>GenericFilter</filter-name> 
  <filter-class>com.cj.genericflt.GenericFilter</filter-class> 
  <init-param> 
   <param-name>preprocessor</param-name> 
   <param-value>/preprocess.jsp</param-value> 
  </init-param> 
</filter>

c) describe a mapping for this filter in web.xml. E.g.:

<filter-mapping> 
  <filter-name>GenericFilter</filter-name> 
  <url-pattern>/myapp/*</url-pattern> 
</filter-mapping>

in this case filter will be on for each your file in /myapp. All steps here are standard and follow to the Servlets API. And now when you invoke any .jsp page: http://your_host/myapp/test.jsp GenericFilter will forward request to your JSP page provided in parameter preprocessor (in this case it is /preprocess.jsp). This page is a normal JSP page where you can do whatever you need with incoming requests. As soon as your preprocessing will be completed the normal chain for your request will be restored. In this example it means that /myapp/test.jsp (the original file) will be processed. And that is the main idea – you can program preprocessing (aspect in the modern terms) right in JSP. Even more: in this JSP page you can use a special custom JSP taglib that helps you change the normal control flow. You may decide for example in some cases to terminate preprocessed request right in this JSP (e.g. your preprocessing checks some access right). In other cases you may decide to add new attributes to request scope (e.g. pre-populate some DB data) and continue the normal chain of execution. For example, in our simple scenario our JSP preprocessor will check attribute presence in the session and terminate request if this attribute absent.

<%@ taglib uri="taglib.tld" prefix="pre" %> 
<%
 if (session.getAttribute("validUser")==null) {
%>
<p>You are not allowed to access <pre:getOriginalURI/>
<pre:stopChain/>
<% } %>

Here custom tag stopChain will terminate incoming request in your JSP preprocessor. So the normal execution chain will be skipped after the preprocessing. By default this execution chain will be resumed. We are using scriptlets here just in order to highlight the special tags from our preprocessor taglib. But of course you are free to use here any JSP tools you like: JSTL, Jakarta taglibs, Coldtags suite etc. E.g. (JSTL):

<c:if test="${session.validUser==null}">
	<p>You are not allowed to access <pre:getOriginalURI/>
	<pre:stopChain/>
</c:if>

And custom tag getOriginalURI lets you obtain in your preprocessor the original URI (URI from the preprocessed request). Now we can return back to our original goal. We do not need to update our web.xml (deploy a new component) for each new preprocessing task. Now it is enough to update our JSP code only. And because it is a plain old JSP file we are free to use all JSP related taglibs here.

Postprocessing. As a postprocessor we will use Generic postprocessor filter from Coldbeans: http://www.servletsuite.com/servlets/generic1flt.htm

The usage is similar to the above-mentioned preprocessor. We have to put .jar file into WEB-INF/lib and describe our filter in web.xml. Right now the initial parameter postprocessor describes our JSP page for postprocessing:

<filter> 
  <filter-name>Generic1Filter</filter-name> 
  <filter-class>com.cj.generic1flt.Generic1Filter</filter-class> 
  <init-param> 
   <param-name>postprocessor</param-name> 
   <param-value>/postrocess.jsp</param-value> 
  </init-param> 
</filter> 

c) describe a mapping for this filter in web.xml. E.g.:

<filter-mapping> 
  <filter-name>Generic1Filter</filter-name> 
  <url-pattern>/myapp/*</url-pattern> 
</filter-mapping>

in this case filter will be on for each your .jsp file in /myapp. Now when you invoke any .jsp page: http://your_host/myapp/test.jsp Generic1Filter will execute this request and bypass the control to your JSP page provided in parameter postprocessor (in this case it is /postprocess.jsp). This page is a normal JSP page where you can do whatever you need with incoming request as well as with the outgoing data. In other words if your requested page (e.g. test.jsp in our example) produced some output you can read this info here (in your postprocessor), modify data or even completely replace the original output with your own content. So your postprocessor will decide what to do with the processed data: stream them to user as is, modify them and stream to user after that or even produce a completely new content. And again a special custom JSP taglib could be involved in this calculation.

What is a source point here? We do a post processing. So our original request has been processed already at this point. This processing produced some content that is ready to be streamed to client’s device (browser, micro browser etc.). In our JSP post processor we should be able to get this content and process it. By this reason our postprocessor taglib contains a bit more tags comparing with the preprocessing:

- we can obtain the original URI and indicate the termination for our request here in our preprocessor
- we can obtain the content provided by our request as well as its attributes: content length, content type

What does it mean termination here? By default after the post processing the original content will be streamed to client’s device. Why do we need (or what can we do) post processing? Think for example about some logging or billing functions. We can for example just record the request and its result into DB or log file. Alternatively we can do something with the original content and send it to our client right here in the post processor. For example it could be XSLT transformation, compression, translation etc. And termination tells to our filter that the post processor itself will take care about the output.

For example in our post process JSP file we can do some like this:

a) assume our request produces some XML content and we will transform it here


<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="postprocess.tld" prefix="post" %>


<!-- obtain our content as a String -->
<post:getContentString id=”xmlData”/>

<!-- import XSL data -->
<c:import url="/xslt/our_xsl_data.xsl" var="xsltData" />

<!-- do the transformation -->
<x:transform xml="${xmlData}" xslt="${xsltData}" />

<!-- terminate request -->
<post:stopChain/>

again, because it is just a JSP file we can use any of existing tools. In this case we used JSTL. Tag getContentString obtains content as a String (text). But we can do the same for the binary data too. Tag getContent will return a byte array.

b) just a simple logger for requested URI and its content length (e.g. for debug purposes)

     <%@ taglib uri="postprocess.tld" prefix="post" %>

     <post:getOriginalURI id="uri"/>
     <post:getContentLength id="len"/>

     <%
         System.out.println(uri+":"+len);
      %>

we did not terminate request here, so after the post processing the calculated content will be streamed to client’s device as is. Actually our filter does this job. And again returning back to our original goal we see that we do not need to update our web.xml (deploy a new component) for each new post processing task. Now it is again enough to update our JSP code only. And because it is a plain old JSP file we are again free to use all JSP related taglibs here. In the real applications you are free of course to use both approaches: pre and post processing. The pattern for the usage is absolutely the same.

So what we did at the end of the day? We demonstrated here the ability to use the plain JSP for the pre- and post-processing incoming requests. This ability is more flexible and easy to use comparing with the writing custom filters for the appropriate tasks. And the usage of custom JSP tags opens the way for the even more simple way to program such actions. Also I would like to highlight that it is not yet another framework and everything could be done within the standard circle: filters and custom tags in the original form.

 © Coldbeans   Comments?

See also Other tips from Coldbeans.