Server-side Java: Patterns for flexible initialization, Part 1

A reflective approach to initializing your server-side system

1 2 3 Page 3
Page 3 of 3

Tying the knot

The final structure of the minimal setup subsystem includes a custom Exception class. It differentiates runtime exceptions that arise in the startup process from other runtime exceptions. The subsystem also includes TestClass, which is the application system's singleton root node. Note that the TestClass class provides five constructors. The one being called should be identified by the object factory using introspection. The main point of this small setup subsystem is that the implementation and type of the root-node application class is completely unknown to the Startup, ObjectFactory, and ConfigFileParser implementations. The configuration file is the only place in the system that contains information regarding which root-node class should be instantiated. Thus, the setup subsystem has completely decoupled the implementation and type of the root-node class from the implementation of the setup subsystem itself. Figure 5 shows the class diagram for the setup system:

Figure 5. The setup system class diagram

Let us finally take a look at the TestClass and Startup implementations.

Listing 4. TestClass.java

// Copyright (c) 1999 jguru.com

// All rights reserved.

package com.jguru.initHandler;

public class TestClass

{

  private String message;

  public TestClass()

  {

     this.message = "Default constructor called";

  }

  public TestClass(String message)

  {

    this.message = "TestClass(String) called with message: " + message;

  }

  public TestClass(int anInt)

  {

    this.message = "TestClass(int) called with number: " + anInt;

  }

  public TestClass(String message, int anInt)

  {

    this.message = "TestClass(String, int) called with parameters: ("

    + message + ", " + anInt + ")";

  }

  public TestClass(String message, short aShort)

  {

    this.message = "TestClass(String, short) called with parameters: ("

    + message + ", " + aShort + ")";

  }

  public String toString()

  {

     return this.message;

  }

}

Listing 5. Startup.java

// All rights reserved.
package com.jguru.initHandler;
import java.util.Map;
import java.lang.reflect.*;
import java.io.*;
import java.util.*;
/**
 * Driver class that starts up the system.
 *
 * @author Lennart Jörelid, jGuru Europe
 * @version $Id$
 * @since January 2000
 */
public class Startup
{
    /** The ObjectFactory used to create the system root instance. */
    private ObjectFactory    objFactory;
    /** The ConfigFileParser used to read and interpret the Config file. */
    private ConfigFileParser confParser;
    /** Absolute path of the config file. */
    private String           configFilePath;
    /**
     * Creates a new startup object, using an old-style Java property
     * file for storing configuration properties and a simple
     * object factory for creating objects.
     */
    public Startup(String configFilePath)
    {
        // Create internal state objects
        this.confParser = new PropertyConfigParser();
        this.objFactory = new SimpleObjectFactory();
        this.configFilePath = configFilePath;
    }
    /**
     * Main setup entry method that reads the configuration file,
     * interprets all directives, and creates the launcher
     * dynamic object that could start up the entire application.
     */
    public Object doSetup() throws StartupException
    {
       // Read all directives from the config file
       Map configDirectives = confParser.parseConfigFile(configFilePath);       // Find the startup class to load
       String startupClassName = (String) configDirectives.get
("startupClass");
       // Find the number of arguments and create the object array
       // where all the parameters go.
       int numArgs = 0;
       Object[] params = null;
       for(int i = 0; configDirectives.containsKey("type" + i); i++)
numArgs++;
       params = new Object[numArgs]; for(int j = 0; j < numArgs; j++)
       {
           // Find the type and value of the current argument
           String theType     = (String) configDirectives.get("type" + j);
           String theArgument = (String) configDirectives.get("arg" + j);
           params[j] = objFactory.createObject(theType, new Object
[]{theArgument});
       // Create the startup object
       Object startupObject =
this.objFactory.createObject(startupClassName, params);
       return startupObject;
    }
    public static void main(String[] args)
    {
       Startup launcher = new Startup("/setupApp/settings.cfg");
       Object dynObject = launcher.doSetup();
       System.out.println("Created instance of " + dynObject.getClass
().getName());
       System.out.println("[Instance]: " + dynObject);
    }
}

Conclusion

When developing a setup subsystem, strive to decouple the application system root class from the implementation of the setup subsystem. The less tightly coupled the two are, the lower the system maintenance cost. The reflectance classes of the Java API greatly facilitate the introspection required to implement such a decoupling. Use a reflective approach when designing your setup subsystem, and its overall maintenance cost will reduce dramatically. In a next issue of JavaWorld, I will augment the small setup subsystem by working with some of the other reflectance classes of the Java API. Stay tuned!

Lennart Jorelid is a server-side Java and ecommerce content expert working for jGuru Europe. With working experience that spans projects in the United States, Canada, United Kingdom, Switzerland, Sweden, and Germany, Lennart is a recognized expert, architect, and educator in the Java technology community. Based in Göteborg, Sweden, he is writing a book on server-side Java patterns. Lennart is a fan of skiing, acting, and science fiction. Learn more about Lennart at jGuru.com. JavaWorld and jGuru have formed a partnership to help the community better understand server-side Java technology. Together, JavaWorld and jGuru are producing articles and free educational Web events.

Learn more about this topic

Server-side Java: Read the whole series -archived on JavaWorld

1 2 3 Page 3
Page 3 of 3