Ask a question
Java

Java (4)


Wednesday, 16 September 2009 09:05

J2EE DesingPatterns - J2EE Antipatterns

Written by Vicky
J2EE Antipatterns
In this chapter, we present a few of the most common antipatterns in the J2EE world. The list is by no means complete. Just like the active community collecting design patterns, there is an equally active community cataloguing antipatterns and their solutions. For a general introduction, the text by William J. Brown, et al, AntiPatterns:Refactoring Software, Architectures, and Projects in Crisis (Wiley & Sons), is the book on antipatterns; it has a decidedly process-based focus. The current seminal work on Java enterprise antipatterns, which we've relied on heavily, is Bruce A. Tate's excellent resource, BitterJava (Manning).
We will look at the following antipatterns:
Excessive Layering and Leak Collection
Cover repeated architectural errors that affect performance and extensibility.
Magic Servlet, Monolithic JSP, Compound JSP, and Overstuffed Session
Cover breakdowns in Model-View-Controller separation.
Everything Is an EJB, Round-Tripping, and Stateful When Stateless Will Do
Help determine how and how not to use EJBs.
Some of these antipatterns are closely related to the regular patterns we've discussed elsewhere in this book. Since antipatterns are recurring mistakes, and design patterns are recurring solutions, it make sense that most antipatterns have a corresponding pattern or two.
12.1 Causes of Antipatterns

Every program, big or small, contains shortcuts, mistakes, and code that could have been thought out a little better. What distinguishes an antipattern from these errors is that, like a design pattern, it is repeated. When we explore the causes of antipatterns, we don't need to look at why they exist—we need to look at why they persist and propagate. The main reasons that antipatterns spread are:
 
·         Inexperience
·         Unreadable code
·         Cut-and-paste development

Inexperienced developers are the major cause of antipatterns. Obviously, newer developers are less likely to have come across these common mistakes previously, and are less like to recognize when they are making them. The danger of antipatterns is subtler when experienced developers use new technology. This danger is especially pronounced in J2EE technology, which evolves quickly, and in which many of the standard tutorials and code generation tools are full of antipatterns. To combat the problem, most organizations use training as well as code reviews with senior developers. But the best defense against antipatterns is to know your enemy: understanding and recognizing antipatterns is the key to avoiding them.

Unreadable code is another fertile breeding ground for antipatterns. Often, the existence of a well-known antipattern will be hidden because readers have to spend all their mental cycles trying to figure out what the code does, not why it does it. Developers sometimes favor conciseness and optimization over readability without taking into account the maintenance costs. Every shortcut that saves a few keystrokes or a few bytes of memory should be balanced against the costs in terms of developer hours and lost business when a hard-to-find bug is discovered. Unreadable code is best fought with consistency: publishing and enforcing code guidelines, relentless commenting, and aggressive review.

Cut-and-paste development refers to code that is taken from one place and pasted directly into another. Teams sometimes assume that cut-and-paste is a form of reuse: because the code has been used before, it is often considered more robust. Unfortunately, cut-and-paste actually makes code less reliable, since the pasted portion is used out of context. Even worse, bug changes don't propagate: changes to cut-and-paste code must be propagated manually. Cut-and-paste should only be necessary when entire objects cannot be reused. If you find yourself copying a particular piece of code, consider abstracting it and making it available to many classes through inheritance or as part of a separate utility class.

12.2 Architectural Antipatterns

The first class of antipatterns we will look at is architectural in nature. These antipatterns are not J2EE-specific: they affect many Java applications and the Java APIs themselves. They are included in a book on J2EE because they affect highly scalable, long-running applications—meaning they are of particular relevance to J2EE developers.

12.2.1 Excessive Layering

If you've read the preceding chapters, you've probably noticed that design patterns tend to suggest adding layers. Façades, caches, controllers, and commands all add flexibility and even improve performance, but also require more layers.
Figure 12-1 shows a rough sketch of the "typical" J2EE application. Even in this simplified view, each request requires processing by at least seven different layers. And this picture doesn't even show the details of each individual layer, which may themselves contain multiple objects.
 
Figure 12-1. A standard J2EE application
 
Unfortunately, in a high-level, object-oriented environment like J2EE, the layers we add are not the only layers that exist. We've already talked about containers—the servlet and EJB containers are the main ones—and how they provide advanced services, generally through layers of their own. The underlying containers are themselves built on top of Java's APIs; the APIs are still a few layers away from the JVM, which interact through layered system libraries with the operating system—which finally talks to the actual hardware. If you look at stack traces from a running JVM, it is not surprising to see a Java application with a call stack well over 100 methods deep!

It's easy to see how a CPU that can execute billions of instructions a second can get bogged down running the J2EE environment. It's also easy to think that with all these layers, adding a few of our own can't possibly make any difference.
That's not the case, however. Think of the structure as a pyramid: every call to a container method requires two or four calls to the underlying Java API, which requires eight Java instructions, and so forth and so on. The layers we add are far more expensive than many of the preexisting layers.

An example of the Excessive Layering antipattern is a common scenario that we call the "Persistence Layer of Doom." While abstracting database access away from business logic has so many benefits that we hesitate to say anything negative about the process, hiding SQL from other components has one serious problem: expensive activities (such as accessing a network or filesystem for a database query) start to look like cheap activities (such as reading a field from a JavaBean). Developers working on the presentation tier will inevitably call the expensive functions frequently, and end up assuming the entire business tier is horribly slow. We'll talk more about this problem later in this chapter when we discuss the Round-Tripping antipattern.
12.2.1.1 Reducing layers

Because it's easy to add layers to a J2EE application, it's important to understand which ones are necessary and which are excessive. Unfortunately, there's no generic answer, since the correct number of layers depends on the type and expected use of an application.

When deciding whether to add layers, we have to balance the costs with the benefits they provide. The cost of layers can be expressed in terms of design time, code complexity, and speed. The benefits are twofold. Layers that provide abstract interfaces to more specific code allow cleaner, more extensible code. Layers such as caches, which optimize data access, can often benefit an application's scalability.

While we can't provide a generic solution to layering problems, we can offer a few hints as to what level of layering is appropriate for generic types of J2EE applications:

All-in-one application
For small applications where the entire model, view, and controller always live on the same server (like a single-function intranet application), reduce layers as much as possible. Generally, this will mean condensing the business tier, often using DAO and business delegate objects that interact directly with an underlying database through JDBC. In the presentation tier, you should stick to a simple servlet/JSP model.
Front end
Often, medium-size applications provide a simple web or similar frontend to a shared data model, usually a legacy application. Examples include airline ticketing systems and online inventory tools. In these applications, the presentation tier is generally the focus of development. The presentation tier should scale across multiple servers, and should be made efficient and extensible with liberal use of layering. Most functions of the business tier will probably be supported by the underlying legacy application and should not be duplicated in a large, deeply layered business tier.

Internet scale application
The last type of application is the ultimate in J2EE: a large application spread over numerous servers meant to handle thousands of users and millions of requests per day. In these large environments, communication overhead between the many servers, as well as the cost of maintaining a large code base, dwarf the cost of layering. Using all the standard layers and multiple layers of caching in both the presentation and business tier can help optimize network transactions, while layers of abstraction keep the code manageable and extensible.

Communication and documentation are our best weapons. When layers are added for performance, document which calls are expensive, and, where possible, provide alternative methods that batch requests together or provide timeouts. When layers are added for abstraction, document what the layer abstracts and why, especially when using vendor-specific methods (see the "Vendor Lock-In" sidebar). These steps assure that our layers enhance extensibility or improve performance instead of becoming an expensive black hole.
Vendor Lock-In

Many J2EE vendors offer enhancements to the core J2EE functionality, such as optimized database access methods or APIs for fine-grained control of clustering capabilities. Using these functions, however, ties your application to that vendor's implementation, whether it's a database, MOM, or application server. The more your application depends on a particular vendor's APIs, the harder it is for you to change vendors, effectively locking you into the vendor you started with.

J2EE purists will tell you why vendor lock-in is a bad thing. If your vendor decides to raise their prices, you are generally stuck paying what they ask or rebuilding your application. If you sell software to a customer, they too must buy your vendor's product, regardless of their own preference. And if the vendor goes out of business, you could be stuck with unsupported technology.

From a practical standpoint, however, vendor's enhancements are often just that: enhancements. Using vendor-specific APIs can often make your application easier to build, more efficient, and more robust. So is there a happy middle ground? There is. While using vendor-specific APIs is not an antipattern, vendor lock-in is.

The most important step in avoiding lock-in is understanding which APIs are generic and which are vendor-specific. At the minimum, clearly document all vendor dependencies. Also, make your best effort to avoid letting the structure of the API influence overall design too much, particularly if you think you might have to eventually abandon the vendor.

A better solution is to hide the vendor complexities by defining an interface with an abstract definition of the vendor's methods and then implementing that interface for the particular vendor you have chosen. If you need to support a new vendor, you should be able to simply reimplement the interface using the new vendor's methods or generic ones if necessary.

12.2.2 Leak Collection

Automated memory management is one of Java's most important features. It is also somewhat of an Achilles's heel. While a developer is free to create objects at will, she does not control when or how the garbage collector reclaims them. In
some situations, objects that are no longer being used may be kept in memory for much longer than necessary. In a large application, using excess memory in this way is a serious scalability bottleneck.

Fortunately, by taking into account how the garbage collector actually works, we can recognize common mistakes that cause extra objects. The Java Virtual Machine uses the concept of reachability to determine when an object can be garbage-collected. Each time an object stores a reference to another object, with code like this.intValue = new Integer(7), the referent (the Integer) is said to be reachable from the object referring to it (this). We can manually break the reference, for example by assigning this.intValue = null.

To determine which objects can be garbage-collected, the JVM periodically builds a graph of all the objects in the application. It does this by recursively walking from a root node to all the reachable objects, marking each one. When the walk is done, all unmarked objects can be cleaned up. This two-phase process is called mark and sweep. If you think of references as strings that attach two objects together, the mark and sweep process is roughly analogous to picking up and shaking the main object in an application. Since every object that is in use will be attached somehow, they will all be lifted up together in a giant, messy ball. The objects ready for garbage collection will fall to the floor, where they can be swept away.
So how does this knowledge help us avoid memory leaks? A memory leak occurs when a string attaches an object that is no longer in use to an object that is still in use. This connection wouldn't be so bad, except that the misattached object could itself be connected to a whole hairball of objects that should otherwise be discarded. Usually, the culprit is a long-lived object with a reference to a shorter-lived object, a common case when using collections.

A collection is an object that does nothing more than organize references to other objects. The collection itself (a cache, for example) usually has a long lifespan, but the objects it refers to (the contents of the cache) do not. If items are not removed from the cache when they are no longer needed, a memory leak will result. This type of memory leak in a collection is an instance of the Leak Collection antipattern.

In Chapter 5, we saw several instances of caches, including the Caching Filter pattern. Unfortunately, a cache with no policy for expiring data constitutes a memory leak. Consider Example 12-1, a simplified version of our caching filter.
Example 12-1. A simplified CacheFilter
public class CacheFilter implements Filter {
 // a very simple cache
 private Map cache;
  
 public void doFilter(ServletRequest request,
   ServletResponse response, FilterChain chain)
 throws IOException, ServletException {
   ...
 
 if (!cache.containsKey(key)) {
    cache.put(key, data);
 }
   // fulfill the response from the cache      
   if (cache.containsKey(key)) {
          ...         
   }
 }
 
 public void init(FilterConfig filterConfig) {
   ...
   cache = new HashMap( );
 }
}
Nowhere in this code is there a remove( ) call to match the put( ) call that adds data to the cache. Without a cache expiration policy, the data in this cache will potentially use all the available memory, killing the application.
12.2.2.1 Reclaiming lost memory

The hardest part of dealing with Java memory leaks is discovering them in the first place. Since the JVM only collects garbage periodically, watching the size of the application in memory isn't very reliable. Obviously, if you're seeing frequent out-of-memory type errors, it's probably too late. Often, commercial profiling tools are your best bet to help keep an eye on the number of objects in use at any one time.

In our trivial example, it should be clear that adding data to the cache and never removing it is a potential memory leak. The obvious solution is to add a simple timer that cleans out the cache at some periodic interval. While this may be effective, it is not a guarantee: if too much data is cached in too short a time, we could still have memory problems. A better solution is to use a Java feature called a soft reference, which maintains a reference to an object but allows the cached data to be garbage-collected at the collector's discretion. Typically, the least-recently used objects are collected when the system is running out of memory. Simply changing the way we put data in the cache will accomplish this:
cache.put(key, new SoftReference(data));
There are a number of caveats, the most important being that when we retrieve data, we have to manually follow the soft reference (which might return null if the object has been garbage-collected):
if (cache.containsKey(key)) {
 SoftReference ref = (SoftReference) cache.get(key);
 Object result = ref.get( );
 
 if (result == null) {
    cache.remove(key);
 }
}
Of course, we could still run out of memory if we add too many keys to the cache. A more robust solution uses a reference queue and a thread to automatically remove entries as they are garbage-collected.

In general, the most effective way to fight memory leaks is to recognize where they are likely to be. Collections, as we have mentioned, are a frequent source of leaks. Many common features—such as attribute lists and listeners—use collections internally. When using these features, pay extra attention to when objects are added and removed from the collection. Often, it is good practice to code the removal at the same time as the addition. And, of course, make sure to document pairs of adds and removes so that other developers can easily figure out what you did.

12.3 Presentation Tier Antipatterns

The Model-View-Controller pattern, covered in Chapter 3, is the fundamental organizing principle for the presentation tier. The building blocks of the MVC pattern create an overall map of the application, making it easier to understand and extend. Preserving the separation of model, view, and controller is essential to maintaining these advantages.

It should be no surprise, then, that the presentation tier antipatterns have to do with the breakdown of model-view-controller separation. While these antipatterns are specific to the presentation tier, be aware that other antipatterns, such as Leak Collection and Excessive Layering, can affect the presentation tier as well.

12.3.1 The Magic Servlet

When servlets were first introduced, developers immediately saw the potential of combining the robust Java environment with an efficient mechanism for serving dynamic content. Server-side Java's killer app was JDBC, a powerful and high-level mechanism for communicating with databases. Over time, technologies like JNDI and JMS were added, allowing J2EE to talk easily and directly to a large number of enterprise information systems.

