The following examples show how to perform various functions with a pipeline servlet.

Setting an Attribute

In this example, a pipeline servlet examines a request to see if it starts with “/stocks” or “/bonds.” If so, then it sets a “wallStreet” attribute to true. Otherwise, it sets a “wallStreet” attribute to false.

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import atg.servlet.*;
import atg.servlet.pipeline.*;

public class WallStreet extends PipelineableServletImpl {
  public WallStreet () {}
  public void service (DynamoHttpServletRequest request,
                       DynamoHttpServletResponse response)
       throws IOException, ServletException
  {
    String pathInfo = request.getPathInfo ();
    boolean val =
      pathInfo.startsWith ("/stocks") ||
      pathInfo.startsWith ("/bonds");
    request.setAttribute ("wallStreet", new Boolean (val));
    passRequest (request, response);
  }
}

This wallStreet attribute is now available for use by subsequent servlets. For example, the following servlet might follow the WallStreet servlet, printing a message if it finds the wallStreet attribute is true:

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import atg.servlet.*;
import atg.servlet.pipeline.*;

public class Trader extends PipelineableServletImpl {
  public Trader () {}
  public void service (DynamoHttpServletRequest request,
                       DynamoHttpServletResponse response)
       throws IOException, ServletException
  {
    Boolean b = (Boolean) request.getAttribute ("wallStreet");
    if (b != null && b.booleanValue ()) {
      System.out.println ("I'm on Wall Street!");
    }
    passRequest (request, response);
  }
}
Setting an Attribute Factory

The sample pipeline servlet element we saw in the previous section has a problem: it always examines pathInfo and creates a new Boolean attribute, whether that attribute is needed or not. This attribute can be expensive to create and wasteful if the attribute is never accessed.

Rather than setting an attribute, this pipeline servlet would be more efficient if it set an attribute factory that creates the attribute value the first time it is needed. The following shows how to do this:

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import atg.servlet.*;
import atg.servlet.pipeline.*;

public class WallStreet extends PipelineableServletImpl {
  // The AttributeFactory
  class WallStreetFactory implements AttributeFactory {
    DynamoHttpServletRequest request;
    public void setRequest (DynamoHttpServletRequest request)
    { this.request = request; }

    public Object createAttributeValue ()
    {
      String pathInfo = request.getPathInfo ();
      boolean val =
        pathInfo.startsWith ("/stocks") ||
        pathInfo.startsWith ("/bonds");
      return new Boolean (val);
    }
  }

  public WallStreet () {}
  public void service (DynamoHttpServletRequest request,
                       DynamoHttpServletResponse response)
       throws IOException, ServletException
  {
    WallStreetFactory f = new WallStreetFactory ();
    f.setRequest (request);
    request.setAttributeFactory ("wallStreet", f);
    passRequest (request, response);
  }
}

The AttributeFactory is defined as an inner class. Every time a request comes through, a new attribute factory is created and registered with the request. This factory is given a pointer to the request, so that when the factory is asked to create the attribute value, it can compute the value from the request.

Setting a Permanent Attribute

The previous example showed how a request could improve performance by delaying computation of the “wallStreet” attribute until it is first needed. But there is still the problem that a WallStreetFactory is created on every request. This repeated creation can be avoided by using permanent attributes. In this example, the WallStreetFactory is stored as a permanent attribute that is accessed during the request.

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import atg.servlet.*;
import atg.servlet.pipeline.*;

public class WallStreet extends PipelineableServletImpl {
  // The AttributeFactory
  class WallStreetFactory implements AttributeFactory {
    DynamoHttpServletRequest request;
    public void setRequest (DynamoHttpServletRequest request)
    { this.request = request; }

    public Object createAttributeValue ()
    {
      String pathInfo = request.getPathInfo ();
      boolean val =
        pathInfo.startsWith ("/stocks") ||
        pathInfo.startsWith ("/bonds");
      return new Boolean (val);
    }
  }

  // The permanent attribute
  class KeyFactory implements AttributeFactory {
    public Object createAttributeValue ()
    { return new WallStreetFactory (); }
  }
  KeyFactory key = new KeyFactory ();

  public WallStreet () {}
  public void service (DynamoHttpServletRequest request,
                       DynamoHttpServletResponse response)
       throws IOException, ServletException
  {
    WallStreetFactory f = (WallStreetFactory)
      request.getPermanentAttribute (key);
    f.setRequest (request);
    request.setAttributeFactory ("wallStreet", f);
    passRequest (request, response);
  }
}

Now the pipeline servlet performs no object allocations when a request comes through. And when the attribute is accessed, only a single Boolean value is created. More permanent attributes could be used to avoid even the creation of that Boolean value.

Notice how this implementation is approximately twice as large as the first implementation that just created a new attribute value with every request. Remember that all of this extra code improves performance – it reuses objects and delays computation of attributes until they are needed. So even though the code is longer, the performance should be better.

Dispatching Servlets

The PipelineableServletImpl provides a convenient method for specifying a nextServlet and for passing calls to that servlet. This provides a nice linear model of processing. There are many instances, however, where you might want to branch to one of many servlets based on the request. For example, if you want to call a servlet that isn’t a pipeline servlet, you’ll need to use an alternative method.

To do this, make sure your servlet implements the java.servlet.RequestDispatcher interface defined in the J2EE specifications. This interface creates a wrapper for your custom servlet. That wrapper specifies the servlets that come before and after your servlet. You also need to define your servlet in your web.xml deployment descriptor.

 
loading table of contents...