Configuration changes in the Tigase Server 5.x

Submitted by kobit on Wed, 2010-01-06 21:22
::
The whole configuration framework for the Tigase server has been redesigned and rewritten. This was done to cleanup all the configuration code and logic and also extend the current functionality and allow for configuration storage in different kinds of repositories - memory, file, database, ... The title says configuration changes but the version 5.x still follows our policy about backward compatibility so the changes should be rather called extensions. There is however one change which can affect a few users. Those who use the server and worked with it's configuration remember the mess and confusion related to duality in the server configuration - the init.properties file and tigase.xml file. This is now over.

Reverting to the old behaviour

While using the tigase.xml file is still possible and the whole old behaviour can be preserved it is now disabled by default. By default the Tigase server reads only init.properties file with initial settings and stores all the complete configuration in memory only. The init.properties works exactly as before and all old parameters are still working exactly as before. The only difference is the lack of the tigase.xml which is not created by default and is not read by default if it is present. The main advantage is that you don't have to remove it each time you change something in the init.properties to pick up new settings. I will first present how to revert to old behaviour as this might be critical to some existing systems which want to upgrade. This is actually very simple to accomplish. The Tigase server now, offers pluggable repository support. This means that you can easily extend current functionality with a different configuration storage by writing own class which reads and writes configuration parameters. By default class tigase.conf.ConfigurationCache is loaded which stores configuration in memory only. Please note, the init.properties file is always read if it exists at given location. To revert to the old behaviour you just need to pass a parameter to the Tigase server with a class name which is responsible for keeping server parameters in the old XML file. You can do it in two ways:
  1. Add a parameter to init.properties file:
    --tigase-config-repo-class=tigase.conf.ConfigXMLRepository
    
  2. You can pass a system property to the JVM at the startup time:
    -Dtigase-config-repo-class=tigase.conf.ConfigXMLRepository
    

Default behaviour

By default the Tigase server loads tigase.conf.ConfigurationCache class which stores the whole configuration in memory. Please note that the init.properties file with initial settings is always loaded if it is available at the given location and all settings in this file work exactly as before. For more details, please refer to the online documentation. A couple of times I mention about 'initial configuration' and 'whole configuration'. What is this about, what is the difference? The initial configuration are startup settings provided by the user in the init.properties file. Most of the server elements, however use far more configuration parameters which are set to sensible default values if they are not provided by the user. The configuration framework in the Tigase server, however always keeps the complete configuration of all active elements. This is implemented in such a way to make it possible to present currently used settings to the end-users or administrators and allow them to change the server parameters at runtime.

Storring configuration in SQL database

There is one more configuration storage implemented right now. It allows you to store the server settings in the SQL database. In most cases this is not quite useful, just opposite, very inconvenient. There is however at least one case when you really want to keep the server configuration in the SQL database. This is the cluster mode. If you have a Tigase cluster system of 10 or more nodes it is much easier to keep configuration in a single central location and manage it from there, rather then go to every single machine, every time you want to change some settings. You can even change any settings for all cluster nodes with a single database query. You set the SQL storage the same way as you set it for XML file, there is, however one more parameter as you have to provide also database connection string for the server so it knows where to connect to for the settings:
  1. Parameters in init.properties file:
    --tigase-config-repo-class=tigase.conf.ConfigSQLRepository
    --tigase-config-repo-uri=connection-uri
    
  2. Alternatively you can provide system properties to the JVM:
    -Dtigase-config-repo-class=tigase.conf.ConfigSQLRepository
    -Dtigase-config-repo-uri=connection-uri
    
Please note, the current implementation for the SQL storage automatically creates necessary table if it does not exists. So you don't have to worry about the schema but you should make sure that the database user used by the Tigase has permissions to create a table. Configuration is stored in table with following schema:
create table tigase_configuration (
-- The component name by which the configuration parameter
-- is used.
  component_name varchar(127) NOT NULL,

-- The configuration property key name or identifier.
  key_name varchar(127) NOT NULL,

-- The configuration property value
  value varchar(8191) NOT NULL,

-- The cluster node by which the configuration property is read,
-- if empty it will be read by all cluster nodes.
  cluster_node varchar(255) NOT NULL DEFAULT '',

-- Additional, secondary identifier for the configuration property.
-- The configuration can be organised in a hierarchical way to allow
-- multiple occurrences of the same property name for a single
-- component, for example you can have the same property for 
-- different tcp/ip ports set to a different value:
-- c2s/5222/port_type=plain
-- c2s/5223/port_type=ssl
-- the port number is a secondary identifier.
  key_node varchar(127) NOT NULL DEFAULT '',

--  Not currently used. In future it will be used to distinguish between
-- different kind of properties (initial settings, defaults, updated by 
-- user, etc...)
  flag varchar(32) NOT NULL DEFAULT 'DEFAULT',

-- The system detects basic Java types and stores information about
-- the property type, when the property is read the original property
-- type is restored and provided to the component without need for
-- a parsing or conversion.
  value_type varchar(8) NOT NULL DEFAULT 'S',

-- It is not currently used. In the future it will be used to reload 
-- settings changed in last, defined period of time. Basicall, the
-- system can automatically check the configuration database to 
-- see whether some properties have been updated, then reload
-- them and apply automatically.
  last_update           timestamp,

primary key(cluster_node, component_name, key_node, 
                  key_node, flag));

Going further

There is more. As the configuration mechanism in the Tigase server offers pluggable storage engines you can easily write your own engine by implementing the interface: tigase.conf.ConfigRepositoryIfc or by extending one of current implementations. There is even more. You can go even further. The whole configuration framework is pluggable and you can replace it completely if it doesn't suites you well enough. Your implementation has to extend tigase.conf.ConfiguratorAbstract class and can be set using JVM system property (as this is configuration framework you can't do this via any configuration system):
-Dtigase-configurator=tigase.conf.Configurator
The example above shows the parameter set to the default configuration framework.

Message router implementation is configurable too

The Message router component was the only component which was fixed to the Tigase instance. In theory it could always be replaced but in practise there was no way of doing it as that was the first element loaded at the server startup time. Now the Tigase message router implementation can be easily replaced to and it can be made a configurable option if needed. At the server startup time the code creates configurator and calls method: getMessageRouterClassName() which by default returns class: tigase.server.MessageRouter. You can extend the configurator and provide any different class name instead which implements required interfaces. You can even make it configurable. It is no longer a fixed thing for the server instance.