A Generic Superclass for Sorting and Paginating in the database with Richfaces

In my previous post, I presented a solution for sorting and paginating in the database with Richfaces, and that post should be read prior to this one.  However, an examination of the previous solution shows that the only things that are specific to the items being presented are the Id of the item, the item itself, and the DAO used to perform the actual queries.  If we put all the parts of the code that deal with these three items into separate methods, and then override those methods in the subclasses, we can avoid duplicating code.  In contrast to my previous post, I will post all the code of the superclass up front, and then discuss it.  Generics are used so that the superclass can be provided with the types of the items and the id.

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.context.FacesContext;

import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.model.Range;
import org.ajax4jsf.model.SequenceRange;
import org.ajax4jsf.model.SerializableDataModel;

/**
 * @param 
 * @param <U>
 */
public abstract class PaginatingDataModel extends SerializableDataModel {
    /** */
    private static final long serialVersionUID = 2954923950179861809L;
    /** */
    protected U currentPk;
    /** */
    protected boolean descending = true;
    /** */
    protected String sortField = getDefaultSortField();
    /** */
    protected boolean detached = false;
    /** */
    protected List<U> wrappedKeys = new ArrayList<U>();
    /** */
    protected Integer rowCount;
    /** */
    protected Map<U> wrappedData = new HashMap<U>();

    /**
     * @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
     */
    @Override
    public Object getRowKey()
    {
        return currentPk;
    }

    /**
     * @see org.ajax4jsf.model.ExtendedDataModel#setRowKey(java.lang.Object)
     */
    @SuppressWarnings("unchecked")
    @Override
    public void setRowKey(final Object key)
    {
        this.currentPk = (U) key;
    }

    /**
     * @see org.ajax4jsf.model.SerializableDataModel#update()
     */
    @Override
    public void update()
    {
        if (getSortFieldObject() != null)
        {
            final String newSortField = getSortFieldObject().toString();
            if (newSortField.equals(sortField))
            {
                descending = !descending;
            }
            sortField = newSortField;
        }
        detached = false;
    }

    /**
     * @return Object
     */
    protected Object getSortFieldObject()
    {
        final FacesContext context = FacesContext.getCurrentInstance();
        final Object sortFieldObject = context.getExternalContext().getRequestParameterMap().get("sortField");
        return sortFieldObject;
    }

    /**
     * @param sortField
     */
    public void setSortField(final String sortField)
    {
        if (this.sortField.equals(sortField))
        {
            descending = !descending;
        } else
        {
            this.sortField = sortField;
        }
    }

    /**
     * @return String
     */
    public String getSortField()
    {
        return sortField;
    }

    /**
     * @see org.ajax4jsf.model.ExtendedDataModel#getSerializableModel(org.ajax4jsf.model.Range)
     */
    @Override
    public SerializableDataModel getSerializableModel(final Range range)
    {
        if (wrappedKeys != null)
        {
            detached = true;
            return this;
        }
        return null;
    }

    /**
     * @see javax.faces.model.DataModel#setRowIndex(int)
     */
    @Override
    public void setRowIndex(final int rowIndex)
    {
        throw new UnsupportedOperationException();

    }

    /**
     * @see javax.faces.model.DataModel#setWrappedData(java.lang.Object)
     */
    @Override
    public void setWrappedData(final Object data)
    {
        throw new UnsupportedOperationException();

    }

    /**
     * @see javax.faces.model.DataModel#getRowIndex()
     */
    @Override
    public int getRowIndex()
    {
        throw new UnsupportedOperationException();
    }

    /**
     * @see javax.faces.model.DataModel#getWrappedData()
     */
    @Override
    public Object getWrappedData()
    {
        throw new UnsupportedOperationException();
    }

