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

Dispatcher eases workflow implementation

Improve your application's workflow with the Dispatcher design pattern and XSL

  • Print
  • Feedback

Page 2 of 7

The consequences of using an XSL Dispatcher include:

  • An increased level of modifiability
  • The ability to reuse views with different workflows
  • Reusable workflow API


Implement the strategy

It's now time to implement the XSL Dispatcher solution. Below, I've outlined some of Dispatcher's important classes and their responsibilities.

AbstractDispatcherFactory

The abstract AbstractDispatcherFactory class employs the Builder pattern to create dispatchers:

package workflow;
/**
* This class creates AbstractDispatchers.
**/
abstract public class AbstractDispatcherFactory {
   public abstract AbstractDispatcher getDispatcher(String name) throws
      DispatcherCreateException;
}


AbstractDispatcher

The abstract AbstractDispatcher class dispatches an object. Its next() method determines the next screen in a workflow:

package workflow;
/**
* This class is an abstracted Dispatcher
**/
import java.util.*;
abstract public class AbstractDispatcher {
    /**
    * The next method finds the next part of a workflow.
    * This part of the workflow is represented as a String.
    * @returns the name of the next part of the workflow.
    **/
    public abstract String next(HashMap parameters, Dispatchable ojb,
        String current) throws Exception;
    public String getDispatcherName() {
        return dispatcherName;
    }
   public String dispatcherName;
}


Dispatchable

The Dispatchable interface represents a dispatchable object. Because it is an interface, you must implement Dispatchable in order for the API to use it:

package workflow;
public interface Dispatchable {
    String toXML();
}


DispatcherCreateException

The DispatcherCreateException exception throws if the AbstractDispatcherFactory cannot create a dispatcher:

package workflow;
public class DispatcherCreateException extends Exception {
}


Figure 3 illustrates the relationship between the classes.

Figure 3. The Dispatcher class diagram. Click on thumbnail to view full-size image.

Implementation

Next, let's see how to implement the aforementioned classes.

XMLDispatcherFactory

The XMLDispatcherFactory class creates XMLDispatchers. It retrieves the stylesheet and creates a javax.xml.transform.Transformer useable by the dispatcher:

package workflow.example;
import javax.xml.transform.*;
import org.apache.xalan.processor.TransformerFactoryImpl;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.stream.*;
import java.util.*;
import javax.xml.transform.sax.*;
import java.io.*;
import workflow.*;
/**
* The XMLDispatcherFactor creates instances of XMLDispatchers.
* It reads in the appropriate XSL and
* creates the Transformer object.
*/
public class XMLDispatcherFactory extends AbstractDispatcherFactory {
    //The various workflows and the stylesheets associated with them.
    static Properties properties = new Properties();
    //The Transformer factory
    static TransformerFactory factory = new TransformerFactoryImpl();
    //Just to keep it simple, add the only workflow we have right now.
    static {
       properties.put("application", "c:/application.xsl");
       System.out.println("added application");
    }
    public XMLDispatcherFactory()
    {
    }
/**
* Gets the dispatcher requested and the workflow represented by the name.
* @param name the name of the workflow.
*/
    public AbstractDispatcher getDispatcher(String name)
       throws DispatcherCreateException {
      Transformer transformer = null;
      XMLDispatcher dispatcher = null;
      try
      {
        System.out.println("Reading in file");
        //Create the transformer object
        transformer = factory.newTransformer
           (new StreamSource(new FileInputStream
           ((String)properties.get(name))));
        //Create an instance of the XMLDispatcher
        dispatcher = new XMLDispatcher(transformer);
      }
      catch (TransformerConfigurationException transE)
      {
         System.out.println(transE.getMessage());
         throw new DispatcherCreateException();
      }
      catch (FileNotFoundException noFile)
      {
         System.out.println(noFile.getMessage());
         throw new DispatcherCreateException();
      }
      dispatcher.dispatcherName = name;
      return dispatcher;
    }
}


XMLDispatcher

The XMLDispatcher class uses the transformer to determine the next screen. The XMLDispatcher does this by persisting an object to XML before performing the transformation. The class also passes various parameters to the stylesheet. The stylesheet simply produces a string representing the name of the view the user should see next:

  • Print
  • Feedback

Resources