Because it was suddenly so easy to talk to databases, directory servers, and messaging systems, many developers were tricked into thinking that their applications would be simple, too. Who needed a complicated design when reading a row from a database was a one-line operation? Unfortunately, as applications grew in scope, complexity crept back in—but the design to handle it did not.

The typical symptom of complexity outpacing design is the Magic Servlet antipattern, in which a single servlet handles all aspects of a given request. On the surface, the magic servlet seems like a reasonable encapsulation. It captures all the logic needed to handle a request in a single, convenient class. But a magic servlet is also large, complex, difficult to maintain, and impossible to reuse. Typically, these servlets have a huge amount of code in a single doGet( ) or similar method.

Imagine you are given the task of putting an LDAP-based corporate address book on the web. Example 12-2 shows a typical magic servlet solution, using the servlet to read all the names and phone numbers in the LDAP directory.
Example 12-2. A magic servlet
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.*;
 
public class MagicServlet extends HttpServlet {
 private DirContext peopleContext;
  
  // setup LDAP access
 public void init(ServletConfig config)
 throws ServletException {
    super.init(config);
    
    Properties env = new Properties( );
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://localhost/o=jndiTest");
    env.put(Context.SECURITY_PRINCIPAL, "cn=Manager, o=jndiTest");
    env.put(Context.SECURITY_CREDENTIALS, "secret");
    
    try {
      DirContext initalContext = new InitialDirContext(env);
      peopleContext = (DirContext)initalContext.lookup("ou=people");
    } catch (NamingException ne) 2{
      ne.printStackTrace( );
      throw new UnavailableException("Error inializing LDAP", ne);
    }
 }
  
  // close LDAP 
  public void destroy( ) {
    try {
      peopleContext.close( );
    } catch(NamingException ne) {
      ne.printStackTrace( );
    }
 }
  