    /**
     * @see org.ajax4jsf.model.ExtendedDataModel#walk(javax.faces.context.FacesContext,
     *      org.ajax4jsf.model.DataVisitor, org.ajax4jsf.model.Range,
     *      java.lang.Object)
     */
    @Override
    public void walk(final FacesContext context, final DataVisitor visitor, final Range range, final Object argument)
            throws IOException
    {
        final int firstRow = ((SequenceRange) range).getFirstRow();
        final int numberOfRows = ((SequenceRange) range).getRows();
        if (detached &amp;amp;&amp;amp; getSortFieldObject() != null)
        {
            for (final U key : wrappedKeys)
            {
                setRowKey(key);
                visitor.process(context, key, argument);
            }
        } else
        { // if not serialized, than we request data from data
            // provider
            wrappedKeys = new ArrayList<U>();
            for (final T object : findObjects(firstRow, numberOfRows, sortField, descending))
            {
                wrappedKeys.add(getId(object));
                wrappedData.put(getId(object), object);
                visitor.process(context, getId(object), argument);
            }
        }
    }

    /**
     * @see javax.faces.model.DataModel#isRowAvailable()
     */
    @Override
    public boolean isRowAvailable()
    {
        if (currentPk == null)
        {
            return false;
        }
        if (wrappedKeys.contains(currentPk))
        {
            return true;
        }
        if (wrappedData.entrySet().contains(currentPk))
        {
            return true;
        }
        try
        {
            if (getObjectById(currentPk) != null)
            {
                return true;
            }
        } catch (final Exception e)
        {

        }
        return false;
    }

    /**
     * @see javax.faces.model.DataModel#getRowData()
     */
    @Override
    public Object getRowData()
    {
        if (currentPk == null)
        {
            return null;
        }

        T object = wrappedData.get(currentPk);
        if (object == null)
        {
            object = getObjectById(currentPk);
            wrappedData.put(currentPk, object);
        }
        return object;
    }

    /**
     * @see javax.faces.model.DataModel#getRowCount()
     */
    @Override
    public int getRowCount()
    {
        if (rowCount == null)
        {
            rowCount = getNumRecords();
        }
        return rowCount;
    }

    /**
     * 
     * @param object
     * @return U
     */
    public abstract U getId(T object);

    /**
     * @param firstRow
     * @param numberOfRows
     * @param sortField
     * @param descending
     * @return List
     */
    public abstract List findObjects(int firstRow, int numberOfRows, String sortField, boolean descending);

    /**
     * @param id
     * @return T
     */
    public abstract T getObjectById(U id);

    /**
     * @return String
     */
    public abstract String getDefaultSortField();

    /**
     * @return int
     */
    public abstract int getNumRecords();
}


The abstract methods are all at the end.  Here is one possible subclass.  Note that it is Session scoped:


import static org.jboss.seam.ScopeType.SESSION;

import java.util.List;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.log.Log;

import PaginatingDataModel;
import IFormsService;
import EntityDTO;
import FolderDTO;

@Name("newhireDataModel")
@Scope(SESSION)
public class NewhireList
    extends PaginatingDataModel
{
    /** */
    private static final long serialVersionUID = 2672142810059859813L;
    
    /** */
    @In
    private IFormsService serviceForms;
    
    /** */
    @In
    EntityDTO currentEntity;
    
    /** */
    @Logger
    Log log;
    
    /**
     * @see PaginatingDataModel#getId(java.lang.Object)
     */
    @Override
    public Integer getId(FolderDTO object)
    {
        return object.getPk();
    }
    
    /**
     * @see PaginatingDataModel#findObjects(int, int, java.lang.String, boolean)
     */
    @Override
    public List findObjects(int firstRow, int numberOfRows, String sortField, boolean descending)
    {
        return serviceForms.findFolders(firstRow, numberOfRows, sortField, descending);
    }
    
    /**
     * @see PaginatingDataModel#getObjectById(java.lang.Object)
     */
    @Override
    public FolderDTO getObjectById(Integer id)
    {
        return serviceForms.getFolder(id);
    }
    
    /**
     * @see PaginatingDataModel#getDefaultSortField()
     */
    @Override
    public String getDefaultSortField()
    {
        return "attribute(EOD)";
    }
    
    /**
     * @see PaginatingDataModel#getNumRecords()
     */
    @Override
    public int getNumRecords()
    {
        return serviceForms.countFolders(null, currentEntity);
    }
    
}

No change needs to be done to the JSF layer when using this solution.

Sorting and paginating in the database with Richfaces

