This class facilitates separation of concerns between the configuration
logic and the application code.
Does your class need to know or has to assume that the configuration is
coming from system properties ??
The response is obviously NO!
Let's compare the following examples:[code]
class Document {
private static final Font DEFAULT_FONT
= Font.decode(System.getProperty("DEFAULT_FONT") != null ? System.getProperty("DEFAULT_FONT") : "Arial-BOLD-18");
...
}[/code]
With the following (using this class):[code]
class Document {
public static final Configurable DEFAULT_FONT = new Configurable(new Font("Arial", Font.BOLD, 18));
...
}[/code]
Not only the second example is cleaner, but the actual configuration
data can come from anywhere (even remotely). Low level code does not
need to know.
Furthermore, with the second example the configurable data is
automatically documented in the JavaDoc (public). Still only instances
of
Logic may set this data. There is no chance
for the user to modify the configuration by accident.
Configurable instances have the same textual representation as their
current values. For example:[code]
public static final Configurable AIRPORT_TABLE
= new Configurable("Airports");
...
String sql = "SELECT * FROM " + AIRPORT_TABLE // AIRPORT_TABLE.get() is superfluous
+ " WHERE State = '" + state + "'";[/code]
Unlike system properties (or any static mapping), configuration
parameters may not be known until run-time or may change dynamically.
They may depend upon the current run-time platform,
the number of cpus, etc. Configuration parameters may also be retrieved
from external resources such as databases, XML files,
external servers, system properties, etc.[code]
public abstract class FastComparator implements Comparator, Serializable {
public static final Configurable REHASH_SYSTEM_HASHCODE
= new Configurable(isPoorSystemHash()); // Test system hashcode.
...
public abstract class ConcurrentContext extends Context {
public static final Configurable MAXIMUM_CONCURRENCY
= new Configurable(Runtime.getRuntime().availableProcessors() - 1);
// No algorithm parallelization on single-processor machines.
...
public abstract class XMLInputFactory {
public static final Configurable> DEFAULT
= new Configurable>(XMLInputFactory.Default.class);
// Default class implementation is a private class.
...
[/code]
Reconfiguration is allowed at run-time as configurable can be
Configurable.notifyChange notified of changes in their
configuration values. Unlike system properties, configurable can be
used in applets or unsigned webstart applications.
Here is an example of configuration of a web application from
a property file:[code]
public class Configuration extends Configurable.Logic implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
try {
ServletContext ctx = sce.getServletContext();
// Loads properties.
Properties properties = new Properties();
properties.load(ctx.getResourceAsStream("WEB-INF/config/configuration.properties"));
// Reads properties superceeding default values.
Configurable.read(properties);
} catch (Exception ex) {
LogContext.error(ex);
}
}
}[/code]
This listener is registered in the web.xml file:[code]
mypackage.Configuration
[/code]
The property file contains the full names of the configurables static
fields and the textual representation of their new values:[code]
# File configuration.properties
javolution.util.FastComparator#REHASH_SYSTEM_HASHCODE = true
javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY = 0
javolution.xml.stream.XMLInputFactory#DEFAULT = com.foo.bar.XMLInputFactoryImpl
[/code]
Configuration settings are global (affect all threads). For thread-local
environment settings
javolution.context.LocalContext.Reference LocalContext.Reference instances are recommended.
Note: Any type for which a text format is
TextFormat.getInstance(Class) known can be configured from
String properties.
author: Jean-Marie Dautelle version: 5.1, July 4, 2007 |