  // "magic" function is model, view and controller
 protected void doGet(HttpServletRequest request, 
             HttpServletResponse response)
 throws ServletException, IOException {
    // view logic
    response.setContentType("text/html");
    java.io.PrintWriter out = response.getWriter( );
    out.println("<html>");
    out.println("<head>");
    out.println("<title>
Servlet</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<table>");2
  
    // model logic
    try {
      NamingEnumeration people = peopleContext.list("");
      while(people.hasMore( )) {
        NameClassPair personName = (NameClassPair)people.next( );
        Attributes personAttrs = peopleContext.getAttributes(personName.getName( ));
        Attribute cn = personAttrs.get("cn");
        Attribute sn = personAttrs.get("sn");
        Attribute phone = personAttrs.get("telephoneNumber");
        
        out.println("<tr><
td>" + cn.get( ) + " " + 
              sn.get( ) + "</td>" +
              "<td>" + phone.get( ) + 
              "</td></
tr>");
      }
    } catch(Exception ex) {
      out.println("Error " + ex + " getting data!");
    }
  
    // back to view logic
    out.println("</table>");
    out.println("</body>");
    out.println("</html>");
 }
}
The doGet( ) method talks directly to the data source, LDAP. It also writes directly to the output. This example is relatively simple, since it doesn't handle input validation or any kind of error handling, for starters. Adding those functions would make the servlet even more complicated and specialized.

The problem with a magic servlet is not a lack of encapsulation, but rather improper encapsulation. The first rule of objects is that they should perform a single function well. The scratch test is whether you can describe what an object does in one phrase. For our magic servlet, the best we could say is "it reads phone numbers from a database and formats the results as HTML." Two phrases at least, and awkward ones at that.
12.3.1.1 Refactoring the magic servlet

To fix the Magic Servlet antipattern, we need to break our servlet into multiple objects, each with a specific task. Fortunately, we already have a pattern for solving just this type of problem: the Model-View-Controller.  The salient point is the separation of the interaction into (at least) three pieces.

The model is responsible for all interactions with persistent storage. We will create a simple JavaBean, Person, with accessor methods for fields firstName, lastName, and phoneNumber. Then we create a class, LdapPersonCommand, to read from LDAP and expose the values as a collection of class Person. The command implements a generic PersonCommand interface:
public interface PersonCommand {
 // initialize the command
 public void initialize(HttpSession session) throws NamingException; 
  
  // execute the query
 public void runCommand( );
  
  // get the result of the query as a List of class Person
 public List getPeople( );        
}
The view, a simple JSP page, uses an instance of class PersonCommand placed in request scope and the Java Standard Tag Libraries to generate a table of names and phone numbers. PersonView.jsp is shown in Example 12-3.
Example 12-3. PersonView.jsp
<%@page contentType="text/html"%>
<%@taglib uri="/jstl/core" prefix="c"%>
<html>
<head><
title>Addresses</title>
</head>
<body>
<jsp:useBean id="personCommand" scope="request"
       class="PersonCommand" />
<table>
 <c:forEach var="person" items="${personCommand.people}"
 <tr><
td><c:out value="${person.firstName}"/
></td>
    <td><c:out 
value="${person.lastName}"/></
td>
    <td><c:out 
value="${person.phoneNumber}"/></
td>
 </tr>
 </c:forEach>
</table>
</body>
</html>
As you can see, our JSP is entirely focused on view management. It contains only the minimal amount of JSTL code needed to handle looping and output.
All this abstraction leaves us with a very simple servlet, as shown in Example 12-4.
Example 12-4. PersonServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.IO.*
import javax.naming.*;
 
public class PersonServlet extends HttpServlet {
 protected void doGet(HttpServletRequest request,
             HttpServletResponse response)
 throws ServletException, IOException {
    try {
      PersonCommand personCommand = new LdapPersonCommand( );
      personCommand.initialize( );
      personCommand.runCommand( );
      
      request.setAttribute("personCommand", personCommand);
    } catch(NamingException ne) {
      throw new ServletException("Error executing " + "command", ne);
    }
    
    RequestDispatcher dispatch =
      getServletContext( ).getRequestDispatcher("/PersonView.jsp");
    dispatch.forward(request, response);
 }
}
This servlet is responsible for coordinating the response but not for performing the dirty work of reading LDAP or generating HTML. The major advantages of this solution are in extensibility. We could easily replace LdapPersonCommand with a class that reads from a database or legacy system. Writing a separate JSP to output to WAP or WML or a different language would also be easy and require no modification of the servlet. All of this should be familiar from previous chapters. The point is that the problem can be solved. You can resolve this antipattern a piece at a time. In this case, you might want to isolate the view first, and come back and separate the model and controller when you have time.

12.3.2 Monolithic/Compound JSPs

When JSPs were first introduced, some developers recognized their potential to replace the awkwardness of embedding HTML output in a servlet with the convenience of scripting. Many decided that since JSPs were parsed into servlets internally, they were just a new syntax for servlets. So they built servlets—including access to models, control logic, and output—as JSPs. Example 12-5 shows a worst-case JSP design.
Example 12-5. LoginPage.jsp
<%@page contentType="text/html"%>
<%@page import="antipatterns.LoginManager" %>
<html>
<% 
  LoginManager lm = new LoginManager( );
 ServletRequest req = pageContext.getRequest( );
 if (!lm.doLogin(req.getParameter("username"), 
          req.getParameter("password"))) {
%>
<head><
title>Login Page</title>
</head>
<body>
 <form action="/LoginPage.jsp" method="post">
 User name: <input type="text" name="username">
<br>
 Password: <input type="password" name="password"
><br>
 <input type="submit">
 </form>
</body>
<% } else { %>
<head><
title>First Page</title>
</head>
<body>
 Welcome to the page!
<% } %>
</body>
</html>
This example has the same problems as a magic servlet. It performs operations belonging to the model, view, and controller. The example above combines the functionality of JSP and servlets, but represents the worst of both worlds from the point of view of maintenance. The HTML is confusing, often duplicated, and spread throughout the file in an opaque way. The Java code is embedded awkwardly—again, hard to find and follow.

There are actually two common antipatterns in Example 12-5. The Monolithic JSP antipattern occurs when JSP pages do more than their fair share of the work, often acting as both view and controller. While this example doesn't interact directly with the model via JNDI or JDBC, it would be a logical extension, further destroying the separation of model and controller.

A closely related antipattern is the Compound JSP antipattern, in which multiple JSP files are crammed into one using Java conditionals. In the example above, our code tests the return value of a call to doLogin( ) and displays different pages based on the result.
12.3.2.1 Fixing monolithic and compound JSPs

JSP's advantage is its simplicity. As a tag-based language, it should be familiar to web designers who no longer need to understand the complexities of Java development in order to build web pages. It is also meant to integrate easily into existing tools, such as WYSIWYG HTML editors.

Monolithic and compound JSPs take away those advantages. It would take a pretty sophisticated editor to separate the two pages contained in Example 12-5. And web designers working with it would have to understand the embedded code, at least enough so as not to break it.

Since monolithic JSPs are really just another type of magic servlet, the solution is pretty much the same. The JSP should be refactored into three separate pieces, with a servlet acting as the controller, the JSP as the view and JavaBeans as the model. We won't go through the whole exercise of converting our monolithic JSP to MVC, since the result is so similar to the previous example and those in Chapter 3.

Compound JSPs present a slightly different problem, but again a similar solution. In Example 12-5 we effectively have two pages: the login page and the welcome page. We should separate these into two separate JSP pages (in this case, HTML pages would work as well). The selection logic should go in the controller servlet, which contains code like:
if (lm.doLogin(username, password)) {
        nextPage = "/welcome.jsp";
} else {
        nextPage = "/login.jsp";
}
 
RequestDispatcher dispatch = 
  getServletContext( ).getRequestDispatcher(nextPage);
dispatch.forward(request, response);
12.3.3 Overstuffed Session

The session, which tracks users as they navigate a web site, is a major feature of the J2EE presentation tier. Objects like the user's security permissions can be stored in the session when a user first logs in, and used several pages later to determine what the user can access. While maintaining session information is quite convenient, it is not without its pitfalls. Putting too much data or the wrong kind of data into the session leads to the Overstuffed Session antipattern.

The first danger of this antipattern is from data with a short lifespan. Since the session is implemented as a collection, we have to be on the lookout for a variant of the Leak Collection antipattern. Putting objects in the wrong scope, as we have done in Example 12-6, can lead to a pseudo memory leak.
Example 12-6. The LeakyServlet's doGet( ) method
protected void doGet(HttpServletRequest request,
           HttpServletResponse response)
throws ServletException, IOException {
 HttpSession session = request.getSession( );
    
  // create the bean
 AddressBean address = new AddressBean( );
 address.setFirst(request.getParameter("first"));
 address.setLast(request.getParameter("last"));
    
  // pass the bean to the view
 session.setAttribute("antipatterns.address", address);
  
  // instantiate the view
 RequestDispatcher dispatcher = 
    getServletContext( ).getRequestDispatcher("/View.jsp");
 dispatcher.forward(request, response);
}
As the snippet shows, we have placed a bean called AddressBean (which contains state data that is only used in this request) in session scope. This bean, however, will be kept around in the user's session for as long as the user is connected.

It's hard to see this kind of scenario as a real memory leak. The user's session expires when they log out, and the memory is reclaimed. But each object adds up, and if lots of users store lots of irrelevant beans in session scope, the total number of users that can connect at any one time will be reduced.[1]

If you use Struts or a similar web application framework, pay particular attention to this issue. The default Form Bean scoping in Struts is to the session, rather than to the request, so it's easy to end up with a large number of extra objects in memory for each active user.

The second danger is from data with a long lifespan. It is very common to store complex state data—such as shopping carts or user preferences—in the user's session, assuming the session will stay alive for as long as the user is using the site. Unfortunately, this is not always the case: if the user takes a break to respond to email or read another web page, or if the web server crashes, the user may unexpectedly lose all the data. This can be a real problem: just ask anyone who has painstakingly selected all the components for his new computer system only to have them disappear while he is looking for his credit card.
12.3.3.1 Unstuffing the session

Fortunately, as far as antipatterns go, fixing an overstuffed session isn't too difficult. For short-lived data, make sure you default to request scope for all your objects, and only use session scope when it is explicitly required. Also, remember that it is possible to remove items from the session if you know they will no longer be used.

Long-lived data should generally be migrated to the business tier. This precaution has a number of advantages, including persistence between logins and across server restarts and transactions. Recently, there has been a trend toward applications with a database solely used by the presentation tier. While it may be overkill, this method provides a convenient (and usually high-speed) place to store user and session information without affecting the design of the business tier.

12.4 EJB Antipatterns

Our final set of antipatterns deal with Enterprise JavaBeans. EJBs are a powerful technology, but can also be complicated and heavyweight. Two of our antipatterns deal with the complexity of EJBs: the Everything Is an EJB antipattern describes when EJBs are appropriate to use at all, while the Stateful When Stateless Will Do antipattern describes when stateful session EJBs should be used. The Round-Tripping antipattern covers common performance problems in client-server applications, and often turns up when you're using remote EJBs.

12.4.1 Everything Is an EJB

There is a common antipattern called the golden hammer. A golden hammer starts life as a good solution to a recurring problem—the kind of solution that design patterns are made from. Eventually, however, the golden hammer starts getting used because it is the most familiar to developers, not because it's the best solution. Like a carpenter with only one saw, the golden hammer may get the job done, but it doesn't give the cleanest or easiest cut.

In many cases, EJBs are just such a golden hammer. Developers—especially developers with a history of database development—tend to see entity EJBs as the solution to every problem. Need security? Create a username and password bean. Need an address? Create an address bean.

Unfortunately, EJBs are not the solution to every problem. Like any other technology (and EJBs are a complex technology, at that), EJBs have both costs and benefits. EJBs should only be used when their benefits outweigh the costs in solving the problem at hand. This is an important concept, so let's look at each aspect separately.

The first part of applying this concept is to understand the benefits of EJBs. The central idea behind Enterprise JavaBeans, particularly entity beans, is to create an "abstract persistence mechanism." EJBs provide a generic, object-oriented way to manage data without worrying about the details of what's underneath. So we describe the data we want to store, along with transaction characteristics, security mechanisms, and so on, and the EJB container worries about translating it into whatever database or other storage mechanism we happen to use. On top of that, the container makes the beans available remotely, enforces the security constraints, and optimizes access to the beans using pools and other mechanisms. It seems like a pretty good deal.

The other significant aspect of the benefit/cost concept involves understanding that there are also substantial costs to using EJBs. EJBs add significant complexity to an application. EJBs must be created, looked up, and referenced using JNDI, and a dizzying array of home, remote, and local interfaces. While containers use caching and pooling to help, EJBs are often a memory and performance bottleneck. And, of course, you often need to negotiate with the purchasing department to buy the container.

Choosing whether to use EJBs comes down to one key issue: solving the problem at hand. EJBs are a great solution when their benefits line up with the features you need. If you don't need to use an existing database, using container-managed persistence can be quite efficient.[2] If you need to add transactions to otherwise transactionless storage, or add secure remote access to your data, EJBs are also a good idea. Too frequently, however, EJBs are used when none of these features are needed.

Contrary to popular belief, CMP can be far more efficient than BMP in recent EJB implementations, due to built-in pooling and caching. Advanced database concepts like views and indexes, however, are still not fully matched with CMP, and mapping existing schemas to CMP can be painful, particularly when there's a lot of data normalization involved.

For example, let's go back to our web-based address book application based on an LDAP database. At the under-designed extreme, we have the magic servlet we saw earlier. While the magic servlet is not robust or extensible enough, solving the problem with entity EJBs is overkill. Figure 12-2 shows a sketch of the EJB solution: an address command in the presentation tier uses an address EJB, which in turn communicates with the underlying LDAP directory.
 
Figure 12-2. A poor use of entity beans

What are the EJBs adding? Chances are, the LDAP directory already provides some of the basic EJB features, such as remote access to the data, security, and maybe even transactions. If the AddressCommand is well defined, it will provide a level of abstraction between the controller and the underlying LDAP. Since we're stuck with the existing LDAP database anyway, the EJBs are not really protecting us from changes to the underlying storage. In the end, there are no real advantages to using EJBs in this case, and the costs in terms of development and performance outweigh the benefits.
12.4.1.1 Escaping EJBs

What are our options, if EJBs are out of the picture? If it's entity beans we gave up, usually the answer is just plain JavaBeans. A command interface looks a whole lot like an EJB, anyway: there are usually setter methods to describe the arguments to the command, business methods to perform the actual command, and getter methods to read the results. We simply build a Command like we would a BMP entity bean, by communicating directly with a database. Since the fundamental bean structure is preserved, it's usually a simple task to switch back to EJBs if we need the features later.

There are, of course, other alternatives. For instance, storing data in XML files or as serialized objects works for simple applications. In more complex cases, Java Data Objects (JDO) provide a simple way to persist arbitrary Java objects without many of the complexities of EJBs.[3] A flexible but more complicated option is to use a variation of the Service Locator pattern in conjunction with façades to hide whether beans are local or remote at all.

In fact, some developers have suggested that using JDO in conjunction with session EJBs provides a better architecture than BMP entity EJBs, but we'll leave that debate for a different book.

On the system logic side, consider turning stateful session beans to stateless session beans (see Section 12.4.3") and evaluate your stateless session beans to determine whether they should be EJBs. If not, think about replacing them with business delegates.

The following criteria can help determine whether you can safely convert your session beans into business delegates:
 
·         Transaction management is locally controlled, such as with a transaction wrapper.
·         Entity beans are not being used.
·         The session bean is just a gateway to an additional remote service (such as a DAO or PAO).
·         A small number of clients (such as a presentation tier) will be using the business component.
·         Business processes all have to run in the same environment.

If most or all of these conditions are true, there won't necessarily be much of a benefit to using session beans. Transaction management, in particular, is often a simpler problem than it is sometimes portrayed as: EJBs make it easy to distribute transactions across multiple resources, including databases and MOM middleware, but if all your transaction management needs are focused on simple database calls (or invoking DAOs), a transaction wrappe
Tuesday, 15 September 2009 11:48

J2EE Design Pattern - Business Tier Interfaces

Written by Vicky
Business Tier Interfaces
Business tier interfaces connect the domain model with the client (in thick-client applications) or the server-side presentation layer (in web applications). They also implement some of the business logic for an application, controlling and limiting the actions that the presentation tier can perform on the domain model.
This chapter focuses on patterns for packaging and presenting the business logic of an application. The Business Delegate pattern and the Session Façade pattern address the organization of process logic and the division between the domain logic and the process logic. As an added bonus, both of these patterns provide performance enhancements in addition to their organizational benefits. We'll also discuss the Business Delegate Factory pattern, which allows us to build more effective non-EJB applications by creating our own versions of some of the services provided by a full application server.
We also cover two patterns for connecting to remote business services. The Service Adapter pattern, which is a variation on the original Gang of Four Adapter pattern, can be used to provide a useful Java-based interface to non-EJB business tier resources. The Service Locator pattern provides centralized management of connections to Enterprise JavaBeans and other remote resources.

9.1 Abstracting Business Logic

The last few chapters explored ways to keep the presentation tier and the business tier separate. We accomplished this by wrapping the domain logic for the system in both regular and Enterprise JavaBeans and introducing various controller patterns, including the MVC and Service to Worker patterns, in order to mediate the interaction between the tiers. This decoupling makes the overall system easier to understand and maintain. But without a good way to communicate between the tiers, the advantages can quickly be lost. The Business Delegate and Business Delegate Factory patterns provide client-side objects that flexibly connect the presentation and business tiers.

9.1.1 Business Delegate

In an MVC design, the controller still has to interact directly with the business tier (the model). The view will do so as well, although in a read-only fashion and mediated through the controller. This exposes the underlying implementation details of the business tier to the presentation tier. The application needs to know enough about the business tier to perform the operations requested by the client, and enough about the networking infrastructure between the presentation tier and the business tier to locate the business objects in the first place. The result is a tightly coupled application.

The Business Delegate pattern defines a client-side object that handles communications with the business objects. It fulfills the model role in an MVC framework. The business delegate doesn't necessarily contain any business logic itself, but encapsulates knowledge about how to locate, connect to, and interact with the business objects that make up the application. These objects might be in the same JVM, or they might be remote Enterprise JavaBeans, CORBA components, web services, or other resources. The business delegate is also responsible for returning enough data to the controller to allow the controller to instantiate an appropriate view.

The business delegate wraps access to a series of business objects and business services into a single, easy-to-implement application call. It can also incorporate all of the networking code required to access those resources, including any retries, caching, or exception handling that might be required. Networking or database access exceptions can be converted into application exceptions for consistent and user-friendly handling.
 
The UML diagram in Figure 9-1 shows a basic set of object relationships for an application using business delegates. The client interacts with the business delegate object, which in turn interacts with a set of business services. Some of these services are instantiated directly, and others are retrieved via a service locator class. The service locator provides a directory interface to locate the various business services used by the business delegate. In EJB environments, this is often a JNDI server. We cover service locators later in this chapter.
 
Figure 9-1. Business delegate

The major difference between our definition of Business Delegate and others is that we don't consider them to be pure EJB front ends. Rather, we consider them the client-side equivalent of an EJB session bean: an object that contains a front end to the process logic underlying an application. It doesn't matter whether the business delegate object implements that logic itself, parcels it out to other components, or does a little of both. The presentation tier delegates business process responsibilities to the business delegate, and that's more or less the end of that.

Our version varies from the version presented in Sun's J2EE Patterns collection.[1] For one thing, we make the Service Locator component optional. While Service Locators are often a good idea, we don't consider them vital to a business delegate implementation.
9.1.1.1 Organizing business logic into business delegates

If none of the external resources available to the business delegate are capable of incorporating all of the business logic, then the business delegate's own implementation should provide the missing elements. For example, consider a use case that involves retrieving stock information from a web service, computing a shipping charge, and submitting stock updates and shipping information to two additional web services. Because business delegates can be shared, we don't consider it bad practice to include the code for computing shipping charges in the business delegate implementation. Of course, it does make sense to consider ways to move that functionality into other areas that can be reused more easily, but that's almost always true. Incorporating the code directly into the presentation tier (having a servlet compute the charges before submitting the order), on the other hand, would easily prove problematic.

The quantity of business logic included in the business delegate depends on the application's persistence model. If the business tier consists exclusively of EJB entity beans that represent the data model, the business delegate will, of necessity, have to incorporate a substantial amount of domain knowledge. It must know which entity beans to create, remove, or update to perform a particular activity. A delegate for a legacy interface, on the other hand, may simply relay calls to an existing API that handles object management. In both cases, we consider the business delegate to be part of the business logic tier, even if the object itself is instantiated at the client tier.

We'll talk more about the division of business logic between business delegates and EJBs later in this chapter, when we discuss the Session Façade pattern.
9.1.1.2 Business delegate implementation

In an iterative or distributed environment, the business delegate can be stubbed out first, allowing development to proceed on the presentation tier while the ultimate business logic implementation is worked out. For applications that include complex relationships with external systems, this approach substantially accelerates development.

Example 9-1
shows a very simple business delegate. It performs a data validity check and then uses a DAO object to update the domain objects. In a real application, the business delegate doesn't need to be much more complex. It should be easy to see how we would convert this class to an EJB session bean.
Example 9-1. A business delegate
public class PatientManagementDelegate {
 
 public static PatientDTO createNewPatient(PatientDTO patient) 
    throws InvalidPatientException{
 
    if(patient == null|| patient.getFirstName( ) == null 
        || patient.getLastName( ) == null) 
          throw new InvalidPatientException(
            "Patient Records Require Full Name");
    
    PatientDAO pDAO = PatientDAOFactory.getPatientDAO( );
    PatientDTO newPatientRecord = pDAO.createPatient(patient);
 
    return newPatientRecord;
 }
  
}
The implementation of the business delegate can include other patterns as well, further hiding the business logic's complexity from the client. For example, a business delegate can use the Gang of Four Strategy pattern to retrieve data from different sources depending on runtime requirements or changing infrastructure (we touched on the Strategy pattern in Chapter 2).

In an EJB environment, business delegates usually work as a front end to a session bean (specifically, to a session façade, which we'll discuss later in this chapter). Implementing the presentation tier-to-EJB tier connection this way insulates the presentation tier programmers from the EJB environment, and simplifies error handling, since the various EJB exceptions can be caught, handled, and either resolved within the delegate or reported to the presentation layer in a consistent, simplified manner. A business delegate can throw exceptions related to the business process rather than exceptions related to the EJB environment.
9.1.1.3 Nesting business delegates

Since a business delegate is an access point to business logic and the domain model, there's no reason it can't use the resources of other business delegates. Business delegates can be nested arbitrarily deep, particularly when you're not in an EJB environment. This ability allows you to create separate business delegates for each use case and combine them as needed to implement the master use cases for your application.

For example, Figure 9-2 shows how a servlet, accessing a business delegate object to submit an order to a purchasing system, might actually invoke three different delegates, even though the servlet only sees one of them.
Figure 9-2. Nested business delegates
 
Nesting business delegates means that we have to keep track of the resources each delegate uses. For example, if each call to a business delegate retrieves a database connection and doesn't return it until all processing is completed (whether by instantiating DAO objects or retrieving the connection directly), a call stack containing five business delegate instances might hold onto five separate database connections. This means that a pool of 25 database connections can only support 5 concurrent users.

Using nested business delegates in an EJB application could result in inappropriate connections between different EJBs. If a session bean uses a business delegate to access another session bean, the business delegate may have to make a remote connection to the second bean, even if it's located in the same EJB server. If the session bean connected directly, it could easily use local interfaces instead. We'll address this issue later in this chapter with the Session Façade pattern.

The other major issue raised by nested business delegates is transaction control. A presentation tier programmer will, absent indications to the contrary, expect that each call to a business delegate method takes part in one transaction. If each business delegate creates its own transaction, the nested delegates will handle their transactions separately from the parent delegate. At best, this process results in incomplete rollbacks when the parent delegate fails; at worst, it will result in database resource locks and the application slowing or grinding to a halt. Since this isn't a simple issue, we'll look at transaction issues in enterprise applications in much more detail in the next chapter, including a pattern, Transactional Context, which addresses the problem specifically.
9.1.1.4 Stateful business delegates

Business delegates can be stateful or stateless. To use a stateful business delegate, generate an instance of the business delegate class. To create a stateless business delegate, declare the business delegate methods as static, and call them accordingly. You can also make the business delegate class a singleton. Either way, all classes running in the same Java VM and class loader will share a stateless business delegate. For web applications, this means that all the code will share the delegate.

The tradeoffs between stateful and stateless business delegates are almost identical to the tradeoffs between stateful and stateless session beans in EJB. Stateful delegates require more resources and can be marginally slower, due to the overhead of creating the additional objects. On the other hand, they allow you to configure a particular instance to your needs, making the delegates themselves easier to reuse. Stateless delegates require less memory and present a simpler interface to the programmer.

Here's a rule of thumb: if a business delegate requires a resource that is both expensive to create and that must be created specifically for the current user (such as a JAAS security principal), and if that resource will be used multiple times within the same delegate by the same thread, use a stateful delegate. You should also use a stateful delegate if the delegate needs complex configuration specifically for the current invocation, rather than trying to pass in all configuration information with each method call. Otherwise, look for opportunities to use a stateless delegate.

9.1.2 Business Delegate Factory Pattern

Since the simplest business delegates are just objects with static methods, we don't need to worry about creating or configuring them. But once we start using stateful business delegates, things get more complicated—even with stateless delegates we can eventually accumulate so many of them that it becomes hard to keep track. Architectures using business delegates face the following problems:
 
·         No standard for instantiating business delegates, making it difficult to exchange one delegate for another
·         Instantiation code, which may include configuring the delegate to access runtime-specific resources, is spread across the application
·         No centralized directory of available business logic

We can address these points with the Business Delegate Factory pattern. The Business Delegate Factory pattern is specialization of the Gang of Four Factory pattern. A business delegate factory is a single object responsible for creating instances or one or more kinds of business delegates.
 
Depending on your application, the factory can produce a particular kind of business delegate (resulting in one factory per delegate class), or a set of delegates related by their configuration requirements or general functionality. Having a broad-spectrum factory makes it easier to find the various business delegates within an application, but also introduces additional compilation dependencies.
 
Like business delegates themselves, business delegate factories can be stateful or stateless. The same rules apply: if the factory needs to be configured for the current thread/user/block of code, or if creating a new delegate instance requires an expensive resource that cannot be shared between all users of the application, consider a stateful factory. Otherwise, consider a stateless factory.
 
Figure 9-3 shows the sequence diagram for a stateful factory creating a stateful business delegate. It's a simple process: the client application creates a new instance of the factory by calling a static newInstance( ) method. It then calls a setAttribute(...) method to configure the factory, and finally requests an instance of a particular business delegate type. The factory creates the delegate instance and returns it to the client. At the end of their useful lives, both the factory and delegate objects go out of scope and are garbage-collected.
 
Figure 9-3. Stateful business delegate factory
A stateless business delegate factory would look similar but could include all of the code executed in the newInstance( ) and setAttribute( ) methods in static initialization blocks or in the getBusinessDelegate( ) method, which would now be a static method on the delegate factory class. If we implement the delegate as a singleton, the initialization can still take place at startup.
9.1.2.1 Modifying business delegate behavior

The Business Delegate Factory pattern lets you add functionality to your business delegates at runtime. As a simple example, consider logging. An application might need to support logging calls to business delegate methods but require different levels of detail, or different outputs, depending on the current status of the application. The simplest way of implementing this functionality (and the road most often taken) is to implement the logging functions in each business delegate object, perhaps tagging them with a "Loggable" interface, and toggling logging on or off via a centralized control class or at creation-time within the factory.

Other solutions take better advantage of the object-oriented nature of Java and create wrapper classes for each business delegate. The factory can wrap each delegate in the appropriate logging wrapper when logging is required, and skip the step when it isn't. The problem is that we need to maintain a separate logging wrapper for each business delegate class, and update them at the same time we update the delegate. It's a lot of work, and a lot of class profusion.

Obviously, we're leading up to something! The Java reflection API (which we've already seen in Chapter 8) includes a class called Proxy, which allows you to dynamically create an object that implements a given set of interfaces. An InvocationHandler object handles calls to methods on those interfaces, and the entire assemblage is referred to as a proxy object. Most uses of this class involve taking an existing object, extracting its interfaces, and creating a new object that implements those same interfaces while providing some additional functionality. The new object can delegate method calls to the original object or handle method invocations itself. Figure 9-4 shows how this can work in practice.
The custom InvocationHandler includes a reference to the wrapped object. When the application calls methods on the proxy object, the invocation handler forwards the method on to the original object and returns the results to the application.
 
Figure 9-4. Wrapping an object with an InvocationHandler

Example 9-2
shows how we can apply this technique to the logging problem. The DelegateLoggingWrapper class includes a single method, decorate( ), and an inner class defining a LoggingWrapperHandler, which implements the InvocationHandler interface. The invoke( ) method prints out the name of the method and the arguments passed into it, invokes the method on the original object, prints another message confirming success, and returns the result of the method call. In the next chapter, we'll use this approach to handle transaction management within and across business delegates.
Example 9-2. DelegateLoggingWrapper.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
final class DelegateLoggingWrapper {
    /**
     * Decorates a business delegate object with a Logging Wrapper. 
     * The object returned by this method will implement all of the 
     * interfaces originally implemented by the target
     * and loaded by the same class loader as that of the target.
     * @param delegate The Business Delegate to wrap
     * @return The business delegate wrapped in this wrapper
     */
    static Object decorate(Object delegate) {
        return Proxy.newProxyInstance(
            delegate.getClass().getClassLoader( ),
            delegate.getClass().getInterfaces( ),
            new LoggingWrapperHandler(delegate));
    }
 
    static final class LoggingWrapperHandler 
                       implements InvocationHandler {
        private final Object delegate;
 
        LoggingWrapperHandler(Object delegate) {
            this.delegate = delegate;
        }
 
        /** Invoke the target method, but display logging 
            information first. */
        public Object invoke(Object proxy, Method method, 
                             Object[] args)
            throws Throwable {
            System.out.println("Invoked Business Delegate Method: " +
                method.getName( ));
 
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    System.out.print(args[i]); 
                    System.out.print( 
                      (i < (args.length - 1)) ? "," : "\n");
                }
            }
 
            Object result = method.invoke(delegate, args);
            System.out.println("Completed Without Exception");
 
            return result;
        }
    }
}
Example 9-3 shows how to use invocation proxies in the business delegate factory itself. We've created a static factory object that produces runtime instances of each delegate object (to save space, we've included only one delegate type). The user can call static methods on the class in order to start or stop logging. If logging is enabled, the DelegateLoggingWrapper is used to add logging capability. Note that we've shifted the logging/no-logging decision all the way down to the wrap( ) method, rather than placing it in the delegate creation methods. While this adjustment is marginally slower, it reduces the amount of code we need to write in each delegate creation method, and makes it easier to add support for additional wrappers later.
Example 9-3. BusinessDelegateFactory with logging
public class BusinessDelegateFactory {
 
