Now that you know how to get the properties of a component (otherwise, please read the Introduction) we are ready to start looking at all the functionality related to properties present in EasyConf.
The properties are hold in a class called ComponentProperties which has one method for each supported property type. For example to get a property called skin which is a string of characters you can use:
String skin = getProperties().getString("skin");
Note: In all the examples it will be assumed that there is a method called getProperties() which obtains the properties of a configuration component. A possible implementation of this method would be:
private ComponentProperties getProperties() { return EasyConf.getComponent("my-component").getProperties(); }
All methods to get the value of a property have an optional parameter to specify a default value. Using this parameter the previous example would be written as:
String skin = getProperties().getString("skin", "blue");
If the property skin is not found in any of the property files associated with the component, blue will be returned.
When no default value is specified EasyConf considers the property mandatory and if it is not found a NoSuchElementException is thrown.
EasyConf can behave in one of two ways when it tries to access a property that doesn't exist:
componentConf.setThrowExceptionOnMissing(true);
Besides the usual String type, EasyConf has included support for automatic conversion to all of Java's numeric types. Native numeric types are supported both in the native and in the class format whenever possible. Here is a complete list of the supported numeric types:
To use the automatic conversion you must know in advance which is the numeric type of the property and use the appropriate getter method of ComponentProperties. For example to read a Short value the getShort(...) method should be used, for a BigInteger, use getBigInteger(...), etc. Here is an example which shows the usage of methods for all of the supported numeric types:
value = getProperties().getBigDecimal("big-decimal"); value = getProperties().getBigInteger("big-integer"); value = getProperties().getBoolean("boolean"); value = getProperties().getByte("byte"); value = getProperties().getDouble("double"); value = getProperties().getFloat("float"); value = getProperties().getInteger("integer"); value = getProperties().getLong("long"); value = getProperties().getShort("short");
If the conversion fails, a runtime ConversionException will be thrown.
Multivaluated properties are those that may have more than one value. EasyConf supports automatic conversion of multivaluated properties to:
The conversion is performed by separating the property value interpreting the comma character as a separator. Here is an example:
multivaluated=one,two,three
Note that the character next to the comma is not ignored even if it is an space so do not leave spaces between elements (unless that's really what you want). This property can be read with both the getList() and the getStringArray() methods:
List values = getProperties().getList("multivaluated"); String[] array = getProperties().getStringArray("multivaluated");
Both methods are pretty similar. The most important property is explained in the support for variables. This is explained in the next section.
Important note: as a result of this automatic conversion if the value of a single valued property contains commas they must be scaped with a double slash. Example:
single-valued=one\\,two\\,three
EasyConf supports using variables in the value of a property to refer to the value of another property. This functionality is not available for all property types, only for the following:
Note: support for variables is provided by one of the underlying libraries, Jakata Commons configuration, which is the one that has this limitation. I hope that the support for variables will be extended to all property types in future versions.
Lets see some examples:
supported-currencies=${trusted-currencies},pound trusted-currencies=dollar,euro european-currency=euro default-currency=${european-currency}
When an application wants to offer the flexibility to change the implementation of a class it must provide some place where the users can specify the class name. If you are using some Inversion of Control framework such as Spring or PicoContainer it handles everything, but when those frameworks are not used there is no simple and standard way to configuring class names without running into trouble. EasyConf aims to fill this gap by giving a special treatment to properties whose value is a class name.
For example, if you have a properties file with the following property:
database-configuration-class=com.germinus.easyconf.example.DatabaseConf
You could read it using the getClass() method of the ComponentProperties class:
Class configuredClass = getProperties().getClass("database-configuration-class");
The getClass method has the usual variants of all other getter methods. So you can specify a default values or a filter. Check the javadocs for further information.
But wait!, Java has an static method which can be invoked as Class.forName(className) which looks for and loads a Class from a class name. That's easy enough, isn't it?. Unfortunately this method has severe limitations which may convert into problems when an application is run in a multithreaded environments or when more than one class loader is used. In those cases using the getClass method provided by EasyConf is preferred.
For the curious EasyConf searches for the class using two class loaders. The following sequence is used:
EasyConf allows including other files in its property configuration files. To specify the name of a file to include a special property called include-and-override is used. Its name shows the fact that the in case of collision of property names the values of the included file will override the values of other file. Lets see an example of use:
include-and-override=external-file.properties
The included file will be searched for using the same conventions as all the other configuration files. Recursive file inclusion is supported so this file can also include other files. Be caution with this to prevent loops.
If an included file is not found it is silently ignored. Leveraging this you can set optional extension points to the property files that can be used optionaly by a user of the application to override properties values. Another useful feature is using variables in the names of the files to be included. An example of using this two features can be found in the explanation about the support for multiple environments. Here is how using a variable would look like:
include-and-override=mycomponent-${environment.name}.properties
Several external files can be included. This can be done either specifying the in comma-separated list or by using several times the include-and-override property.
include-and-override=external-file1.properties,external-file2.properties include-and-override=external-file3.properties
In this case the property files will be loaded in the specified order and in case of property name collision the values of the last files loaded will override the previous ones.
Note: Commons configuration also has a feature to include external files. EasyConf does not use it to have more control of the included files. For that reason it is not documented here.