Richfaces is designed to easily add ajax capabilities to a Java Server Faces (JSF) application, without the developer having to write any javascript.  All Richfaces components are skinnable, and when a given skin is applied, all the components on a given website have the same look and feel.

Unfortunately, out of the box, Richfaces does not provide a way to sort and paginate results using the database–all results must be passed to Richfaces, which then sorts and paginates in memory.  This might prove to be showstopper if you have a large result set.

When a Richfaces component does not do what you need by default, you have several options.

  1. Use another component library to provide the missing component
  2. Use simple Richfaces components, such as Rich Panel, to provide a canvas that has the Richfaces look and feel, and then on that canvas, use regular (non-ajax) links.
  3. Extend the capability of one or more Richfaces components to provide the functionality you need.

The Seam example “Seamdiscs” takes the first approach.  It uses a Trinidad table component that natively supports paging and sorting via the database, and places this component in the middle of a site that uses Richfaces for the remainder of the components.  Of note, if you run the seamdiscs example, links at the bottom of the main page describe exactly what changes you need to make to your application to get both Trinidad and Richfaces working together smoothly.  Here is picture of what this approach looks like:

Richfaces and Trinidad components together

As you can see, the Trinidad table doesn’t quite match the look and feel of the rest of the site. Consequently, you may want to examine one of the other approaches. What I will explain here is the third approach.  The Richfaces documentation states that if you want to roll your own data model, to support such features as sorting and paginating in the database, or perhaps to pull from a non-standard data source, you should extend the org.ajax4jf.model.ExtendedDataModel.  Further, the documentation suggests inheriting in particular from the SerializableDataModel, which itself inherits from ExtendedDataModel.  The first time you create a concrete class that inherits from SerializableDataModel, you may be overwhelmed at the number of abstract methods that you have to implement.  But, don’t worry–those methods will all be explained here.

public Object getRowKey() and public void setRowKey(Object key)

These methods should just get and set an instance variable that is Serializable, and which you can use to look up an individual object that will populate a row in your table.  In my case, each row of my table will correspond to a Folder object, and I look up Folder objects in the database via a pk that is an Integer, so my instance variable is an Integer:

private Integer currentPk;
@Override
public Object getRowKey()
{
    return currentPk;
}

@Override
public void setRowKey(Object key)
{
    this.currentPk = (Integer) key;
}

The most important method is the walk method.  This method will be called by Richfaces, and will give you an opportunity to pull from the database just those records that will be shown to the user.  However, it is important to note that this method can potentially be called many times during one request, and we only want to make one call to the database.  So, we want to cache the results, but we also don’t want to cache them too aggressively, for if a person requests a different page of results, or changes the sort order, then we want to fetch new results.  So, two other methods that you must override, public void update() and public SerializableDataModel getSerializableModel(Range range) come into play as well.  Here is the code, discussion follows:


private boolean detached = false;
private List wrappedKeys = null;
private final Map wrappedData = new HashMap();
private String sortField = "lastname";
@In
private IFormsService serviceForms;

