Dear Wiki user, You have subscribed to a wiki page or wiki category on "James Wiki" for change notification.
The following page has been changed by JoachimDraeger: http://wiki.apache.org/james/Development/ReplacePhoenix/OSGi/ConfigurationAdmin New page: = ConfigurationAdmin = == Motivation == Although OSGi doesn't force us, we should consider to do configuration the OSGi-way. If we would not find an appropriate solution, it would be possible to implement an own or use another configuration service if there is one. Doing it the OSGi-way would enable other bundles to interact with james configuration and give us more interoperability. == How The ConfigurationAdmin works == In OSGi configuration is handled by the ''Configuration``Admin'' service. Every component that needs to be configured does subscribe to a configuration by using a ''service.pid''. The ''service.pid'' is a system-wide unique identifier that is e.g. constructed by using the full qualified class name. The configuration for a component consists of a java-style properties like dictionary of key/value pairs. When the component first subscribes to the configuration or every time the configuration is changed ConfigurationAdmin calls the components that implements ''ManagedService'' update method. {{{ public void updated(java.util.Dictionary properties) throws ConfigurationException }}} ''Note: Spring OSGi will even support direct injection of values into setters. But maybe this is even not appropriate at all, in some cases.'' And what about fancy nested XML configuration? For updating a single bean or a static hierarchy of beans the flat approach should be sufficient and actually the most handy: {{{ component.option1=test component.bean1.option1=test component.bean1.option2=test component.bean2.option1=test component.bean2.bean1.option1=test }}} For components that have 0..n child beans OSGi provides a ''Managed``Service``Factory'' interface. For each child that is added/modified the update method gets called together with a new unique pid. {{{ public void updated(java.lang.String pid, java.util.Dictionary properties) throws ConfigurationException }}} This pid could be usually combined with the full class name and an incrementing number for each child. If the child gets deleted, deleted is called {{{ public void deleted(java.lang.String pid) }}} The component should hold an own map pid -> child to manage update/delete properly. As an example from the James world, you could think of multiple mailets that get attached to a spoolmanager processor. == ConfigurationAdmin And Persistence == Although some people dislike overloaded nested xml file configuration a long pseudo-nested properties-file could be really unhandy, too. So how comes the configuration into the ''Configuration``Admin''? ''Configuration``Admin'' service itself allows also the modification of configuration. Here an example for a ''Managed``Service``Factory'': add a new child to Component1 {{{ Configuration conf = getConfigurationAdmin().createFactoryConfiguration( "org.apache.james.Component1"); String newPid=conf.getPid()); Dictionary newOptions = new Hashtable(); newOptions.put("key", "value"); conf.update(newOptions); }}} And now we modify it using the pid ''newPid'' {{{ Configuration conf = getConfigurationAdmin().getConfiguration(newPid); Dictionary options = conf.getOptions(); options.put("key2","value2"); conf.update(options); }}} In both cases ''Component1.updated(pid,dictionary)'' gets called. To delete the child named ''newPid'': {{{ Configuration conf = getConfigurationAdmin().getConfiguration(newPid); conf.delete(); }}} The changes made to the ''Configuration``Admin'' are automatically made persistent. But the format used by the ''Configuration``Admin'' to save the data depends on its implementation. So there is a solution needed to get the data into the ''Configuration``Admin''. Because the possibilities to make configuration are not limited this approach makes sense. (UI/files/Ldap...) At the moment the only existing solution I know is a console offered by knopflerfish. This is great for making small quick only changes but not an option for bigger reconfiguration. The idea I have in mind is a custom import/export service. This would allow the use of configuration files. At startup and every time a change in the files is signaled (manually or automatically) the custom configuration gets imported into the ''Configuration``Admin''. If desired it is imaginable to even allow an export of online changed options. As input file we could choose xml/properties as appropriately. We have to find a way how the input data could be mapped to ''Configuration``Admin'' properties without the need of (too much) depended code. An ideal way would be to do it ''by convention'' or e.g. a xml-description file. But isn't that much more complicated as what we are doing now? At the moment our components deal directly with the structure of the ''config.xml'' which makes them very dependent. By only passing a key/value map we are avoiding the dependence but the actual work of mapping human-readable config file to attributes has to be done somewhere. == Outlook == So isn't the persistence done by the ''Configuration``Admin'' just overhead? If configuration is done only via external config files, yes. But there are examples where it becomes useful: * When config is changed online the user may decide to discard his changes by reloading the config files * If config is provided by an LDAP server the admin could decide to allow the server to start with the last known config values when the LDAP server is unavailable at startup. * there maybe situations where configuration is changed so fast that an export to an external place (big config file/slow and overloaded ldap server) on every change is not appropriate.