IMO using preferences trees as low level representation of configuration is not bad, since it provides a comprehensive and intuitive representation, which also for error analysis is quite useful. But my experience shows we should consider a few points:
- util.Prefernces in the JDK has numerous flaws
- bad design with abstract classes that constrain different things, including the synchronization of access, or are difficult to adapt
- platform dependent default behaviour (file storage vs. Windows registry etc)
- no out of the box support for different subtree providers
- but the main concern is, that there is no separation between presentation (the nodes) and the model, which makes it very cumbersome to be used in a EE context. We implemented such a separation in the bank, including a complete subtree model spi and node context management, but given this experience IMO util.preferences is too much crap to build a configuration JSR on top of it. Despite the fact that we would only be able to use it in a feasible way, if we would replace the PreferencesFactory, which may be incompatible with people that already did register their own factory.
- most preferences models seem to model a tree of nodes, with properties on the nodes. IMO this has some disadvantages:
- by exposing the tree structure to the API users, you enable clients to cache and access any node in your tree, at any time from any thread. This leads to greater complexity in a multi-threaded, multi-tenancy system, and thus requires more synchronization than would be needed in many cases. In multi-threaded high parallell access this design tends to lead to dead-locks or starvation issues quickly. Especially when preferences nodes are also mutable, like the JDK Preferences API. IMO most of the configuration remains quite stable about an application/servers runtime, so I would argue, to define immutable semantics on the configuration aspects, where possible.
- This means not that configuration cannot change, but I would allow the change by another isolated API, thus separating read of configuration and update of configuration explicitly. Reading clients can also easily be informed on config changes by listening on according ConfigChange events.
So summarizing organizing configuration in a configuration tree (or preferences) would quite probably be a feasible design, when the following points are considered:
- access by default is only reading
- the model and the tree structure should be separated, so referenced node instances can be invalidated without harming the whole configuration model.
- writing/changing operations are modeled separately.
- From each node, access of values by property identifier is still possible (or even encouraged).
- Looking at the complexities of complex application product installations (like we have) I additionally would argue, that I would like to access/support several configuration/pref trees:
- default trees (corresponding what I called aggregates before) for each default aggregate
- a tree for each scope
- trees for each custom aggregate
Based on such a "low level" representation we might define more advanced services as useful...
-Anatole