|
|
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
Page 3 of 4
Your system has indeed created an object from a class specified in the configuration file, thus fully decoupling the application initialization class from the application setup code. This process was covered in Part 1, so the only remaining issue is to call a method in that class to actually launch the system. A setup system can do all the initialization and required object creation from within a single constructor call; the system can then work properly. However, some systems will be better off not launching vast numbers of new threads from within the constructor of one of its classes. This is especially true of systems where race conditions may occur for reasons beyond your control. Such systems need to construct and set up all required objects, then have a specific method called afterward to launch the normal working thread.
To keep with the tradition of creating the launcher object completely from configuration-file specifications, you should place the name of the method to invoke in the configuration file. Since all proper object setup should have been done from within the launcher class's constructor, the launcher method should rarely, if ever, need any parameters to control its execution. The Invocation pattern of the launcher method can therefore be greatly simplified.
You will have to provide the launcher method name in the configuration file. The only modification of this file is the single,
boldface row at the end of the following list, which provides the startupMethod directive.
############################################ # # # jGuru Sample Configuration file # # Created by Lennart Jörelid, lj@jguru.com # # # ############################################ startupClass=com.jguru.initHandler.TestClass arg0=A custom config string type0=java.lang.String arg1=42 type1=java.lang.Integer startupMethod=loadSystem
These equivalent Java statements should be performed after parsing the configuration file above:
TestClass launcher = new
com.jguru.initHandler.TestClass("A custom config string", 42);
launcher.loadSystem();
The first statement sets up all the objects in the system, as was demonstrated in Part 1. Your task is to invoke the loadSystem method from instructions read in the configuration file. This is another task handled well by the Java reflection API of
package java.lang.reflect. Thus, the Startup class is slightly altered to handle the method invocation. The alterations from the former Startup class are small, and have been marked in bold below:
// Copyright (c) 1999 jguru.com
// 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 <a href="mailto:lj@jguru.com">Lennart
Jörelid</a>,
* <a href="http://www.jguru.com">jGuru
Europe</a>
* @version $Id$
* @since January 2000
*/
public class Startup
{
/** The ObjectFactory used to create the dynamic
(first) 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;
/** All parsed directives found in the config
file. */
private Map configDirectives;
/**
* 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 variables
this.confParser = new PropertyConfigParser();
this.objFactory = new SimpleObjectFactory();
this.configFilePath = configFilePath;
}
/**
* Main setup method, that reads the configuration file
* interprets all directives, and creates the launcher
* dynamic object that could startup the entire application.
*/
public Object doSetup() throws StartupException
{
// Read all directives from the config
file
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 of the 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 void invokeStartupMethod(Object target) throws
StartupException
{ // If the user has defined a startup
method, invoke it. String startupMethodName = (String)
configDirectives.get("startupMethod");
if(startupMethodName == null ||
startupMethodName.equals(""))
{
System.out.println("Found no startup method in config
file.");
System.out.println("Exiting startup.");
return;
}
System.out.println("\nInvoking method " +
startupMethodName);
Method[] allMethods = target.getClass().getDeclaredMethods();
for(int i = 0; i < allMethods.length; i++)
{ // Make sure the method have no
parameters. if(allMethods[i].getName().equals(startupMethodName)
&& allMethods[i].getParameterTypes().length == 0)
{
// This is the method to
invoke. try
{
// Finally invoke the
method. allMethods[i].invoke(target, null);
}
catch(InvocationTargetException itex)
{
System.err.println("Could not invoke startup
method " + startupMethodName);
System.err.println("" +
itex.getTargetException());
}
catch(Exception ex)
{
System.err.println("Could not invoke startup
method " + startupMethodName);
System.err.println("" + ex.getMessage());
}
}
}
}
public static void main(String[] args)
{
// First, create a dynamic setup object from
the
// given directives of the configuration file.
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);
// Invoke the startup method on the
dynamically created object.
launcher.invokeStartupMethod(dynObject);
}
}
Server-side Java: Read the whole series -archived on JavaWorld