Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Hook on to Jakarta Commons Chain

New Commons framework implements the Chain of Responsibility pattern

  • Print
  • Feedback

The Jakarta Commons project encompasses several subprojects, which contain reusable Java components. Of these, the Logging, Validator, and Digester subprojects are the best known, if only because Struts uses them. A fairly new Commons subproject, still in development, is Chain. The Chain framework is an implementation of the Chain of Responsibility pattern, used to execute a flow of sequential process steps. In the near future, Chain will also be used by Struts (not entirely coincidental—some Struts committers are also Chain committers).

In this article, I explain Chain's usage, advantages, and current imperfections.

Chains, commands, and catalogs

In the Chain framework, units of work within a sequential flow of steps are represented by commands. A sequence of commands forms a chain. The chain itself is also a command that can be executed. Chains are kept in catalogs, from which they can be retrieved at the time of execution. For this purpose, the Chain framework offers the interfaces Chain, Command, and Catalog, see the figure below for a class diagram.

Class diagram of some Chain interfaces

The Chain framework itself contains ready-to-use implementations of Chain and Catalog. You still must implement the commands containing the functionality that forms a unit of work. See Listing 1 for a simple example.

Listing 1. An implementation of a command

 public class ACommand1 implements Command {
   public boolean execute(Context ctx) throws Exception {
      //Add functionality for ACommand1
      String property = (String) ctx.get("property");
      System.out.println("A command1: " + property);
      return false; //The chain will resume
   }
}


An application using the Chain framework must instantiate a Catalog with chains and commands. This can be done directly by using the Chain API or by using a configuration file. The latter option offers the most flexibility. See Listing 2 for a simple configuration file.

Listing 2. A chain-config.xml file

 <catalog>
   <chain name="a-chain">
      <command className="chain.test.ACommand1"/>
      <command className="chain.test.ACommand2"/>
   </chain>
</catalog> 


From this point, applying the Chain framework to execute the configured commands isn't hard, as Listing 3 demonstrates.

Listing 3. The execution of a chain

 public class ChainStart {

public static void main(String[] args) { ChainStart cs = new ChainStart(); //Get the catalog Catalog catalog = cs.parseConfigFile(); //Get the command Command command = catalog.getCommand("a-chain"); try { //Create a context YourContext ctx = new YourContext(); ctx.setProperty("a-value"); //Execute the command command.execute(ctx); } catch (Exception exc) { System.out.println(exc.toString()); } } private Catalog parseConfigFile() { //Parse the configuration file ConfigParser parser = new ConfigParser(); String fileLocation = "/chain/test/chain-config.xml"; try { parser.parse(this.getClass().getResource(fileLocation)); } catch (Exception exc) { System.out.println(exc.toString()); } return CatalogFactoryBase.getInstance().getCatalog(); } }


The ConfigParser can be used to instantiate the Catalog. The Catalog is stored in the singleton CatalogFactoryBase. Because the Catalog doesn't have a name attribute in the configuration file, it automatically is CatalogFactory's default catalog. Therefore, it can be retrieved by the getCatalog() method. Only chains or commands that are direct children of Catalog can be retrieved by the getCommand() method. So, the command ACommand1 cannot be retrieved directly from Catalog. If desired, you can configure ACommand1 as a direct child of Catalog. In that case, Catalog should also have a name attribute.

  • Print
  • Feedback

Resources