Persistent configuration data
Services need some persistent configuration data.
For example, a service that initializes all network devices (bootp/static...) needs to store these bootp/static parameters.
For this I'm introduction the concept of a persistent configuration object per plugin.
Each plugin can implement a class (derived from PluginConfiguration) that holds all configuration data for that plugin. The classname of this class should be specified in the configuration-class attribute of the plugin descriptor.
This configuration class is instantiated by the plugin manager and also saved/loaded by the plugin manager. All public get/set methods are used to identify the attributes that must be persisted.
A service implemented in a plugin can obtain a reference to its configuration object via the plugin descriptor use it to get/set its configuration data.
Ewout
- Login to post comments
Types
What types can be persisted? Serializable? XMLEncodeable? Both? Neither?
The concept is very clean and neet, but how does it work?
Alex
Re: Types
How does it work, well the persistency itself still has to be implemented. But here are my ideas.
The storage-service gets a configuration object and uses reflection to obtain all public properties and saves them to its storage medium.
The other way around: the plugin manager instantiates the configuration object and passes it to the storage-service, which in term load the data and sets all public properties.
The issues here is that we need some kind of long term persistence, that can cope with changing classes (during development).
Ideas?
Another issue is that i want the storage-service to be pluggable. So there will be plugins that cannot have this kind of configuration data, because they must be started before the storage-service. E.g. a filesystem may well be used by the storage-service.
I'm thinking of adjusting the start-order of plugins, so it starts plugins with configuration data to the end of the start-list.
Ewout
how to get the info from the classes
Hi,
you supposed to use reflection to obtain all public properties.
But to be able to restore the saved data to a new version of any given class, where some properties may have changed, it could be better to implement an Interface. This Interface may at least have two methods :
property[] getProperties()
void setProperties(property[] props)
One property may have a name and a value.
In this case the missing properties in the stored date of that updated class can be handled by the setProperties(property[] props) method in any way.
I know it is much more work not to use reflection, because everyone who will use that service has to implement these methods.
Trickkiste
beans.XMLEncoder
The beans.XMLEncoder provides all of this funtionality. I have used it with tremendus success as a mode of persistence in my oodb.
XMLEndoder works like an ObjectOutputStream, instanciate it with a target stream, and feed it objects. The objects are inspected for bean properties to be saved. The XMLDecoder is then the same as an ObjectInputStream.
In order to be encodable, an object must have an empty public constructor. In order for the data it represents to be saved that data must be exposed in complete bean patters (get and set). If either part is missing the data represented by the propery will not be recoverable. Also the data of the properties must be encodable. This is the same idea as the tree of serializable objects needed for serialization.
The xml data is very resilient to class def changes.
The changes that effect xml encoding surround the pressence of complete bean properties (get and set).
There are three property change senarios:
1) A property that was in ClassA is no longer in ClassB: the data from that property will be lost.
2) A property is in ClassB that was not in ClassA: the data represented by the new property will be null.
3=1+2) A property in ClassA is renamed in ClassB: the data of the original property will be lost and the data of the new property will be null.
The only change that the encoder cannot cope with is a change in the name of the class of the persisted object. In that case Class.forName() will fail and the system will have no Class to inspect.
What do you think,
Alex
configuration
In order to be encodable, an object must have an empty public constructor. In order for the data it represents to be saved that data must be exposed in complete bean patters (get and set). If either part is missing the data represented by the propery will not be recoverable. Also the data of the properties must be encodable. This is the same idea as the tree of serializable objects needed for serialization.
This is not necessarily true because one can implement java.beans.PersistenceDelegate for such a class. This can sometimes made for performance reasons too:
eg. the standard transformations for arrays generate huge amount of 'code'. With a little knowledge about the structure of your data one can tweak the mechanism alot.
---
Since I have recently written a small configuration API I can add a small idea to that larger topic:
The basic is that I distinguish between what the configuration is able to store and what a specific module (in JNode: service) thinks about that data. My solution involved an abstract base class providing the API to the configuration system (via protected methods) named Prefs.
Now each module which wants to store some configuration has to subclass Prefs and provide an API to its local environment to access the stored data (default values inclusive). Instances of these subclasses have to be handed out to the configuration system, of course.
Just my 2 € cents
Class not there yet
Looks promising, but this class is not implemented by classpath yet.
Are there any open implementations yet?
Ewout
Java and XML Encoding/Decoding
Hi,
for others Open-Source Library that transform Java to XML and back, look at: http://skaringa.sourceforge.net/ , and at http://xstream.codehaus.org
I'm using both in some Projects, they are fast and works very well.
For example, I'm using this library with another Open-Source ibrary, very promising (about Prevalence): www.prevayler.org that manage any data structure in-memory with transaction logs on filesystem, and periodical snapshot (on disk) of the entire dataset. This is really VERY fast, having always all the data in RAM (and accessing directly to Java Objects, without SQL or other parsed languages), but for a lot of Applications if really a next step forward.
Here they use some adaptors to make Skaringa usable for the snapshot, instead of the default format (Java Serialization), but I can configure any other library if I want ...
Maybe this could be useful also as a JNode Service for some types of Applications ...
Bye,
Sandro
Hi
I think it does the same like the reflection way (1 .. 3).
What I though was in case 2 is different.
E.g. in case of an ArrayList as property. In your case this ArrayList would be null.
So you can not get the iterator for that (empty) ArrayList (the attempt would end in an exception).
In my opinion (as posted above) the class provides the get / set methods.
In the newer version of that class the set method could set the ArrayList to null also, but it could set it to new ArrayList() and the call of iterator() will return a proper iterator for that (empty) ArrayList.
Do you know what I mean?
Trickkiste
I see
I see your point. Number three could be diferent too. The data could be properly realocated in the event of a property name change (instead of loosing the data).
I guese Ewout has to decied
Alex