 private static boolean useLogging = false;
 
 public static PatientManagementDelegate 
                 getPatientManagementDelegate( ) {
    PatientManagementDelegate delegate = 
        new PatientManagementDelegateImpl( );
    return (PatientManagementDelegate)wrap(delegate);   
  }
 
 private static Object wrap(Object o) {
    if(useLogging)
      return DelegateLoggingWrapper.decorate(o);
    return o;
 }
  
  public static void startLogging( ) {
    useLogging = true;
 }
 
 public static void stopLogging( ) {
    useLogging = false;
 }
 
 public static boolean getLogStatus( ) {
    return useLogging;
 }
}
You probably noticed that the proxy object requires interfaces, rather than concrete classes. Rather than maintain a single class for each business delegate we want to wrap, we now need to maintain an implementation class and an interface. This is simple enough to do (and still less work than maintaining separate wrapper classes for each delegate, since it's easy to update the interface at the same time a delegate changes: no additional code needs to be written). We assume you already know how to create an interface, but for completeness, Example 9-4 shows the interface for the patient management delegate.
Example 9-4. PatientManagementDelegate.java (interface)
public interface PatientManagementDelegate 
{
 public PatientDTO createNewPatient(PatientDTO patient) 
    throws InvalidPatientException;
}
Example 9-4 expects a PatientManagementDelegateImpl object that implements this interface. The code for this class is exactly the same as in Example 9-1, but renamed and with an implements clause.
This approach to modifying behavior on the fly does have performance implications. Each request for a business delegate now carries the overhead of creating the proxy object, which increases the time required to create a new business delegate instance. Each method call also incurs additional overhead, both for the reflection activity itself and whatever activities the wrapper performs. In absolute terms, the difference due to reflection is measured in microseconds, and we don't consider it significant, particularly given that the business delegates and the wrapper objects are likely to be participating in much more resource intensive activities.
Since the Factory pattern itself is fundamental to good object-oriented programming (out of everything in the original Gang of Four book, it may well be the pattern most frequently encountered),[2] it's worth keeping the proxy approach in mind when implementing other areas of your system.

9.2 Accessing Remote Services

Business delegates are great for providing local code with access to business resources, whether the resources themselves are local or not. For local resources the data lives on the same server—maybe even in the same JVM—as the business delegate. In these situations, connecting to the data is not a huge concern. J2EE, however, is designed to handle much more complicated scenarios. An enterprise J2EE deployment typically involves resources that are distributed between multiple servers. To fulfill requests, the servers hosting the presentation tier may need to communicate with application servers, messaging middleware servers, database servers, and legacy IS systems. Finding all these servers and maintaining the various connections can quickly complicate otherwise simple business delegates.

Since the work of connecting is not central to the business delegate, it is often beneficial to build a separate object that the delegates can use to access remote services. The Service Adapter and Service Locator patterns describe ways to do this, the former for non-J2EE business services and the latter primarily for EJBs. Figure 9-5 shows how the service locator and service adapter act as intermediaries between the business delegates and business services.
 
Figure 9-5. Using service adapters and locators

9.2.1 The Service Adapter Pattern

A business delegate might make use of several services to fulfill a particular use case. In order to keep the business logic code understandable and maintainable, we want to use the simplest interfaces possible. A service adapter encapsulates interactions with a remote service, hiding details of the implementation when they aren't central to fulfilling the business need.

The Service Adapter pattern is a variation on the Gang of Four Adapter pattern. The Adapter pattern wraps a class in a superclass that implements a standard interface. The Service Adapter pattern goes one step further by wrapping a remote service in a standard Java object that can be used without knowledge of the underlying access mechanism. The Java wrapper is responsible for:
 
·         Locating the Remote Service.
·         Translating Java method calls into a format that the remote service understands.
·         Accessing remote functionality.
·         Translating results into a pure Java representation.

The Service Adapter pattern is overkill for EJBs, which already map business methods to Java methods. The translation activities are not required, and the directory services abstracted by a service adapter can be better addressed in the EJB context with the Service Locator pattern, discussed later in this chapter.

However, if the native interface to the external service is not Java, a service adapter can bridge the gap. A good example is an application that needs to access a SOAP-based web service. The service might be delivered by SOAP over HTTP, SOAP over SMTP, or via specialized, routed protocols like ebXML. The service adapter hides the complexities of creating a SOAP or ebXML message, allowing the developer to substitute different transport mechanisms as the needs of the application evolve. A SOAP-based service adapter in a prototype system can be replaced with a JMS-based adapter before going to production. Figure 9-6 shows a service adapter for a SOAP web service.
 
Figure 9-6. Service adapter for a SOAP web service

In J2EE 1.4 or earlier versions with the appropriate add-on modules, the JAX-RPC API and support tools can be used to build service adapters for web services. This largely eliminates the need to hand-code service adapters for web services.
The most recent Java IDEs support building service adapters directly from WSDL definition files. Some tools do this in a more platform-independent way than others, so it's worth watching for portability issues when using such tools.

However, most of the generated code is either already reusable or can be easily modified to be so. Let's look at how this might work with a simple web service. Sticking with our health care theme, imagine a web service that returns a patient's medical records. Since complex data is more useful than simple data (and because we don't want to have to execute a few dozen web service requests for each use case), we've written the service to return a number of pieces of data with each request, in the form of a complex XML type. (If you're new to web services programming, now would be a good time to go read Java Web Services, by Dave Chappell and Tyler Jewell, also published by O'Reilly.)

A call to a web service can return a simple data type (numbers, strings, etc.) or a complex type. Complex types are defined within the WSDL file that specifies the web service, in the form of embedded XML Schema documents. In this case, the schema for the patient record type looks like this:
<schema
         targetNamespace="http://chapter9/IMedicalRecordService.xsd"
         xmlns="http://www.w3.org/2001/XMLSchema"
         xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
         <complexType name="chapter9_PatientRecord">
            <all>
               <element name="FirstName" type="string"/>
               <element name="LastName" type="string"/>
               <element name="MiddleName" type="string"/>
               <element name="Address1" type="string"/>
               <element name="Address2" type="string"/>
               <element name="City" type="string"/>
               <element name="State" type="string"/>
               <element name="Zip" type="string"/>
               <element name="Country" type="string"/>
               <element name="PatientID" type="long"/>
            </all>
         </complexType>
      </schema>
Within our application, we've defined a JavaBean, PatientRecord, which corresponds with this type. The JavaBean includes the same String and long properties, in traditional get/set form, and is otherwise indistinguishable from any other JavaBean.

Example 9-5
shows a class that uses the Apache SOAP toolset to identify a web service, calls its getMedicalRecord( ) method with a patient identifier as a parameter, and translates the return value from the XML defined in the WSDL file (shown above) into the JavaBean defined within our application. It then returns the JavaBean to the code that called it.

The code is pretty simple, and it gets even simpler once you realize that it's largely auto-generated: our IDE put most of the adapter code together based on the WSDL file and the JavaBean. All we did was clean it up and replace a vendor-provided SOAPHTTPConnection implementation with Apache's freely available version.
Example 9-5. MedicalRecordServiceAdapter.java
import org.apache.soap.transport.http.SOAPHTTPConnection;
import org.apache.soap.encoding.soapenc.BeanSerializer;
import org.apache.soap.encoding.SOAPMappingRegistry;
import org.apache.soap.util.xml.QName;
import org.apache.soap.*;
import org.apache.soap.rpc.*;
 
import java.net.URL;
import java.util.*;
 
public class MedicalRecordServiceAdapter {
 
 public MedicalRecordServiceAdapter( ) {
    m_httpConnection = new SOAPHTTPConnection( );
    m_smr = new SOAPMappingRegistry( );
 
    BeanSerializer beanSer = new BeanSerializer( );
   m_smr.mapTypes(Constants.NS_URI_SOAP_ENC, 
      new QName("http://chapter9/IMedicalRecordService.xsd", 
        "chapter9_PatientRecord"), chapter9.PatientRecord.class, 
        beanSer, beanSer);
 }
 
 public String endpoint = 
    "http://service.hospital.org/records/MedicalRecordService";
 private SOAPHTTPConnection m_httpConnection = null;
 private SOAPMappingRegistry m_smr = null;
 
 public PatientRecord getMedicalRecord(Long patientID) 
    throws Exception {
    PatientRecord returnVal = null;
 
    URL endpointURL = new URL(endpoint);
    Call call = new Call( );
    call.setSOAPTransport(m_httpConnection);
    call.setTargetObjectURI("chapter9.MedicalRecordService");
    call.setMethodName("getMedicalRecord");
    call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
 
    Vector params = new Vector( );
    params.addElement(new Parameter("patientID", 
      java.lang.Long.class, patientID, null));
    call.setParams(params);
 
    call.setSOAPMappingRegistry(m_smr);
 
    Response response = call.invoke(endpointURL, "");
 
    if (!response.generatedFault( )) {
      Parameter result = response.getReturnValue( );
      returnVal = (PatientRecord)result.getValue( );
    }
    else {
      Fault fault = response.getFault( );
      throw new SOAPException(fault.getFaultCode(), fault.getFaultString( ));
    }
 
    return returnVal;
 }
 
}
Using this service adapter in a regular application is easy. To print out a patient's first name, all you would need to do is:
try {
      MedicalRecordServiceAdapter adapter = 
         new MedicalRecordServiceAdapter( );
      System.out.println(adapter.getMedicalRecord(new Long(4)).getFirstName( ));
    }
    catch(Exception ex) {
      ex.printStackTrace( );
    }
9.2.2 Session Façade

Enterprise JavaBeans take much of the complexity of building a distributed system out of the hands of the developer. They do not, however, eliminate that complexity: they hide it under an easy-to-use implementation (or at least easier). Just because you, the programmer, don't have to write the code for transporting data across a TCP/IP connection, doesn't mean that the data doesn't have to get transported.
Performance can be a challenge in EJB architectures, particularly when you don't have a lot of computing muscle to put behind your application. If a client application needs to access multiple entity beans in order to perform a transaction, it must make a network call each time it retrieves a new entity bean or calls an EJB method. The performance consequences are potentially huge, since a single network invocation can take several hundred milliseconds or more, depending on the amount of work that has to be done on the other side and the state of the intervening network.

The Composite Entity Bean pattern reduces the number of entity beans in a system and makes them easier to manipulate but does not address the broader performance problem. To make matters worse, even the best entity bean designs usually involve more than one bean per use case. A client wishing to modify more than one entity bean in the course of a transaction must handle transaction control itself, via the JTA API or another mechanism. Alternately, the business logic for the specific use case can be built into one entity bean, but this approach results in a massively overcomplicated entity bean design, in which domain objects have far too much knowledge of the context in which they are used.
EJB entity beans also don't provide much help when it comes to structuring business logic. The Business Delegate pattern helps organize an application's business logic in a convenient, easy-to-use manner, but doesn't control the number of network calls or simplify transaction management (although the burden can be shifted to the Business Delegate from the client application itself, which can be of some advantage to the programmers involved).

The Session Façade pattern addresses these issues by grouping sets of activities into a session bean that can be invoked by a client to complete an entire use case at once. The façade is a business-tier object that hides the session beans, entity beans, and other business services from the presentation tier.

Using the session façade simplifies transaction management. Since transaction control is implemented at the first point of entry into a method on the EJB, a business method attached to a session façade can manipulate all of the entity and session beans required to fulfill the current use case within a single transaction.

Figure 9-8
shows a potential class diagram for an EJB session façade that provides two business methods and makes use of generic business objects, EJB session beans, and EJB entity beans (in one case directly, in another indirectly via the session bean). The session façade can also use service adapters to access non-EJB resources.
 
Figure 9-8. A session façade class structure

Session façades provide a performance boost because interactions between EJBs within a server are much more efficient than interactions between EJBs and remote clients: with EJB 2.0, local beans can use local interfaces to communicate with one another, cutting out the networking layer.
Not all session beans are session façades! Business rules usually should not be implemented within the façade itself. A mathematical formula assessing a customer's credit rating, for example, belongs either in the entity bean representing the customer or in a separate, "utility" session bean, depending on how tightly coupled it is to the entity and whether the rule needs to be reused in other contexts. Conversely, remote applications shouldn't access any EJBs except for session façades. That same credit rating assessment should be included in (or at least accessible via) a session façade when the use case reports a credit assessment back to the presentation tier.

Use cases can be divided between a set of façades, although splitting use cases between session façades can be as much an art as a science. Creating a separate session façade for each use case can rapidly lead to a profusion of session façades. At the same time, avoid creating a single session façade for the entire application, unless the application is extremely small. All-encompassing session façades are sometimes known as "God Façades" or "God Objects." A God façade inevitably becomes difficult to maintain as the number of included use cases increases.

When organizing logic into a session façade, try to locate groups of related use cases. An e-commerce system, for example, might use a single session façade for all activities related to processing sales: checking inventory, setting shipping, arranging handling, and billing customers. Another façade might support catalog activities, and a third could handle account management for individual customers.
It's helpful to organize your use cases in an outline format, using the highest-level items as your top-level session façades. This technique usually leads to a nice balance between class complexity and class profusion.
9.2.2.1 Implementing a session façade

The EJB 2.0 specification introduced local EJBs, which can boost the performance of session beans by avoiding excessive round trips to the same server (see the Round-Tripping antipattern in Chapter 12). By restricting local EJBs to the same JVM, much of the overhead associated with translating data to and from network formats can be avoided. Example 9-6 shows a simple session façade, which uses the local interfaces of a number of EJBs to process a sale.
Example 9-6. A session façade EJB
import javax.ejb.*;
import java.util.*;
import javax.naming.*;
 
public class SaleFacadeBean implements SessionBean {
    private SessionContext context;
    private LocalCustomerHome customerHome;
        private LocalItemHome itemHome;
        private LocalSalesRecordHome recordHome;
    
    public void setSessionContext(SessionContext aContext) {
        context=aContext;
    }
    
    public void ejbActivate( ) {}
    public void ejbPassivate( ) {}
    
    public void ejbRemove( ) {
        customerHome = null;
        itemHome = null;
        recordHome = null;
    }
 
    public void ejbCreate( ) {
        try {
            InitialContext ic = new InitialContext( );
            customerHome = 
               (LocalCustomerHome)
               ic.lookup("java:comp/env/ejb/local/Customer");
            itemHome = 
               (LocalItemHome)
               ic.lookup("java:comp/env/ejb/local/Item");
            recordHome = 
               (LocalSalesRecordHome)
             ic.lookup("java:comp/env/ejb/local/Record");
        } catch(Exception ex) {
            throw new EJBException(
           "Error looking up home object: " + ex, ex);
        }
    }
 
    public ReceiptDTO doSale(int itemNumbers[], int customerId) {    
        try {
           LocalCustomer cust =     
          customerHome.findByPrimaryKey(customerId);
      
           LocalItem items[] = new LocalItem[itemNumbers.length];
                for (int i = 0; i < itemNumbers.length; i++) {
               items[i] = itemHome.findByPrimaryKey(itemNumbers[i]);
           }
Sitelinkx -->	  
Tuesday, 15 September 2009 09:47

J2EE Design Pattern - The business Tier

Written by Vicky
 The Business Tier

Business tiers are about complexity, memory, and scale. Business tiers are complex because they implement the rules the business must follow. The rules themselves can be simple ("mark each item shipped as removed from inventory," "when shipping to Massachusetts, add a 5% sales tax") but the interconnected system of rules can rapidly become more than any one person can easily handle. Memory, in the long-term recollection sense rather than the hardware sense, is important because businesses need to record every activity they participate in. Humans aren't well equipped to do this reliably, at least without tools and time. Finally, business tiers are about scale. Even if process and record-keeping activities are simple enough to be done by hand, repeating them several thousand times over the course of a day is costly, error-prone, and inflexible.[1]

In the business tier, more than anywhere else, you have to keep an eye out for the unexpected. Creating domain models and business logic that meet the growth requirements of the environment presents a challenge to system architects. Even when the initial application requirements may not seem to impose much in terms of complexity, memory, and scale, change is inevitable. Business tiers require a substantial investment, so once created, they tend to be used and extended over the long haul. In fact, we rarely see successful enterprise applications enter an end-of-life stage. They're much more likely to be incorporated as a component of something else. Fifteen years from now there will be a vendor making a lot of money selling adapters to incorporate your old J2EE applications into whatever happens to be the new dominant environment. You'll often do the same thing yourself, integrating existing legacy systems into new J2EE frameworks.

A poorly implemented business tier imposes limitations on a system that fancy user interfaces can't overcome. On the other hand, a difficult user interface, or a middle tier that is slow or difficult to extend, prevents effective use of even the best-designed business and domain logic. A full J2EE application is an integrated whole, however compartmentalized it may be, that makes each tier more or less equally important. The art is in the interfaces that create the smoothly functioning whole. The business logic and domain model are the starting point that everything else grows out of.
  
6.1 The Business Tier
There are several ways to slice up a J2EE application. It's quite common to hear the phrases domain logic, business logic, business object, business tier, and other variants tossed around with wild abandon, resulting in more than a little confusion. What is the business tier? Is the application server part of the business tier, or does it enable the business tier? What about the database? The tables in the database? The servlet container?
All business tiers, as we use the term, have two functions in common. Business tiers:
  • Provide a structured model for application data.
  • Provide procedures for performing business-related activities.
Most also share the following characteristics. Business tiers:
  • Are shared by multiple clients.
  • Provide a framework for transactions, ensuring that the information in the domain model remains in a valid state.
  • Provide a persistence mechanism for application data.
Most enterprise applications ultimately serve multiple clients, whether different types of clients (servlet applications versus Swing GUIs) or multiple instances of the same type (10,000 Swing GUIs, or an array of web servers). Most applications will use some transaction functionality at least once, but transaction implementations can be done via JTA, EJB, JDBC, or raw objects, depending on the needs and desires of the designer. Persistence is commonly associated with the transaction logic, often via JDBC and a database. Chapter 10 is devoted to transactions and concurrency management, so we'll skip lightly over it here.
The persistence mechanism, although we've listed it under the "most" heading, is essentially universal. Of course, the method by which different applications implement the persistence mechanism varies tremendously, from serialized objects to Enterprise JavaBeans, to database tables and JDBC. The business tier itself might be housed in a complex application server or as a humble application in a standalone JRE (or, quite frequently, in the same JRE as the presentation tier).
6.1.1 Business Tier Components
The standard J2EE application model defines a Server Side Business Logic layer, implemented via EJBs or other objects, which optionally accesses Enterprise Information Systems. We don't find that view quite as helpful, because it doesn't address what we actually put into the system: just how we'd implement it.
For the purposes of this chapter and those that follow, we subdivide the business tier into three parts: the visible business tier, the resource layer, and the enterprise layer. The visible business tier is what's exposed to the presentation tier, while the resource and enterprise layers provide the services that allow the visible portion of the business tier to do its job.
Although the business tier can be subdivided, it isn't the same kind of subdivision that we get with the tiers themselves. The coupling between the various components that make up the business tier generally has to be quite tight: you can't create a new set of domain objects and expect all the business logic to work properly. However, with proper compartmentalization, you retain some flexibility. In most applications, the business logic isn't tightly coupled to a particular database, and as a result we can potentially change the underlying database without having to rewrite the business process code.
Figure 6-1 shows a view of the business tier. Not every business tier will look like this, of course. Components higher on the chart access components that are lower on the chart, either directly or through intermediaries. Process logic, for instance, accesses domain objects and the enterprise layer.

Figure 6-1. The business tier
 
6.1.1.1 Business tier components

Domain objects
represent the "nouns" of the application. They're the concrete things that map to real or virtual concepts within the application. Objects (or database tables) represent customers, orders, stock items, user accounts, outstanding invoices, clinical measurements, or anything else that could substitute for one of the blanks in "a ___ is related to a ___."

The business logic reflects the business process. A business process is the set of steps required to fulfill one of the system's use cases, and can be thought of as a "verb" or a system activity. Business processes don't have a life of their own except in the project management sense: once the process is complete, a record may be kept for analysis, but an instance of the process itself only exists while it works towards a particular goal. For example, when an order is shipped, the order process is complete. (The domain object containing the record of the order, however, is permanent.)

Put together, domain objects and business logic are sometimes known as the domain model. They represent the "domain" of an application, including both the physical entities and the processes.
Figure 6-1 subdivides the business logic layer into domain objects and process logic (the business processes). The process logic manipulates the domain objects. In some cases, the process logic is the only part of the application visible to any of the lower tiers. For example, a J2EE application might embed process logic in EJB session beans, or via a web services interface. The session beans or web service backend are responsible for interacting with the domain objects. This is good practice, but it doesn't make sense for every aspect of every possible application.

Both domain objects and business logic are subject to business rules. A business rule might state that a particular order is associated with one and only one customer, or that employees may only report to managers and not to programmers. The business rules for the domain apply regardless of the application. For example, an orders system and an inventory system that deal with the same domain (stock management) could theoretically use the same domain model. The business rules embedded in the model should apply equally to either application. These rules don't show up on the diagram in Figure 6-1, but instead constrain the actions of the various pieces of the business logic layer.
6.1.1.2 Supporting players

The resource layer in a J2EE application is typically a database, but it can include any persistent storage mechanisms, both locally (on disk) or remotely (in messaging, transaction management, and other support systems). Chapter 8 is devoted to the patterns that apply to the resource layer. The resource layer should be largely invisible to the presentation tier, which interacts only with the business logic objects.

Finally, the enterprise layer consists of connections to other systems, whether they're legacy systems, J2EE systems, or web services. Business processes often involve handoffs to external systems. Sometimes these exchanges are handled quickly in near real time (such as a credit card authorization for an online merchant) and sometimes asynchronously (such as a request to approve a mortgage application). Chapter 11 addresses intersystem integration in detail.
Literature on software architecture often mentions business services. In a well-designed application that is properly divided into components that have fully defined interfaces between them, a business service is simply another phrase for a business tier component.
Business Tier Services

A service is a software component that performs an action on behalf of another component. A typical action might involve retrieving a piece of information for a client, or performing a specific operation for that client, often on a remote resource.

Directories are probably the most common software service, and are a good illustration of a service because they provide access to both information and resources. A corporate LDAP directory is an example of a directory that accesses information. Normally, the directory maintains all sorts of information about employees, including simple items like names and phone numbers, as well as more complex relationships, such as whom individual employees work for. A UDDI directory, on the other hand, returns resources: rather than providing information directly, it points an application towards a web service that can help.

When a Java application accesses an LDAP directory, it doesn't manipulate an object representation of that directory. Instead, it issues a request for specific information through the generic Java Naming and Directory Interface (JNDI). The request must explicitly state exactly what information is required (either by providing a specific name or a set of criteria); in response to the request, JNDI returns an object containing the requested information. If the application needs to update the directory, and has permission to do so, it can pass the object back, again specifying exactly how the directory should store it.

In each case, the service interface acts as the medium of exchange. Other business services, including web services, work the same way, fielding requests for information or actions and returning responses.
The most important thing to remember is that web services in particular are not inherently stateful. Each service call contains all the information required to complete a request, whether the service call is requesting the name of an object, asking that an equation be solved, or providing a business transaction to post. Of course, stateful remote components do exist: they're just called distributed objects.

6.2 Domain Objects

The patterns in this chapter focus on important aspects of business tier development. We start with the Domain Object Model, which is at the heart of most large J2EE applications. The Domain Object Model defines an object-oriented representation of the underlying data of an application. The benefits of this approach should be familiar by now: the tiers integrating with the business tier become simpler and are decoupled from the implementation of the business tier, allowing changes to the resource layer level implementation without affecting the UI components. Business processes can be included in the domain object model via methods attached to the entity objects in the model or to specialized objects.
We'll also look at the Composite Entity pattern, which provides a guideline for building domain objects in an efficient way. The goal is to balance flexibility and efficiency by creating object representations that can be used in the most efficient way.

6.2.1 Domain Object Model

The domain model is the portion of the business tier that defines the actual data and processes managed and implemented by the system. The process for creating an effective domain model varies depending on the project, the information available, and the future requirements of the system.

The Domain Object Model pattern is central to most J2EE applications. The pattern is fundamentally simple: create a Java object model that represents the concepts in the underlying domain. This may seem obvious, and you may even question whether it should be considered a pattern at all. It's certainly intrinsic to EJB. On the other hand, it's possible to build applications with J2EE technology that don't use a formalized domain model at all, and it's possible to build a domain object model without using EJB.

Many web applications get along fine without a domain object model. They keep their domain model entirely in the database component, never building an object representation. In this case, the model is relational rather than object-oriented: two-dimensional tables full of data, linked to other tables via a set of shared keys. The application updates the model by executing SQL statements directly from servlets, and produces HTML pages the same way. In some cases, business process information is also held in the database, in the form of stored procedures, or it is embedded in the servlet tier.

In contrast, a domain object model represents the application's entities (which would otherwise be found in database tables) and processes (which would otherwise be scattered throughout the application). The ultimate repository may still be a relational database, and the objects that make up the model are responsible for persisting themselves to the database in an appropriate way. The presentation tier can access the Java objects instead of manipulating the database directly. In building a domain object model, we translate the business model into object terms.

Figure 6-2
shows a simple domain object model for a system that issues government IDs. We'll leave the potential civil liberties issues inherent in this system aside, and focus on the domain modeling issues instead. We have three classes, one for the federal government, one for the state governments, and one for citizens. The federal government can be associated with multiple state governments, which can have multiple citizens. We also have four classes that perform business activities. The Passport Issue class uses the federal government and the citizen classes to issue a passport. The State License Issue class is abstract, and is extended by two other classes that issue particular kinds of state ID cards.
 

6.2.2 Building an Object Model

The analysis process for building an object model depends on the project, resources available, and processes within a particular organization. We find the following general approach to be both prevalent and useful.
Building an object model for the domain requires a solid understanding of the business foundations underlying the system. Often, developers aren't in a position to supply this information on their own, particularly when they're coming in as consultants or independent contractors. The information has to come from the business users. This process isn't always simple, since the users may be busy, unavailable, or in the case of a company developing a new product, nonexistent. Even when they can be tracked down, they don't always know what they want.[3]

Nothing in this chapter should, however, be taken as an excuse for engineers to run off and develop software without input from the end user community or some reasonable proxy thereof.
6.2.2.1 Define the vision

The place to start is the business requirements for the software. Whole books have been written on the subject of gathering requirements effectively and presenting them as usable specifications. See, for example, Software Requirements by Karl Wiegers (Microsoft Press) and Writing Effective Use Cases by Alistair Cockburn (Addison-Wesley).

We find it helpful to start by creating a vision statement for the domain model. This statement, which can be exceedingly brief, should describe a high-level vision for the domain model, including its purpose and scope. An example might read: "An inventory, customer, and sales management system for use by all of the web-based applications and internal systems at XYZ Corporation." More than a paragraph is probably overkill. The vision statement should address current requirements and potential future needs, but it should take care not to overload the project with speculative features. Vision statements help to boost morale, too. Developers, like most corporate citizens, like to know that they're working on something that's been thought out in advance. A vision statement also helps keep change requests under control, since potential alterations can be evaluated in the context of the product vision.

Let's build towards the domain object model introduced in Figure 6-2. We're going about it a bit backward, since we've already shown you the model, but stick with us here. In our case, the vision statement might be, "The system will manage and issue official forms of identification for every citizen in the United States. It will support the major forms of identification issued by the federal and state governments."
6.2.2.2 Gather the user cases

The next step is to identify the use cases for the application or applications that will follow the domain model. In some situations, these use cases will be in the style introduced in Chapter 2. In other cases, you may need to work backward from a requirements specification. Working from requirements specifications can often be harder than working from pure use cases: the author of the specification may have unknowingly made some design decisions as he spelled out exactly what the system should do. Watch out for these implicit assumptions.

Our example National ID system might have several use cases, including "Issue Passport," "Verify Citizenship," and "Issue State License" (generalized from "Issue State ID" and "Issue Driver's License"). There are several actors involved, as well: the State Department, the local DMV, and citizens of the state and the country. The State Citizen actor generalizes to a Citizen, and the two use cases for issuing state IDs generalize to a parent use case for issuing state level licenses. For example, the Issue Passport use case might include the following steps:
 
1.      Verify applicant's identity.
2.      Verify applicant's citizenship.
3.      Take and scan photograph.
4.      Enter passport data into system.
5.      Issue passport.

The Driver's License use case is similar, but involves verification that the applicant has passed her driving test, has a clean driving record, and is a citizen of the state in which she is applying for a license.
6.2.2.3 Find object candidates

The next step is to identify object candidates for each use case. In our example, we need to identify citizens for each use case, and we need to store information about who has been issued a particular ID; a Citizen object is an obvious choice. The State Department and the DMV could have their own objects, but we don't need access to any other aspects of the State Department or the DMV. We do need to know which states citizens are citizens of, so we have a State class, and a Federal class to hold the states.

Citizenship is constrained via a business rule within the domain model: a citizen is a citizen of any polity in whose object they are contained. So, all citizens are federal citizens, and each citizen is also a citizen of exactly one state. This is also an example of a domain boundary for the system: it only applies to the United States, or other countries that assign citizens to two hierarchical categories for purposes of licensing. Countries that devolve these responsibilities to, say, a city within a state would need to modify the model.

We define these relationships in the class diagram by making the associations between Federal, State, and Citizenship objects composite associations, rather than simple associations. Using this approach builds the business rule directly into the domain model, and also means that we've made a trade-off: supporting multiple citizenship or state citizens who are not federal citizens would be difficult in the future.

We now have the three domain objects in the system: the federal government, the state governments, and the individual citizens. These are our "nouns." We also define four classes, one of which is abstract, to represent the use cases we're implementing. In this case, we've kept things relatively simple and built a class to handle each activity. The two state-level activities share a superclass that contains methods common to both: for instance, a method to verify state citizenship.

We're now more or less done: the resulting class hierarchy is the one we introduced in Figure 6-2. In designing all of these classes, we've tried to keep one of the fundamental principles of object-oriented programming clearly in sight: the separation of responsibilities. Each class should be responsible for as little as possible, and should only be responsible for activities that bear on it directly.

For example, the Citizen class in the example above includes methods to retrieve the licenses and IDs created by the other classes, but doesn't include mechanisms for issuing passports and drivers' licenses. While these activities affect individual citizens, carrying them out is not the citizen's responsibility. However, the Citizen class might include a method, such as verifyResidence( ), which could be used in the license issue process.
Domain Models and Iterative Development

One of the great things about Java is that it makes iterative development a lot easier than some earlier technologies. By delivering fast-paced releases that prioritize key functionality, developers can get a system out faster and incorporate user feedback and testing in more places during the development cycle. Java, and object-oriented languages in general, make it easier to build frameworks and fill in specific functionality as you go.

This approach raises some questions about domain model development, though. If, for example, the use cases that support customer account management won't be added to a system until the third or fourth iteration, should the components of the domain model that will be required by these use cases (and only these use cases) be incorporated into the initial design, or can they be incorporated later? To a certain extent, you can do both. Isolating individual tiers reduces the affect of changes made to the domain model later on: the presentation tier can remain ignorant of even substantial changes in the underlying database schema.

In general, we think it makes sense to consider all of the use cases when designing a domain model, even if you won't be implementing the user interfaces, presentation tiers, or business logic right away. Entity models, however well compartmentalized and designed, are always something of a pain in the neck to modify.

One technique that makes life easier is to put off finalizing the difficult-to-change aspects of the domain model, which are usually related to the persistence layer. Every aspect of the system is a use case, after all, even if it's not a "functional" use case. If persistence to a database table structure is a requirement, it can be postponed until later in the process, when the object model has had a chance to settle down. For development in the interim, you can serialize the object hierarchy to disk or use some of the approaches we'll discuss in Chapter 8. This method involves a bit more coding, but it can shorten the overall development cycle, since the domain model will be based more on feedback and less on sitting in a conference room trying to figure everything out with no practical data.

Designing domain models for the future involves a tricky balance of doing work now for a potential payoff later. A helpful approach when making any domain modeling decision is to consider what opportunities you might be closing off by adopting a particular approach.
6.2.2.4 Implementing a domain object model in J2EE

Traditionally, domain object models in J2EE are based on EJBs. However, just because EJBs exist doesn't mean that you need to use them. EJBs have two major advantages over Plain Old Java Objects (POJOs). First, they can be accessed remotely: the EJB server can be located on one system while the client is located on another. In design parlance, this means they are remoteable. Second, EJBs are transactional: a set of operations performed on one or more EJBs can be made contingent on the success of all the operations. We'll discuss transactions in much more depth in Chapter 10.

For enterprise applications with a Swing GUI interface, the ability to access objects hosted remotely is often vital: without this ability, the client will have to maintain its own connection with the resource tier, and changes to the business tier implementation will involve updating every single deployed client, creating an access control and scalability nightmare.

EJBs often make sense when you need a coarse-grained entity model, remote access, and integral transaction support. Typical situations in which EJBs are appropriate include applications that are geared toward frequent and complex transactions, applications in which the domain model will be accessed by a number of systems at once, either via clustered web servers or a large number of Swing GUI clients, and applications that spread transactions across multiple services (databases, messaging servers, etc.). For more on when to use and not use EJBs, see the "Everything Is an EJB" antipattern in Chapter 12.

Plain Old Java Objects can be a little more work to code, but they are easier to deploy, since they don't require an EJB container. Because they don't provide a remote interface, they can be more efficient than EJBs when distributed capabilities aren't required. For the same reason, regular objects lend themselves to a more finely grained object model than EJBs do, since each regular object maps to a single object instance (EJBs require four or more). In many web applications, the same server can run the POJO model and the servlet container, keeping everything in the same JVM.

The tradeoff is that you need to support transactions on your own, rather than delegating to the EJB container (we'll look at strategies for dealing with this in Chapter 10). POJO models can also be difficult to cluster effectively, although the greater efficiency of this approach for many applications can reduce the need for clusters in the first place, at least for scalability purposes. Most modern databases, running on appropriate hardware, easily keep up with the load imposed by a high volume site, assuming the data model was designed properly. Since a POJO object model lives in the same JVM as the web tier, it's easy to cluster several web servers and point them to the same database, provided you have the right concurrency design.

The other nice thing about a POJO object model is that you're not stuck with it. If it turns out that you need an EJB interface after all, it's relatively easy to wrap BMP Entity and Session Beans around your existing objects and move them into an EJB server.

Some applications don't need to expose the entire data model (as found in the database) as Java objects. We'll look at strategies for interacting directly with relational databases in the next chapter.

6.2.3 Composite Entity/Entity Façade Pattern

One common mistake is mapping each table in the underlying database to a class, and each row in that table to an object instance. It's easy to fall into this trap when developing Enterprise JavaBeans using Container Managed Persistence, but it can happen just as readily with non-EJB technologies like Java Data Objects, O/R mapping tools, or coding from scratch. A good data model can actually make this temptation worse.

In the EJB world, a profusion of entity beans has severe performance consequences. Each bean requires not one but several objects to support it, and the server must do more to maintain the integrity of each bean and manage resources effectively. Since clients need to access a large number of distinct entity beans in order to accomplish any given task, communication overhead causes performance degradation proportional to the number of objects involved (see the Round-Tripping anti-pattern in Chapter 12).

These issues can be ameliorated using the Composite Entity pattern, which is also known as the Entity Façade pattern.[4] We'll see a few more façade patterns over the next couple of chapters, all based on the GoF Façade pattern. The Façade pattern provides a simple interface to a complex system: one object fronting for several objects or several database tables.

This pattern is referred to as Entity Façade in Oracle's BC4J application framework.

Composite entities are simply coarse-grained domain objects. When implementing a system using EJB, rather than mapping one bean class to each table and one bean instance to each row, a Composite Entity will collect information from multiple tables and multiple rows into a single entity bean. The entire domain model may still be represented, but not as a direct mapping to the underlying persistence structure.

Composite entities aren't the exclusive province of Enterprise JavaBeans. Any object representation of a domain model entity can use this approach to make itself more efficient and easier to use. Clients accessing composite entity objects have an easier time manipulating the domain model, since they have to manage fewer EJB instances at once. This is particularly the case when the database design has already been defined and can't be changed, either due to legacy system considerations or conflicting requirements.

On the implementation side, using a composite entity allows you to improve performance in at least two ways. First, the smaller number of entity beans reduces the amount of network activity required between the client and the server, as well as between the various beans within the server. With fewer objects in memory, a given quantity of computing resources can handle that many more connections. Second, mapping multiple tables to a single bean allows you to take advantage of the capabilities of the underlying database to merge information at the SQL level rather than the object level.
6.2.3.1 A composite entity schema

Let's look at a simple composite entity schema, which we'll use in the next few chapters. The example is the core of a data structure for managing patient visits at a small hospital. We will track patients, patient addresses, patient visits, notes recorded at each visit, staff members involved in a visit, and notes on the procedures that were performed.

There's no central table in this example. Instead, the tables queried depend on the needs of the application. The database structure is normalized: any time an entity within the database, such as a patient, visit, address, or staff member is referenced in more than one place, it is pulled out into a new table with a separate primary key (we'll talk more about primary keys in Chapter 8). Similarly, data with uncertain cardinality[5] is also pulled into separate tables, with a reference back to the primary key of its logical parent. For example, a patient may have multiple addresses: Home, Office, Billing, Insurance, and so forth. Rather than add fields to the Patient table for each of these, we create a new table, PATIENT_ADDRESS, linked to the Patient table via a primary key. This allows us to add all the addresses we want. We do the same thing with visit notes, which are stored in the VISIT_NOTES table and linked to the VISIT table and the STAFF table (since there can be multiple visit notes per visit, and each visit note could be created by a different staff member, such as a radiologist or nurse). Figure 6-4 shows an illustration.
 
Figure 6-4. Patient and visit database schema

The simplest way of mapping this schema to an EJB object structure is to create a new EJB entity bean type for each table. This process allows us to easily use Container Managed Persistence, and allows simple remote updates to each type of data. On the other hand, it results in a profusion of entity beans. A healthy patient probably averages one or two visits a year, and sick patients will generally visit much more often. So the average number of yearly visits may be closer to four or five. Each visit might have 10 or more visit notes associated with it, depending on what procedures were performed. That means each patient could produce 40 or 50 new entities a year. These add up fast, since a single hospital might serve 10,000 or more patients (most of them just pop in for 20 minutes a year). Of course, a well designed EJB container will manage to avoid keeping most of this material in memory at all times, but it's still an awful lot of objects. That's the problem at the macro scale.

The An-Entity-Bean-for-Everything approach also causes problems at the micro scale. Remember that each time you access a remote EJB, you incur a network performance penalty that can be measured in milliseconds. A web page that requires accessing 40 different EJBs will take much longer to generate than one that requires 4, with a corresponding impact on your budget for application servers.

Figure 6-5
shows the hospital visit object model using a set of composite entities. There are still two classes of entity bean: the Patient bean and the HospitalVisit bean. The HospitalVisit bean contains objects representing the visit date, the attending physician, and all of the procedures performed during the visit. The Patient entity bean contains an Address object, and has a one-to-many relationship with a set of HospitalVisit entity beans.
 
Figure 6-5. Object model with composite entities

When the EJB container instantiates the HospitalVisit bean, the bean loads all of the associated visit notes, as well as the staff information for both the attending physician and for each visit note. This process may take two or three queries, but it can be optimized for performance. For example, the visit note information and visit note staff information can be retrieved with one SQL statement. Here's a simple approach to building out the objects (we'll see much more of this in Chapter 8).
// Assume visit_id variable containing the visit primary key
 
Connection con = getConnection( );
Statement stmt = con.createStatement( );
ResultSet rs = stmt.executeQuery("select VISIT_DATE, FNAME, LNAME from " +
        "VISIT, STAFF WHERE VISIT.VISIT_ID = "+visit_id+" AND STAFF_NO = SEEN_BY");
 
if(rs.next( )) {
        // ... Read visit information
}
 
rs.close( );
 
rs = stmt.executeQuery("select NOTE_DATE, NOTE, FNAME, LNAME from " +
        "VISIT_NOTES, STAFF where VISIT_ID = " +visit_id+" AND STAFF_NO = NOTE_BY");
 
while(rs.next( )) {
        // load visit notes
}
// etc.
We leave the Patient and HospitalVisit objects as entity beans because they might need to be associated with a variety of other objects (such as bills or HMOs). We also need something that external components can access. The individual procedures and addresses, on the other hand, are not necessary outside the context of the entity beans that control them.

The StaffMember class is shown twice on the diagram to indicate that a particular instance of the object isn't shared between visits and notes. Like the VisitNote and Address objects, a StaffMember object is created at need by the parent object.

In EJB applications, composite entities are more difficult to implement using Container Managed Persistence, although it's certainly possible. For easier portability, it often makes more sense to use Bean Managed Persistence. In the next chapter, we'll look at some database-related patterns that make it easier to build both BMP and POJO entity objects.
 
Tuesday, 15 September 2009 06:39

Advanced Presentation Tier Design

Written by Vicky
4.1 Reuse in Web Applications

Reusability is a driving factor in object-oriented languages, including Java. Java is full of built-in frameworks meant to promote reuse. JavaBeans provides an explicit component model, while Swing and AWT both provide reusable widget libraries. Throughout the software industry, the adoption of object-oriented programming languages in the 90s led to across-the-board development of a number of frameworks for reuse.
Sadly, there is no standard component framework in the relatively young field of J2EE web applications. While the JavaBeans component model is often used to communicate model data, there is no universal mechanism for reusing parts of views or controllers. Until quite recently, web application developers have had to build their own framework or settle for applications that were not intrinsically reusable. This problem has been recently recognized, and frameworks such as Struts[2] have gained popularity as a solution (see the sidebar "Frameworks and Patterns"). These frameworks allow controllers and views to be developed using standard interfaces and connected in standard ways.
Frameworks and Patterns

Most web application frameworks implement at least the MVC pattern, and many even claim to be "pattern-based." In general, frameworks force applications written to them to conform to certain patterns. Recognizing these patterns can be a big help in designing applications that work well in a given framework. Here's a look at two popular frameworks and the patterns they implement:
 
·         Jakarta Struts is probably the best-known web application framework. It is based on what they call a "Model 2" approach, an implementation of MVC in which you write the model and view components, and Struts provides the controller. The Struts controller is based on the Service to Worker pattern, featuring a front controller, a dispatcher configured via XML files, and a code framework for embedding application logic into actions. Struts also provides a number of utility classes and tag libraries, including Tiles, an implementation of the Composite View pattern.
 
·         JavaServer Faces (JSF) is a new web application framework from Sun. The primary goal of JSF is to provide a UI framework for web applications, allowing the development of custom, reusable UI widgets that maintain state across requests. As such, JSF is centered around the Composite View pattern, and includes an extensive tag library for developing and using these components. JSF also provides a simple implementation of the Service to Worker pattern, including a front controller, an XML-configured navigation handler, and support for actions.

4.2 Extending the Controller

In the last chapter, we discussed how to best add features to a front controller. The main problem was that adding new features directly to the controller specializes it. A specialized controller quickly becomes unwieldy, with lots of code for each specific page. Every time we wanted new functionality, we had to rebuild, retest, and redeploy the entire controller. To solve this problem, we looked at the Decorator pattern, which allowed us to dynamically add functionality to the front controller.

With decorators in place, common functions such as security are separated from the front controller. But the controller is still responsible for managing page navigation as well as instantiating actions. Since the set of pages and the set of available actions are likely to change, a tight coupling between them and the front controller is a bad idea. Similar to decorators, we would like to separate the specialized bits of the code for actions and navigation into their own classes and leave the major objects—like the front controller—to act as frameworks.

Here's an example. Imagine a simple, multistep form, such as an online mortgage application.[3] If each page in the form contained embedded references to the next page, it would be very difficult to change the page order. Each affected page, as well as those that came before and after it, would need to be modified to reflect the change. Even worse, these pages could not be reused. If the first page of our mortgage application took basic name and address information, we might want to use the same view in a credit card application. Unfortunately, we can't, since the first mortgage page contains a reference to the second mortgage page: there's no way to direct it to the credit card application instead. This inflexibility stems from the tight coupling of views to controllers.
 
Yes, we know that in reality these are anything but simple!

To build a flexible application, we need to decouple the pages and controllers. We need the flexibility to add, remove, and reorder pages, reusing them at will. Ideally, we want to do all of this at runtime, while preserving the view-controller separation. The Service to Worker pattern can help us.

4.2.1 The Service to Worker Pattern

The Service to Worker pattern is based on both the Model-View-Controller pattern and the Front Controller pattern. The goal of Service to Worker is to maintain separation between actions, views, and controllers. The service, in this case is the front controller, a central point for handling requests. Like in the Front Controller pattern, the service delegates updating the model to a page-specific action called the worker. So far, Service to Worker is the same as the Front Controller pattern.

In the Service to Worker pattern, an object called the dispatcher performs the task of managing workers and views. The dispatcher encapsulates page selection, and consequently, worker selection. It decouples the behavior of the application from the front controller. To change the order in which pages are shown, for example, only the dispatcher needs to be modified.

The Service to Worker pattern is shown in Figure 4-1. It looks like the Front Controller pattern, with the addition of the dispatcher.
 
Figure 4-1. The Service to Worker pattern

The controller provides an initial point of entry for every request (just like in the Front Controller pattern). It allows common functionality to be added and removed easily, and it can be enhanced using decorators.

The dispatcher encapsulates page selection. In its simplest form, the dispatcher takes some parameters from the request and uses them to select actions and a view. This type of simple dispatcher may be implemented as a method of the front controller. In addition to the requested page, the dispatcher often takes several other factors into account when choosing the next view, the current page, the user permissions, and the validity of the entered information. This type of dispatcher is implemented as a separate class, and ideally, it is configurable via a file at runtime.

The dispatcher uses a set of actions to perform model updates. Each action encapsulates a single, specific update to the model, and only that update. An action might be something as simple as adding a row to a database table, or as complex as coordinating transactions across multiple business objects. Because all navigation is encapsulated in the dispatcher, the actions are not responsible for view selection. As in the Front Controller pattern, actions are usually implemented as an instance of the GoF Command pattern.

The end result of the Service to Worker pattern is an extensible front controller. The controller itself is simply a framework: decorators perform common functions, actions actually update the model, and the dispatcher chooses the resulting view. Because these pieces are loosely coupled, each can operate independently, allowing extension and reuse.

4.2.2 Service to Worker in J2EE

As an example of Service to Worker, let's think about a workflow.[4] A workflow is a sequence of tasks that must be performed in a specific order. Many environments have workflows, such as the mortgage application we discussed earlier and the "wizards" that guide a user through installing software.

This example is based loosely on a proposed workflow language for the Struts framework, part of the Apache project. More information is available from http://jakarta.apache.org/struts/proposal-workflow.html.
Our workflow is very simple, and it is based on our previous examples. It consists of three web pages: one asking the user to log in, another setting a language preference, and a third displaying a summary page. This workflow is shown in Figure 4-2.
 
Figure 4-2. A simple workflow

While it would be easy enough to build this workflow based on the Front Controller pattern, we would like the result to be extensible. We want to be able to add pages and actions without changing the front controller. Ideally, we would like to specify our workflow in XML, so we could change the order of pages without even modifying the dispatcher. Our XML might look like:
<?xml version="1.0" encoding="UTF-8"?>
<workflow>
    <state name="login" action="LoginAction" 
           viewURI="login.jsp" />
    <state name="language" action="LanguageAction" 
           viewURI="language.html" />
    <state name="display" action="RestartAction" 
           viewURI="display.jsp" />
</workflow>
The dispatcher, then, is a simple state machine. When a request is submitted, the dispatcher determines the current state of the session and runs the corresponding action. If the action succeeds, there is a transition to the next state. Once the state is determined, control is forwarded to the associated view.
The interactions in a J2EE Service to Worker implementation are shown in Figure 4-3. To explain all these pieces, we'll work backward, starting with models and views and ending with the front controller.
 
Figure 4-3. J2EE Service to Worker implementation
4.2.2.1 Models and views

The models and views in the Service to Worker pattern remain more or less unchanged from the MVC and Front Controller patterns. As in Chapter 3, our model is the UserBean. The interface has been extended slightly from earlier examples to include a "language" attribute:
package s2wexample.model;
 
public interface UserBean {
    // the username field
    public String getUsername( );
    public void setUsername(String username);
  
    // the password field
    public String getPassword( );
    public void setPassword(String password);
    
    // the language field
    public String getLanguage( );
    public void setLanguage(String language);
    
    // business methods to perform login
    public boolean doLogin( );
    public boolean isLoggedIn( );
}
The views are simple JSP pages that read the model data from our UserBean. Our login page is virtually unchanged from the earlier example. Example 4-1 shows the login page.
Example 4-1. login.jsp
<%@page contentType="text/html"%>
<jsp:useBean id="userbean" scope="session" 
             class="s2wexample.model.UserBean" />
<html>
<head><title>Login</title></head>
 <body>
 <br><br>
 <form action="/pages/workflow" method="post">
   Username:<input type="text" name="username"
   value=<jsp:getProperty name="userbean" property="username"/>>
   <br>
   Password: <input type="password" name="password">
   <br>
   <input type="submit" value="Log In">
 </form>
 </body>
</html>
The only thing to notice here is that our form action is now /pages/workflow. This will be the target of all our links, such as those in the second page, language.html. Since this page does not require any dynamic data, it is stored as a plain HTML file, shown in Example 4-2.
Example 4-2. language.html
<html>
<head><title>Language Selection</title></head>
 <body>
 <br><br>
 <form action="/pages/workflow" method="get">
   Language: <select name="language">
              <option value="En">English</option>
              <option value="Fr">French</option>
             </select>
   <br>
   <input type="submit" value="Continue">
 </form>
 </body>
</html>
4.2.2.2 Actions

Actions, as we mentioned earlier, are implemented as instances of the command pattern. All of our actions will share a simple interface:
public interface Action {
    public boolean performAction(HttpServletRequest req,
                                 ServletContext context);
}
This interface gives each action full access to the request, as well as the servlet context, which includes the HTTP session. Each action reads a different set of parameters from the request. The action then updates the model data, which is accessible through either the request or the session. If the performAction( ) method returns true, the dispatcher knows to move on to the next state. If not, the same state is repeated.
Example 4-3 shows the LoginAction, which is called with input from the login page. This action is also responsible for creating the initial UserBean if it does not exist.
Example 4-3. LoginAction.java
package s2wexample.controller.actions;
 
import s2wexample.controller.*;
import s2wexample.model.*;
import javax.servlet.http.*;
import javax.servlet.*;
 
public class LoginAction implements Action {
    public static final String USERBEAN_ATTR = "userbean";
    private static final String NAME_PARAM = "username";
    private static final String PASSWORD_PARAM = "password";
    
    public boolean performAction(HttpServletRequest req, 
                                 ServletContext context) {
        // read request parameters
        String username = req.getParameter(NAME_PARAM);
        String password = req.getParameter(PASSWORD_PARAM);
 
        // find the UserBean, create if necessary
        HttpSession session = req.getSession( );
        UserBean ub = (UserBean)session.getAttribute(USERBEAN_ATTR);
        if (ub == null) {
            ub = UserBeanFactory.newInstance( );
            session.setAttribute(USERBEAN_ATTR, ub); 
        }
        
        // try to login, return the result
        ub.setUsername(username);
        ub.setPassword(password);
        return ub.doLogin( );
    } 
}
4.2.2.3 The dispatcher

Dispatchers, like actions, come in many flavors. There may be a single master dispatcher or different dispatchers for different parts of an application. Usually, there is one default dispatcher and a few more specialized ones to handle special cases like wizards. In any case, we will define a simple Dispatcher interface to allow uniform access to all the possible dispatchers:
public interface Dispatcher {
    // called after initialization
    public void setContext(ServletContext context)
        throws IOException;
    // called for each request
    public String getNextPage(HttpServletRequest req,
                              ServletContext context);
}
The dispatcher must build and store a simple state machine for each user. As requests come in, the dispatcher retrieves the current state and uses it to determine the correct action to run. If the action succeeds, it displays the view associated with the next state.

Our dispatcher must also process the XML state data. When we see an action attribute, we will convert it to a Java class by loading the class named nameAction, where name is the value of the action attribute.
Internally, we will use simple Java objects to model the states of the workflow. The WorkflowDispatcher is shown in Example 4-4.
Example 4-4. WorkflowDispatcher
 package s2wexample.controller;
 
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
 
public class WorkflowDispatcher implements Dispatcher {
    // tags expected in the XML
    private static final String WORKFLOW_TAG = "workflow";
    private static final String STATE_TAG = "state";
    private static final String NAME_ATTR = "name";
    private static final String ACTION_ATTR = "action";
    private static final String VIEW_ATTR = "viewURI";
    
    // where to find action classes
    private static final String ACTION_PREFIX = 
        "s2wexample.controller.actions.";
    
    // the internal model of a workflow state
    class State {
        protected String name;
        protected Action action;
        protected String viewUri;
    }
    
    // the current state and state list
    private State[] states;
    private int currentState;
    
    // called by the controller after initialization
    public void setContext(ServletContext context)
        throws IOException {
        InputStream is = 
            context.getResourceAsStream("/LanguageWorkflow.xml");
        try {
            states = parseXML(is);
        } catch(Exception ex) {
            throw new IOException(ex.getMessage( ));
        }
        currentState = 0;
    }
    
    // choose the next state
    public String getNextPage(HttpServletRequest req,
                              ServletContext context) {
        State s = states[currentState];
        // increment the state only if the action suceeds
        if ((s.action == null) || 
            s.action.performAction(req, context)) {
            if (currentState < states.length - 1) {
                s = states[++currentState];
            } else {
                currentState = 0;
                s = states[currentState];
            }
        }
        
        return s.viewUri;
    }
    
    // parse a state XML file
    private State[] parseXML(InputStream is) throws Exception {
        DocumentBuilderFactory factory = 
            DocumentBuilderFactory.newInstance( );
        DocumentBuilder builder = factory.newDocumentBuilder( );
        Document doc = builder.parse(is);
        
        // find the workflow element
        NodeList workflows = doc.getElementsByTagName(WORKFLOW_TAG);
        Element workflow = (Element)workflows.item(0);
        
        // find all the states
        NodeList states = doc.getElementsByTagName(STATE_TAG);
        State[] stateList = new State[states.getLength( )];
        
        // read state information
        for(int i = 0; i < states.getLength( ); i++) {
            stateList[i] = new State( );
            
            Element curState = (Element)states.item(i);
            stateList[i].name = curState.getAttribute(NAME_ATTR);
            stateList[i].viewUri = curState.getAttribute(VIEW_ATTR);
            
            // convert actions names into class instances
            String action = curState.getAttribute(ACTION_ATTR);
            if (action != null && action.length( ) > 0) {
                Class c = Class.forName(ACTION_PREFIX + action);
                stateList[i].action = (Action)c.newInstance( );
            }
        }
        
        return stateList;
    }
}
4.2.2.4 The front controller

Last but not least is the front controller, which is more of a framework than a container for actual application logic at this point. The controller's job right now is to manage dispatchers, using them to choose the next view. Once the view is chosen, the front controller passes control to the view, and the front controller's job is finished. Example 4-5 shows our front controller servlet.
Example 4-5. FrontController.java
package s2wexample.controller;
 
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import s2wexample.model.*;
 
public class FrontController extends HttpServlet {
    private static final String DISPATCHER_ATTR = "Dispatcher";
    private static final String DISPATCHER_PREFIX =
        "s2wexample.controller.";
    
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }
    
    // process get requests
    public void doGet(HttpServletRequest request,        
                      HttpServletResponse response)
    throws ServletException, IOException {
        process(request, response);
    }
    
    // process post requests
    public void doPost(HttpServletRequest request, 
                       HttpServletResponse response)
    throws ServletException, IOException {
        process(request, response);
    }
    
    // common processing routine
    public void process(HttpServletRequest request, 
                        HttpServletResponse response)
    throws ServletException, IOException {
        HttpSession session = request.getSession( );
        ServletContext context = getServletContext( );
        
        // get the last element of the request in lower case
        String reqPath = request.getPathInfo( );
        reqPath = Character.toUpperCase(reqPath.charAt(1)) +
            reqPath.substring(2).toLowerCase( );
        
        // find the dispatcher in the session
        Dispatcher dispatcher =
            (Dispatcher)session.getAttribute(reqPath + 
                                             DISPATCHER_ATTR);
        // if no dispatcher was found, create one
        if (dispatcher == null) {
            String className = reqPath + "Dispatcher";
            try {
                Class c = Class.forName(DISPATCHER_PREFIX + 
                                        className);
                dispatcher = (Dispatcher)c.newInstance( );
            } catch(Exception ex) {
                throw new ServletException("Can't find class " + 
                                           className, ex); 
            }
            
            // store the dispatcher in the session
            dispatcher.setContext(context);
            session.setAttribute(reqPath + DISPATCHER_ATTR, 
                                 dispatcher);
        }
        
        // use the dispatcher to find the next page
        String nextPage = dispatcher.getNextPage(request, context);
 
        // make sure we don't cache dynamic data
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        
        // forward control to the view
        RequestDispatcher forwarder = 
            request.getRequestDispatcher("/" + nextPage);
        forwarder.forward(request, response);
    }
}
Notice that the front controller manages dispatchers in the same way that the dispatchers manage actions. Dispatchers are mapped based on the requested URL. Since all our views used the path /pages/workflow in their requests, the front controller maps these requests to an instance of the WorkflowDispatcher class. As a result, the same application could use many different dispatchers for different parts of the web site. In practice, the mapping between URLs and dispatchers is usually done with an XML file, just like for actions.

Using the Service to Worker pattern, the controller has been divided up into a set of reusable components: a front controller, dispatchers, and actions. Adding a new page is dynamic: you simply create the view JSP and corresponding action class and add it all to an XML file. To add, remove, or reorder pages, we only need to change the XML.

The Service to Worker pattern, as we have presented it, is quite flexible. The simple navigation model of our example, however, is only really appropriate for workflows. Even branches to the linear flow of pages are not covered. We won't cover all the possible dispatchers and actions here. Both the Jakarta Struts project and Sun's J2EE sample applications contain more advanced implementations of the Service to Worker patterns, and they are a good place to look for more information.

4.3 Advanced Views

Until now, we have treated the view as a black box, assuming that a single JSP page will convert our model data into HTML to send to the user. In reality, this is a tall order. Large JSP pages with lots of embedded code are just as unwieldy as a large front controller. Like the controller, we would like to break the view into a generic framework with the specialized pieces separated out.

The challenge is to break up the view within the restricted programming model of JSP. Remember that one of our goals was to minimize embedding code in our JSP pages, since it blurs the line between the view and the controller. Thus, we will avoid the kinds of classes and interfaces we used to solve the same problem in the controller.

Fortunately, JSP gives us a different set of tools to work with: JSP directives and custom tags. We will use both of these extensively in the next two patterns to help separate the view into reusable components.

4.3.1 The View Helper Pattern

One mechanism for reducing specialization in views is a view helper. A view helper acts as an intermediary between the model and the view. It reads specific business data and translates it, sometimes directly into HTML, and sometimes into an intermediate data model. Instead of the view containing specialized code to deal with a particular model, the view includes more generic calls to the helper. Figure 4-4 shows how a view uses helpers.
Figure 4-4. A view using helpers
 
View helpers increase reusability in two ways: by reducing the amount of specialized code in a view, helpers make views more reusable; and, since a helper encapsulates a specific kind of interaction with the model, helpers can be reused themselves.

4.3.2 Implementing a View Helper

When you think about view helpers in JSP, custom tags should immediately pop to mind. Conceptually, custom tags fit the bill—they adapt Java objects into JSP markup. Moving code embedded in JSP into custom tag classes reduces coupling, since the tag defines a clear interface independent of the underlying objects. And since tags are grouped into libraries by function, they are inherently quite reusable themselves. While it is easy to think of all custom tags (or even all tags) as view helpers, they are not the same thing. A view helper is a tag, or set of tags, that translates model data into a convenient form for the view.

A view helper may read business data in many forms, including JavaBeans, Enterprise JavaBeans, direct database access, or access to remote web services. For our example, let's look at the last of these: accessing a remote web service.
Really Simple Syndication (RSS)[5] is an XML format that is the de facto standard for web sites to exchange headline information. RSS files are generally available via public HTTP from most news sites, at the very least. Example 4-6 shows a slightly simplified RSS file for a made-up news page, PatternsNews. (For simplicity, we have stuck to the 0.91 version of RSS. The current version, 2.0, is far more complicated.)

RSS is an actively evolving standard. For a good introduction and history, see http://backend.userland.com/rss.
Example 4-6. PatternsNews.xml
<?xml version="1.0" encoding="iso-8859-1"?>
 
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" 
                     "http://www.scripting.com/dtd/rss-0_91.dtd">
 
<rss version="0.91">
 <channel>
    <title>Patterns news</title>
    <link>http://www.patternsnews.com</link>
  
    <item>
      <title>Local pattern-creators honored</title>
      <link>http://www.patternsnews.com/stories?id=0001</link> 
    </item>
    <item>
      <title>Patterns solve business problem</title>
      <link>http://www.patternsnews.com/stories?id=0002</link>
    </item>
    <item>
      <title>New patterns discovered!</title>
      <link>http://www.patternsnews.com/stories?id=0003</link>
    </item>
 </channel>
</rss>
We would like to read RSS files and include their headlines on our own web site. In order to do this, we will build a view helper that makes the RSS data available as a JSP custom tag. Figure 4-5 shows the pieces we will build.
 
Figure 4-5. A view helper for parsing RSS
4.3.2.1 Parsing the RSS

For starters, we need to parse the RSS into a Java format that we can use. To do this, we create an RSSInfo class that parses RSS files and stores them as Java objects. We won't go into the specifics of how the parsing works, since the innards look a lot like the DOM-based XML parser we built for the last example. Example 4-7 shows the interface to the RSSInfo class.
Example 4-7. The RSSInfo interface
public interface RSSInfo {
 
    // channel information
    public String getChannelTitle( ); 
    public String getChannelLink( );
 
    // item information
    public String getTitleAt(int index);
    public String getLinkAt(int index); 
    public int getItemCount( );
    
    // parse the RSS file at the given URL
    public void parse(String url) throws Exception;
}
The RSSInfo object represents an intermediate data structure: it is not exactly the underlying data, but also not exactly what we are using in the application. Building an intermediate data model may seem inefficient, but it can help significantly in reusability. Since the RSSInfo class is independent of any type of display mechanism, it can be used in many contexts: JSP custom tags, servlets, web services, etc. If the parsing was implemented directly as custom JSP tags, the logic would have to be duplicated.
4.3.2.2 Using the RSS: Custom tags

Now that we have a generic method for parsing RSS, we would like to use it in a JSP environment. We could store the RSSInfo object in the session and access it directly using JSP directives. While this option is quite flexible, it embeds a fair amount of logic for iteration and such in the JSP.[6] This logic would have to be rewritten for each page that used the RSS parser. As another option, we could create a custom tag that read the RSS and returned a preformatted table. This method has the advantage of being easy, since only one line of JSP is needed to include all the headlines. Unfortunately, it would mean including our page styles in the custom tag, and we would be unable to reuse the tag on a different page.

Version 2.0 of the JSP spec adds an expression language and standard tag library, which greatly reduce the need for embedded scripts in these situations. This does not, however, provide an excuse for manipulating ill-suited business objects directly in JSP.

The best solution in this case is a hybrid: we will design custom tags to parse and iterate through the RSS data, and expose JSP scripting variables with the relevant values. This solution allows us the flexibility to format the output any way we want, while performing the heavy lifting in the custom tag logic. To format the RSS data as a table, for example, we would like to have our JSP look something like Example 4-8.
Example 4-8. JSP custom tags in action
<%@page contentType="text/html"%>
<%@ taglib prefix="rss" uri="/ReadRSS" %>
<html>
<head><title>RSS Results</title></head>
<body>
<rss:RSSChannel URL="http://www.patternsnews.com/patternsnews.xml">
 <b><a href="/<%= channelLink %>"><%= channelName %></a></b>
 <br>
 <table>
  <rss:RSSItems>
   <tr><td><a href="/<%= itemLink %>"><%= itemName %></a></td></tr> 
  </rss:RSSItems>
 </table>
</rss:RSSChannel>
</body>
</html>
Here, our view helper consists of two custom tags. The first, RSSChannel, takes a URL corresponding to an RSS file and downloads and parses that file using the RSSInfo class. It exposes the channel title and channel link information in two scripting variables: channelTitle and channelLink. The second tag, RSSItems, performs a similar task, repeating its body for each item in turn and exposing the itemTitle and itemLink variables. The helper (the tags) is therefore responsible for creating and interpreting the intermediate data model (the RSSInfo).
The RSSChannel tag source is shown in Example 4-9.
Example 4-9. RSSChannelTag.java
import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
 
public class RSSChannelTag extends BodyTagSupport {
    // scripting variable names
    private static final String NAME_ATTR = "channelName";
    private static final String LINK_ATTR = "channelLink";
    
    // the input parameter
    private String url;
    // the RSS parser
    private RSSInfo rssInfo;
    
    public RSSChannelTag( ) {
        rssInfo = new RSSInfoImpl( );
    }
    
    // called with the URL parameter from the tag
    public void setURL(String url) {
        this.url = url;
    }
    
    // used by the RSSItemsTag
    protected RSSInfo getRSSInfo( ) {
        return rssInfo;
    }
    
    // parse the RSS and set up the scripting variables
    public int doStartTag( ) throws JspException {
        try {
            rssInfo.parse(url);
 
            pageContext.setAttribute(NAME_ATTR, rssInfo.getChannelTitle( ));
            pageContext.setAttribute(LINK_ATTR, rssInfo.getChannelLink( ));
        } catch (Exception ex) {
            throw new JspException("Unable to parse " + url, ex);
        }
        return Tag.EVAL_BODY_INCLUDE;
    }
}
The RSSItems tag is slightly more complicated, since it implements the IterationTag interface. It loops through the item data, setting the itemTitle and itemLink variables with every pass. RSSItems also uses the findAncestorWithClass( ) method to locate the RSSInfo object that was stored by the parent. The RSSItemsTag source is shown i