OSGi Preferences Service by Example
A common question asked by new Java developers is what’s the best solution to store user-specific or application settings. Of course, it is always possible to designate a particular folder (for instance /etc/myapp) in the filesystem to that use, but that often represents a limit for the application portability (what happens if it doesn’t run on Windows?). That’s the reason the Java Preference API was designed.
OSGi of course is not immune to that problem; an OSGi bundle may run in any device supporting a R4 OSGi container, and therefore needs a well defined and portable mechanism to store application and user settings. That’s the business of the OSGi Preferences Service.
In this article I’m going to show how you can use the Preferences Service in your OSGi applications.
First of all, you need an implementation of the OSGi Preferences Service. Apache Felix provides, as usual, a portable implementation that you can download and use in any R4 container: you can download the jar here and check the documentation here.
After you have downloaded and installed the bundle in your OSGi container, accessing to the Preferences Service is as simple as using any other service in OSGi:
ServiceReference serviceref = context.getServiceReference(PreferencesService.class.getName());
if (serviceref != null)
{
PreferencesService preferences = (PreferencesService) context.getService(serviceref);
//store and retrieve your preferences here
}
Preferences are organized in a tree structure, so you can define quite complex preference models; the only limitation is give by the fact that you can store on “simple” values (boolan, double, float, int, long and strings) and not any type of Java object.
As mentioned before, the Preferences Service can be used to store application and user settings. To store application settings, you will place your settings under the system root.
Let’s see in the following example how an application can store the information gathered during the installation:
ServiceReference serviceref = context.getServiceReference(PreferencesService.class.getName());
if (serviceref != null)
{
PreferencesService preferences = (PreferencesService) context.getService(serviceref);
//create a node 'installation' under the system root
Preferences installationPreferences = preferences.getSystemPreferences().node("installation");
installationPreferences.put("path", "/opt/myapp"); //path chosen by the user
installationPreferences.put("license-key", "687-6GH-9JU-35H"); //license key
installationPreferences.put("license-email", "hacker@hackerz.com"); //license owner...
}
Reading these settings is equally simple (note that every getter method has a second argument that specifies a default property value if the one required is not found):
ServiceReference serviceref = context.getServiceReference(PreferencesService.class.getName());
if (serviceref != null)
{
PreferencesService preferences = (PreferencesService) context.getService(serviceref);
//retrieve the 'installation' node under the system root
Preferences installationPreferences = preferences.getSystemPreferences().node("installation");
String key = installationPreferences.get("license-key", null); //get the license key
String ownder = installationPreferences.get("license-email", null); //get the license owner
}
Using the same API you can store and read user settings. Instead of accessing the System Root just access the User Root writing:
ServiceReference serviceref = context.getServiceReference(PreferencesService.class.getName());
if (serviceref != null)
{
PreferencesService preferences = (PreferencesService) context.getService(serviceref);
//retrieve the 'installation' node under the system root
Preferences installationPreferences = preferences.getUserPreferences("John");
}
Need more OSGi articles and tutorial? Check the OSGi Recipes section
If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.


Ok that’s cool. Now, what if I want those preferences to be stored on a server? Do I need my own implementation of the service or can I leverage OSGi Remote Services?
RP
I don’t know of any implementation of the Preferences Service storing configuration in the database.
Well but how it’s connected to Configuration Admin Service from compendium services spec? I guess it addresses the same problem.
Hi Andrew, yes, I agree that Configuration Admin and Preferences Service have some overlap and that might lead to some confusion.
However, as far as I understand, they have slightly different goals. The Preferences Service is a tool that developers can use to store temporary data or the status of the application; such data are not fundamental for the application, that must be able to recover in case they’re missing or lost; furthermore, data are not meant to be changed by the final user of the application, as they are of exclusive internal use.
On the other side, the Configuration Admin service is the tool to manage configurations; as such, users are expected to explicitly provide this configurations (as property files, or via a management console), and these configurations are sent to the application that relies on them to work correctly.
Thanks for the explanation, that makes sense.