@Override
public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException
{
    if (detached &amp;&amp; getSortFieldObject() != null)
    {
        for (Integer key : wrappedKeys)
        {
            setRowKey(key);
            visitor.process(context, key, argument);
        }
    } else
    {
        int firstRow = ((SequenceRange) range).getFirstRow();
        int numberOfRows = ((SequenceRange) range).getRows();
        wrappedKeys = new ArrayList();
        for (FolderDTO folder : serviceForms.findFolders(firstRow, numberOfRows, sortField, descending)
        {
            wrappedKeys.add(folder.getPk());
            wrappedData.put(folder.getPk(), folder);
            visitor.process(context, folder.getPk(), argument);
        }
    }
}

@Override
public SerializableDataModel getSerializableModel(Range range)
{
    if (wrappedKeys != null)
    {
        detached = true;
        return this;
    }
    return null;
}


@Override
public void update()
{
    if (getSortFieldObject() != null)
    {
        String newSortField = getSortFieldObject().toString();
        if (newSortField.equals(sortField))
        {
            descending = !descending;
        }
        sortField = newSortField;
    }
    detached = false;
}

We have two checks to see if we should return cached data, or if we should fetch new data.  The first boolean, detached, starts as false.  It will be set to “true” when SerializableDataModel getSerializableModel(Range range) is called, and back to false when public void update() is called.  In this manner, the model will not be updated when the jsf component is rebuilt on postback, but rather when the new model is being built.  The other check, for getSortFieldObject, is in place for the following reason:  When it is not the table itself which has an action taken on it, but rather something outside the table (such as a DataScroller), the update method will not be called.  Since we will be passing our own parameter (the sort field) whenever a column header is clicked on, we know that getSortFieldObject() will be null if it is something outside the table that is clicked.  Here is the getSortFieldObject() method:


private Object getSortFieldObject()
{
    FacesContext context = FacesContext.getCurrentInstance();
    Object sortFieldObject =  context.getExternalContext().getRequestParameterMap().get("sortField");
    return sortFieldObject;
}

Continuing with methods we must override:  public int getRowCount():

private Integer rowCount;
@Override
public int getRowCount()
{
    if (rowCount == null)
    {
        rowCount = serviceForms.countFolders();
    }
    return rowCount;
}

Here, we are just returning the total number of folders.

The next method is public Object getRowData():

@Override
public Object getRowData()
{
    if (currentPk == null)
    {
        return null;
    } else
    {
        FolderDTO folder = wrappedData.get(currentPk);
        if (folder == null)
        {
            folder = serviceForms.getFolder(currentPk);
            wrappedData.put(currentPk, folder);
        }
        return folder;
    }
}

This method uses the currentPk, which is passed in via the setRowKey method, to look up an object.  Since the walk method will have been called first, all objects should be in wrappedKeys.  The lookup via the dao is primarily a failsafe.

public boolean isRowAvailable().

@Override
public boolean isRowAvailable()
{
    if (currentPk == null)
    {
        return false;
    }
    if (wrappedKeys.contains(currentPk))
    {
        return true;


    }
    if (wrappedData.entrySet().contains(currentPk))
    {
        return true;
    }
    {
    if (serviceForms.getFolder(currentPk) != null)
    {
        return true;
    }
    return false;
}

This method just does what its name suggests..it returns if a given pk (set via the setRowKey method) actually corresponds to an object.

public void setRowIndex(int rowIndex), public void setWrappedData(Object data), and public Object getWrappedData() are all unused, so you can simply throw an UnsupportedOperationException():

@Override
public int getRowIndex()
{
    throw new UnsupportedOperationException();
}

@Override
public Object getWrappedData()
{
    throw new UnsupportedOperationException();
}

@Override
public void setRowIndex(int rowIndex)
{
    throw new UnsupportedOperationException();
}

Now that you have implemented all the methods, there’s one more thing to note: this class should be either Session or Conversation scoped. Among other things, this ensures that the previous sort order will be preserved, so that we know if we should reverse it.

It’s time for the xhtml. We start with an ordinary Rich DataTable.  However, we add in an actionparam with each header.  This actionparam will be sent back to our table, and will let us know which header the person clicked on.  This information allows us to determine by what column we should sort the table.



    
        
            
                
            
        
        
    
    
        
            
                
            
        
        
        
    

To this, we add a datascroller, and we’re done:


Update: See the next post for instructions on abstracting the described class into a superclass and a subclass.

Struts, Acegi, and JBoss Portal

You can easily find documentation for running struts applications as a JSR 168 portlet–for example, here. In fact, the JBoss Portal itself now ships with the apache portals-bridges-common library, so all you need to do is ship your application with the appropriate implementation from apache (in my case, portals-bridges-struts-1.2.7-1.0), and you can simply follow the standard instructions for getting any struts application running as a JSR 168 portlet. Those instructions say that you need a container specific implementation of org.apache.portals.bridges.common.ServletContextProvider, and fortunately, JBoss Portal ships with one–specifically, org.jboss.portal.portlet.bridge.JBossServletContextProvider, which the struts bridge expects you to declare in portlet.xml.

You can also find documentation for running applications requiring Acegi on the JBoss Portal. In fact, Acegi ships with a JBoss adaptor. This adaptor is in two parts–one that provides a JBoss Portal Login Module, and one that provides a filter that is meant to be used in place of the httpSessionContextIntegrationFilter. The Login Module returns an instance of Authentication, which JBoss Portal then makes available to all portlets via JNDI…specifically, it places a JAAS Subject at java:comp/env/security/Subject, and one of the principals associated with that subject will be the Authentication instance returned from the Login Module. It also makes the Principal available from the portletRequest object…just call portletRequest.getUserPrincipal(). If you look at the code of the filter, you can see that all it does is get the Subject from the jndi location, and then iterate through all of the associated JAAS Principals, looking for a Principal that is an instance of Authentication. It then places this Authentication in the SecureContext. Note that if you don’t have Acegi handle the login on the portal side of things, you won’t actually get a Principal that is an instance of Authentication, but in theory you can write your own filter which gets the active principal, calls getName() on the principal, (which returns the login name) and then looks up an Authentication instance in your database that corresponds to the name.

However, if you try to combine these two concepts–the Struts Bridge, and the filter, you will find that it doesn’t actually work. The issue is that when the acegi filter is running inside the struts bridge, there won’t actually be a subject at java:comp/env/security/Subject. If you cast the ServletRequest in the filter to an HttpServletRequest, and then call getUserPrincipal(), you won’t find anything there either. Oddly enough, if you put a scriptlet on the page that you want to display to the user, you will find that you can now access the Subject in JNDI, but by then it’s too late…you want the Authentication object in the SecureContext before the Acegi intercepting filter is run, not when you are displaying the page.

The solution is as follows: subclass the included JBossServletContextProvider, and then override the HttpServletRequest getHttpServletRequest(GenericPortlet genericPortlet, PortletRequest portletRequest) method. You’ll still want to get the HttpServletRequest to return, by calling super, but while you’re in this method, you have access to the Subject via JNDI, or, if you want, the Principal via portletRequest.getUserPrincipal. Once you have the Authentication instance, you have a couple of possibilities: You can place it in the session, and it will be available to you in an Acegi filter, where you can place it into the SecureContext. Alternatively, you can place it directly into the SecureContext. Note that placing it into the request won’t help…it won’t be available to you in the request object in the Acegi filter. If you use this method, don’t forget to update portlet.xml and put in the name of your subclass instead of the included JBossServletContextProvider.

In the application I am working on, we use a slight variant–we don’t use the Acegi JBoss Login module, and so when we get the Principal, we just get the Portal login name. So, our logic looks something like this: Get the Principal. See if there is an Authentication instance already in the session with a name that matches the login name. If there is no authentication instance, or if the authentication instance name does not match the portal login name, then get an authentication instance corresponding to the login name out of the database. Once we have the Authentication, either from the database or the session, we place that in the SecureContext and in the session. We then don’t have a httpSessionContextIntegrationFilter configured for Acegi, but rather proceed directly to the intercepting filter.

Book Review: Core Security Patterns: Best Practices and Strategies for J2EE(TM), Web Services, and Identity Management

Authors: Christopher Steel, Ramesh Nagappan, Ray Lai

Publisher: Prentice Hall / Sun Microsystems Press

ISBN: 0131463071 (Click to buy from Amazon)

When the Gang of Four wrote Design Patterns, they could be reasonably assured that most readers would know the basics of object oriented programming, and so they could spend their time on best practices when using objects. Similarly, when the authors of Core J2EE patterns wrote their book, they were able to assume that readers knew the basics of server side java, such as Requests, Sessions, and EJBs. However, the authors of Core Security Patterns made a different choice. They chose, correctly in my view, to assume no prior security knowledge. Consequently, the authors start with an introduction to basic security principals, including such details as the various types of encryption algorithms (symmetric and asymmetric, and for symmetric, block and stream), giving examples of each. They then give examples of how the various types of encryption algorithms are used, and detail how common protocols such as SSL make use of the algorithms. They show common means of attack, and how various security principles can prevent such attacks.

Once these basics of security are laid out, the authors spend several chapters describe how the various java security packages come together to implement the security described in chapter 2. A quick perusal of the topics of these chapters explains why several chapters are necessary–as it turns out, there is quite a bit of security functionality already built into standard J2Se and J2EE. For example, in J2SE 5, there are tools for key generation and management, for looking up revoked certificates, and of course for encryption and decryption, among other things. JAAS is covered here as well. The authors then cover web services and identity management, and how various XML security standards, such as XML Signature, can be used in both cases, and describe the java tools to work with such standards.

Finally, the authors move to the patterns themselves, and here the book finally becomes more like the standard patterns book, giving examples of the different scenarious under which you would use patterns, and providing the pros and cons of each. Since many readers will have taken advantage of the previous sections to learn about all the security technologies in depth for the first time, the patterns then provide a welcome companion, describing the proper use of the various technologies. There is nothing unique about the pattern presentation here, as compared to the other more well know pattern books–patterns are described and the pros and cons of each are given in depth, and so this part of the book may not get as much use. Still, just for the first part of the book alone, this book is worth reading.

Book Reviews: SOA Using Java Web Services, and J2EE Web Services: XML SOAP WSDL UDDI WS-I JAX-RPC JAXR SAAJ JAXP

Author: Mark D. Hansen

Publisher: Prentice Hall

ISBN: 0130449687 (Click to buy from Amazon)

Author: Richard Monson-Haefel

Publisher: Addison-Wesley

ISBN: 0321146182 (Click to buy from Amazon)

Given the big change from JAX-RPC to JAX-WS during the move from JEE 1.4 to JEE 5, and the fact that the SOA book covers JAX-WS while the older J2EE book covers JAX-RPC, it might seem that you would only need the newer SOA book. That assumption would be wrong. These two books are, in fact, quite complementary. The J2EE book provides, as its name suggests, a background of all the web service technologies, starting even with a background on XML. It then looks in depth at SOAP and WSDL, breaking apart what can be a complex and intimidating subject in the way that the author, Richard Monsel-Haefel, became famous for in his earlier EJB and JMS books. It moves to UDDI, and the use of JAXR as a way of interfacing with UDDI, giving examples of how to interface with public test UDDI servers. A section on SAAJ follows, describing how you can manipulate the soap message using the SAAJ api. There is a section on JAX-RPC, but that section is well contained, and can be safely skipped, assuming that you will also be reading the SOA book. Overall, this is the sort of high quality, comprehensive book we have come to expect from this author.

The SOA book, whether intentional or not, is an almost perfect companion to the J2EE book. It covers in depth the parts of the Java web service stack that have changed since the J2EE book came out, while not touching at all upon other parts of the stack. It then covers how to use these technologies for SOA. For example, JAXR, UDDI, and SAAJ have not changed since the time the J2EE book was written, and this book covers them not at all, except for describing how one part of SAAJ can be used for fault handling in SOA. On the other hand, JAX-WS is entirely new, and uses JAX-B as the serialization engine, and the book spends quite a bit of time on JAX-WS and JAX-B in particular. Annotations are another difference between JAX-WS and JAX-RPC, and the book lays out all the annotations and their effects upon the generation of WSDL, which is essential to know.

In addition to bring to reader up to speed on the latest on the Java Web Service stack, the book also devotes time to using these tools for SOA. Here, the author does a good job of explaining the theoretical basis for Java Web Services, and the theoretical basis for SOA, and describes the areas in which those two concepts are sometimes not a perfect match. He then provides enough information for the reader to decide how best to overcome these differences when they become apparent–For example, in extreme situations, a mapper XML tool, such as castor, may be used in place of a binder XML tool such as JAXB. Because of the two strengths of this book, it is recommended even if you not doing SOA, but merely want information on the latest Java Web Service tools. If you are also planning to do SOA, then this book becomes a must read.

Book Review: Core J2EE Patterns, Second Edition

Authors: Deepak Alur, Dan Malks, John Crupi

Publisher: Prentice Hall / Sun Microsystems Press

ISBN: 0131422464 (Click to buy from Amazon)

With the advent of lightweight frameworks promoting dependency injection, and now JEE 5, with both dependency injection and pojo based EJBs, one might question the current practical applicability of a four year old book that describes patterns targeted at the JEE 1.4 platform. Indeed, some of the patterns in this book are outdated. However, the majority of the patterns are still applicable. This book review will go through each of the patterns, showing which of them are still relevant. If you decide that one or more of the still relevant patterns applies to the problems you are facing, then you would be well advised to purchase this book. The book divides its patterns into presentation tier, business tier, and integration tier, and I will use that same format.

Presentation patterns:

Intercepting Filter: This pattern is certainly still highly relevant. Indeed, this pattern is often how current frameworks add functionality. For example, in the Spring Framework, Acegi is used as the security manager. Acegi works as an intercepting filter, checking the incoming request to ensure that the user has permissions to access the target of the request.

Front Controller: The most well know front controller may be the one built into Struts. The struts controller takes protocol specific information, such as request parameters, and puts them into a more protocol independent object, such as a Form, and then delegates the rest of the processing to specific other classes. Such behavior is classic for a Front Controller, and can been seen in more modern frameworks as well. For example, in JSF, the request specific parameters are processed and directly applied in the Apply Request Values phase before the rest of the JSF lifecycle continues. If you are bypassing your framework for some set of requests, or not using a framework at all, then you should still write a Front Controller of your own.

Context Object: This is simply the protocol independent object created by the front controller holding the information received by the application, and meant to be passed to the rest of the application. It’s mostly hidden in current frameworks, which directly apply request values to your objects for you.

Application Controller: The most well known example here may be the Struts action subclasses that are written by programmers, but other frameworks also use application controllers. The idea here is to take the Context object, and then act on the information received. In more modern frameworks, this basic idea is still present, but without the context objects. For example, in JSF, a value change event may be used to act on information received from the user.

View Helper: This pattern is still used anytime a jsp or jsf tag is placed on a page, which is to say that is it highly relevant to today’s programmer. The view helper kicks in after the view is already in the process of being rendered, and helps to format or otherwise process the information in the business tier. The business tier may place objects in the session or request object, which are then processed and rendered by the view helper.

Composite View: This pattern is even more used today than when the book was first written, and consequently, frameworks have made this pattern easier and easier to use. In this pattern, a view is composed of multiple smaller views. For example, you may want to include a navigation bar on each page, but you don’t want to have to code that navigation bar in each page. Earlier composite views were assembled with jsp:include, and later with Struts Tiles. Using Tiles in Struts requires the use of a tiles config file, mapping tile name to jsp. Modern templating libraries such as facelets, which can be used with JSF, have tiling and composite views built in, and no external configuration is required.

Service to worker: This pattern describes how to combine some of the other presentation patterns, so that you can specify business logic to be performed before a view is rendered. Basically, the Front Controller delegates to the Application Controller, which communicates with the business layer (via a Command Object (GOF) or a Business Helper), and then the Application Controller determines which view to show. This model is still how even modern frameworks work.

Dispatcher view: This is simply an alternate to the service to worker, where the dispatcher simply delegates to the view, and the view can use view helpers to construct the view. As such, it is also used today.

Business patterns:

Business Delegate: This pattern is one that is less likely to be used in modern frameworks. The purpose of this pattern is to present a non ejb view of an underlying Session EJB facade, capturing and rethrowing EJB specific exceptions. The Business delegate can also handle lookups. However, with the dependency injection in today’s frameworks and in JEE5, lookups are not really needed, and a Session EJB is more likely to be local. When scaling is needed, the SessionEJB can be clustered, but one instance will still be local to the presentation layer, so again the remote access to a Session EJB is less likely.

Service Locator: This pattern is obsolete with dependency injection, present in most frameworks and JEE5.

Session Facade: Originally, to quote the book, the pattern was to “control client access to business objects” and “limit network traffic between remote clients and fine grained business components and services”. The key change is from when the book was originally written is that the remote clients today are often web services request, and so that generally limits any session facade servicing web services to being a Stateless session bean, as those are those are the only ones (in Jee5) which can expose a web service via a simple annotation. However, the other benefits that derive from controlling client access to business objects remain…in the rich domain model, access to modifications of the model are generally done via a session facade.

Application Service: The purpose of an application service is to hold logic that coordinates multiple business objects, removing such logic from teh session facade. However, with the advent of pojo bases EJBs that can easily communicate among themselves, leading to a rich domain model, the need for an Application Service pattern is diminished.

Business Object: While the importance of the Application Service has diminished, the importance of the business object pattern has increased. This is where the rich domain model, where the object model is patterned after the problem space, is actually implemented.

Composite Entity: This pattern, of tying the lifecycle of related business objects together, is quite useful, and has been standardized in EJB3 through the use of Value Type classes, which explicitly tie a Value Type lifecycle to that of an Entity.

Transfer Object: This pattern is now obsolete, since EJB3 entity beans can be detached from the persistence context and sent over the wire, if need be. Typically, though, these classes are not sent over the wire at all, but merely passed to the presentation layer as is.

Transfer Object Assembler: This pattern is mostly obsolete, for the same reasons as for the Transfer object, but it may still have a role in the use of web services, where you may want to send just a few objects, and not an entire object graph.

Value List Handler: This pattern is also obsolete since the built in query mechanisms of EJB3 does not use the same sort of mechanism as the finders of ejb2, and so is much more lightweight.

Integration Tier Patterns

Data Access Object: While technically, the persistence of objects can be handled through the EJB3 entity manger, it may still be nice to provide type safe DAOs. However, with generics in java 5, there is no need to write more than one such DAO with actual functionality it it–just write that one DAO, and then subclass it for each object type. The subclasses can be very simple and do not have to have any functionality in them–they are just for the strong typing. See this piece of hibernate documentation for examples.

Service Activator: The original reasons for this pattern (which is basically JMS) were for asynchronous methods, publish and subscribe, and splitting a business task into several parts. While publish and subscribe are still valid reasons for using messaging, there are now other options for the asynchronous part. For example, in the Seam framework, annotating a method with @Asychronous turns the method call into an asynchronous one. Behind the scenes, Seam uses the EJB Timer service (default) or Quartz to schedule a job that will run and actually perform the method. The main reason for choosing @Asynchronous would be ease of use. However, if your framework of choice does not support similar functionality, then JMS is still a useful option.

Domain Store: This pattern describes a way to persist and object model without changing the object model, and has thus been supplanted by EJB3.

As you can see from the above listing, many of the patterns described in the book are still in use today, and an understanding of the patterns will help you to understand and get the most use out of whatever modern framework you happen to choose.

Book Review: Core JavaServer Faces, Second Edition

Authors: David Geary – Cay Horstmann

Publisher: Sun Microsystems Press

ISBN: 978-0131738867 (Click to buy from Amazon)

Although JSF was first released in March of 2004, it has become more popular only recently. There are several reasons for the increased popularity:

1. Version 1.2 of the spec both adds some needed functionality and has a new, less buggy reference implementation.

2. The presence of new frameworks such as Ajax4JSF and ICEFaces, which add ajax functionality to JSF applications without the developer having to hand code any javascript.

3. New integration frameworks, such as Seam. One of the knocks against JSF was the fact that it seemed to add back in all the XML that we got rid of with EJB3, but Seam takes care of that.

To use the new frameworks, you’ll need a solid background in the theoretical aspects of JSF, with less time devoted to all the configuration options, since the integration frameworks will take care of that for you. Unfortunately, earlier JSF books took the opposite approach–configuration accounted for a great deal of their content. Fortunately, this book, published after the new frameworks came out, spends a great deal of time on explaining the reasoning behind the design of JSF, and how you can use that knowledge in your own application, and how the new frameworks tie into JSF. Armed with this theoretical knowledge, the authors can also explain the reason behind some of the limitations of the various frameworks. Configuration options are still covered, but in a more succinct way.

The most important theoretical piece of information to know about JSF is the lifecycle of a request–

  1. Restore view
  2. Apply request values; process events
  3. Process validations; process events
  4. Update model values; process events
  5. Invoke application; process events
  6. Render response

One of the advantages of JSF over other, earlier frameworks is that the phases have been explicitly defined and exposed to the developer. The authors take the phases as their guide for how to explain JSF, and this approach works well, as they show what you, the developer, can do at each phase to help accomplish the goals you have for your application.

For now, this is the book to get if you are working with JSF in any capacity.