HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML

Every other month in this column we (Deepak Alur, John Crupi, Dan Malks, and other architects from the Sun Java Center (www.sun.com/service/sunps/jdc) will discuss various topics from our book, Core J2EE Patterns: Best Practices and Strategies (Alur, Crupi, Malks, Prentice Hall/Sun Press 2001). These topics include the 15 J2EE patterns in our catalog, design strategies, bad practices, refactorings, and pattern-driven design in J2EE technology.

Patterns are expert solutions - recurring designs that have proven effective over time. This month's article will provide you with a bit more detail on the subject.

When applying patterns to the presentation tier, we address the following:

  • Pre- and postprocessing of a request and/or response
  • Request handling, navigation, and dispatch
  • View preparation and creation
  • Application partitioning
In other words, how do we handle a Web request, managing any necessary data access and generating presentation content for the user? How might we transform the incoming or outgoing stream? How do we determine what processing to perform to fulfill this request? What view should be used to service the request and how do we generate it? What are the logical abstractions and how do we design and decompose our software to take advantage of these abstractions?

Six presentation tier patterns are documented in the Core J2EE Patterns Catalog. The patterns and their tier categorizations are shown in Table 1. Because of the focus of this column, we'll describe just one of the presentation patterns in detail. First I want to provide some context on how the presentation tier patterns fit within a common J2EE architecture, starting with a basic description of a system.

Table 1

When a client makes a Web request for a particular resource, the request is processed, a view is generated, and a result is returned to the client. To provide more detail, we can define several logical components and subcomponents of a typical Web-based architecture:

  • Request handler:
    - Pre- and postprocessing
    - Request processing
    - Command processing
  • Navigation and dispatch:
    - Navigation resolution
    - Request dispatching
  • View processor:
    - View preparation
    - View creation
These components and subcomponents are shown visually in Figure 1. Let's have a look at the Intercepting Filter pattern, which addresses issues in the request-handling portion of the architecture, as outlined above and in the figure.

Figure 1
Figure  1:

Intercepting Filter
The Intercepting Filter pattern documents issues relating to preprocessing and postprocessing a Web request. Here are some common examples of preprocessing:

  • Decrypting an input stream: The incoming data may have been encrypted for security purposes.
  • Decompressing a stream: The incoming stream may have been compressed for more efficient transfer over the network.
  • Translating various encoding schemes to a common format: Multiple encoding schemes require different handling. If each encoding is translated to a common format, the core request-handling mechanism can treat every request similarly. Some common examples of encoding schemes are:
    - application/x-www-form-urlencoded
    - multipart/form-data
  • Performing authentication or authorization: Authentication and authorization may be performed either in a filter or as part of the core processing flow, typically as part of the controller.
What constitutes postprocessing of a request? Here are some common examples:
  • Encrypting an output stream: The outgoing data may be encrypted for security purposes.
  • Compressing a stream: The outgoing stream may be compressed for more efficient transfer over the network.
  • Transformation of data for different clients: Transformation into HTML, XML, or WML.
Additionally, one of the forces that motivates us to consider this pattern is the desire to add and remove these processing components independently - independent of other filtering components and of the underlying core processing that fulfills the client's request.

Let's look at the class diagram (see Figure 2) that describes this pattern's structure. In the figure the actual resource that is the target of the client request, such as a servlet or JavaServer Page technology, is represented by the Target class. The individual pre- or postprocessing components that perform filtering functionality, as described above, are shown as Filter One, Filter Two, and Filter Three. One important thing to notice in this diagram is that there's no direct association between any of the filters and the target resource. Additionally, there's no direct association from any filter to one of the other filters.

Figure 2
Figure  2:

This is an important point, since it clarifies that the filters are loosely coupled both to the target resource and to other filters. This allows the filters to be easily added and removed unobtrusively, as mentioned.

Filters are an excellent way to layer functionality onto your system, providing pluggable behavior that can be used to decorate core request processing. Another benefit of using this pattern is that it promotes the reuse of these various filtering components across different requests, in different combinations, and even in different applications.

There are several implementation strategies for this pattern, the most powerful of which leverages the standard filtering supported in the Servlet specification 2.3. Vendor support for this revision of the specification will be widespread in the not too distant future.

Listings 1 and 2 are excerpts from the Standard Filter Strategy code example in the book. The example describes using filters to preprocess requests, checking their encoding schemes, and translating these different schemes to a common format. The common format is to store all request states within request attributes. Subsequently, any control code that checks for incoming values will get these values from request attributes, regardless of the original encoding.

Figure 3 is the sequence diagram that shows the basic collaboration of the objects in the example. Note that in this implementation the role of the FilterManager from the class diagram is fulfilled by the Container in the sequence diagram. We hope this provides you with a basic understanding of the benefits and some implementing options for the Intercepting Filter pattern.

Figure 3
Figure  3:

There's more than one way to approach any task. This is as true with software development as with anything else. So when I tell you that people approach the task of developing software in different ways, you certainly won't be surprised. Some folks feel that most design work should precede implementation, while others like to jump in, write some code, and start to think about how these bits of implementation fit together. The difference is basically that of top-down design versus bottom-up design.

Refactoring applies to either approach, though it's typically applied in an environment where there is an understanding that design is spread across the life of the project. That said, the fact is that wherever there is coding, there may be refactoring. Martin Fowler, in his great book Refactoring: Improving the Design of Existing Code (Addison-Wesley), describes refactoring as "improving the design of the code after it has been written." His book identifies many common design flaws and describes the incremental coding changes that result in improved design. The issues are typically general and not specific to any particular area of Java or software development.

The lion's share of Fowler's book is devoted to what he calls "small refactorings," meaning the design changes are at a very low level, each involving several discrete coding modifications, such as adding a parameter to a method. A small portion of the book, coauthored by Kent Beck, is devoted to "big refactorings," which exist at a higher level of abstraction and have steps that aren't as well defined or as concrete.

In our book we include some J2EE technology-specific refactorings, describing opportunities to improve the design of a J2EE technology-based system and the relevant steps involved. The format and style is based on that in Fowler's book, which we find extremely valuable. Based on Fowler and Beck's definition, the J2EE refactorings included in our book might be called "medium refactorings" based on their level of abstraction. The refactorings are listed in Table 2, categorized by tier.

Table 2

We find these refactorings to be excellent companions to the patterns and bad practices described in the rest of our book. In fact, you can think about the refactorings as often providing the steps that help guide the developer from a less optimal solution, or bad practice, to a more optimal one, suggested by a pattern.

In a future article we'll provide more information on these refactorings and their relationship to the patterns in the catalog. We'll also go into greater detail on the presentation, business, and integration tiers, as well as communication across these tiers.

Thank you for reading, and please e-mail us at [email protected] to provide feedback on this article and to suggest other topics of interest.

Portions of this article contain excerpts with permission from Core J2EE Patterns by Deepak Alur, John Crupi, and Dan Malks (ISBN 0-13-064884-1) Copyright 2001. Sun Microsystems, Inc.

Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. Sun, Sun Microsystems, the Sun logo, Java, J2EE, Java Center, and JavaServer Pages are trademarks or registered trademarks of Sun Microsystems, Inc., in the United States and other countries. Sun Microsystems, Inc., may have intellectual property rights relating to implementations of the technology described in this article, and no license of any kind is given here. Please visit www.sun.com/software/communitysource/ for licensing information.

The information in this article (the "information") is provided "as is," for discussion purposes only. All express or implied conditions, representations, and warranties, including any implied warranty of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed, except to the extent that such disclaimers are held to be legally invalid. Neither Sun nor the authors make any representations, warranties, or guaranties as to the quality, suitability, truth, accuracy, or completeness of the information. Neither Sun nor the authors shall be liable for any damages suffered as a result of using, modifying, contributing, copying, or distributing the information.

Author Bio
Dan Malks, a senior Java architect with Sun Microsystems, is currently focusing on distributed, service-based designs, patterns, and implementations. He has developed in a variety of environments, including Smalltalk and Java, while focusing on OO technologies. Dan has published articles on Java in leading industry periodicals, and holds bachelor's and master's degrees in computer science. [email protected]


Listing 1: Intercpting Filter Implementation Example:
Standard Encode Filter
public class StandardEncodeFilter 
extends BaseEncodeFilter { 
     // Creates new StandardEncodeFilter 
     public StandardEncodeFilter() {} 

     public void doFilter(javax.servlet.ServletRequest 
     throws java.io.IOException, javax.servlet.ServletException { 
         String contentType = 
         if ((contentType == null) || 

contentType.equalsIgnoreCase("application/x-www-form-urlencoded")) { 
             translateParamsToAttributes(servletRequest, servletResponse); 
         filterChain.doFilter(servletRequest, servletResponse); 
     private void translateParamsToAttributes(ServletRequest request, 
ServletResponse response) 
         Enumeration paramNames = 
         while (paramNames.hasMoreElements()) { 
             String paramName = (String) 
             String [] values; 
             values = request.getParameterValues(paramName); 
             System.err.println("paramName = " + paramName); 
             if (values.length == 1) 
                 request.setAttribute(paramName, values[0]); 
                 request.setAttribute(paramName, values); 


Listing 2: Intercepting Filter Implementaion Example:
public class MultipartEncodeFilter extends 
BaseEncodeFilter { 
     public MultipartEncodeFilter() {} 
     public void doFilter(javax.servlet.ServletRequest 
                          servletRequest, javax.servlet.ServletResponse 
     throws java.io.IOException, 
     javax.servlet.ServletException { 
         String contentType = 
         // Only filter this request if it is multipart 
         // encoding 
         if (contentType.startsWith("multipart/form-data")){ 
             try { 
                 String uploadFolder = 

                 if (uploadFolder == null) uploadFolder = "."; 
                 /** The MultipartRequest class is: 
                 * Copyright (C) 2001 by Jason Hunter 
                 * <[email protected]>. All rights reserved. 
                 MultipartRequest multi = new 
                                                           1 * 1024 * 1024 ); 
                 Enumeration params = 
                 while (params.hasMoreElements()) { 
                     String name = (String)params.nextElement(); 
                     String value = multi.getParameter(name); 
                     servletRequest.setAttribute(name, value); 

                 Enumeration files = multi.getFileNames(); 
                 while (files.hasMoreElements()) { 
                     String name = (String)files.nextElement(); 
                     String filename = 
                     String type = multi.getContentType(name); 
                     File f = multi.getFile(name); 
                     // At this point, do something with the 
                     // file, as necessary 
             catch (IOException e) 
                 LogManager.logMessage("error reading or saving file"+ e); 
         } // end if 
     } // end method doFilter() 


All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.