Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Magic with Merlin: Working with preferences

JSR 10, the Preferences API Specification, allows for the manipulation of preference and configuration data

John Zukowski (jaz@zukowski.net), President, JZ Ventures, Inc.
Author photo
John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and serves as the resident guru for a number of jGuru's community-driven Java FAQs. His latest books are Java Collections and Definitive Guide to Swing for Java 2 (2nd ed) from Apress. Reach him at jaz@zukowski.net.

Summary:  The addition of the java.util.prefs package to Java 1.4 (through JSR 10) lets you manipulate user preference data and configuration data by providing you with access to an implementation-specific registry (for example, the Windows Registry on Windows platforms). In this installment of Magic with Merlin, John Zukowski introduces you to the Preferences class and walks you through its use. He puts it all together with a sample program.

View more content in this series

Date:  01 Oct 2001
Level:  Introductory
Also available in:   Japanese

Activity:  8438 views
Comments:  

Have you ever needed to save configuration data for your program but didn't know where to store the data? While you can use property files or resource bundles for this information, the Java platform has never specified a standard place to store the files. That's all changed with JSR 10, which provides for the addition of the java.util.prefs package to the Java 1.4 API. The storage mechanism is an implementation-specific detail, but something that the programmer doesn't need to know or worry about. For Windows platforms, this location is the Windows Registry. You don't have free rein in the Registry, but you do have access from a common root node for all your applications.

Getting started

The aptly named Preferences class provides the basic framework for working with preferences. The class provides a series of static and abstract methods to work with one of the two sets of preferences: one for user preferences and one for system preferences. Using the static methods, you get a platform-specific implementation, like the WindowsPreferences class; then you can use the abstract methods implemented by that platform-specific implementation to do the work.

It's good practice to group a program's preferences by package to avoid naming conflicts with other applications. When you ask for a Preferences object, you simply pass along the package name. In the case of a non-static method, you can pass a reference to yourself (this), and the program will determine the package for you, as shown in Listing 1.


Listing 1. Fetching a Preferences object from non-static method
Preferences userPrefs = Preferences.userNodeForPackage(this);
Preferences sysPrefs = Preferences.systemNodeForPackage(this);

If, however, you're in a static method, you have to get the root node and provide the package yourself, as shown in Listing 2.


Listing 2. Fetching Preferences object from static method
Preferences userPrefs = Preferences.userRoot().node("/net/zukowski/ibm");
Preferences sysPrefs = Preferences.systemRoot().node("/net/zukowski/ibm");

After you have the node to work with, you can set, get, remove, and dump settings at your leisure. Just think of the Preferences object as one big key-value hashtable that structures the keys in a tree-like structure. It is not part of the Collections Framework, though (for more on the Collections Framework, see Resources).


Writing data

We'll begin by looking at how to store preferences. The Preferences class provides a series of put() methods, shown below, for storing values. In addition to basic string support, you can store booleans, doubles, floats, integers, longs, and byte arrays (think serialization). The helper methods take the appropriate data type and do the necessary conversions to store the data as a string.

  • put(String key, String value)
  • putBoolean(String key, boolean value)
  • putByteArray(String key, byte value[])
  • putDouble(String key, double value)
  • putFloat(String key, float value)
  • putInt(String key, int value)
  • putLong(String key, long value)

All the put() methods return a void. If the storage mechanism is unavailable, a BackingStoreException will be thrown.

Note: The key for a specific preference is limited to a length of Preferences.MAX_KEY_LENGTH (80) characters, while values are limited to Preferences.MAX_VALUE_LENGTH (8192) characters.


Reading data

Getting specific preferences is done through a series of get() methods, shown below. Like writing, there is a different method for each of the supported data types. One difference with getting, though, is that you must provide a default value in the event that the backing store is unavailable, or for when something hasn't been saved yet. This requirement ensures at least reasonable default settings for your program.

  • get(String key, String default)
  • getBoolean(String key, boolean default)
  • getByteArray(String key, byte default[])
  • getDouble(String key, double default)
  • getFloat(String key, float default)
  • getInt(String key, int default)
  • getLong(String key, long default)

If you're not sure of the preference names, you can find a list of the keys associated with a node with the keys() method. This method returns a String[] of nodes. Besides getting and storing individual preferences and getting a list of keys, you can also remove nodes and values with clear(), remove(), and removeNode().


Dumping data

If you want to save and restore preferences outside of the system-provided backing storage, you can do so in an XML-formatted document. You can either export a node with exportNode() or a whole subtree with exportSubtree(). The information is stored in UTF-8 format. Then, when you want to restore the information, use the importPreferences() method.


Listening in

Curiosity may have killed the cat, but if you are interested in finding out when preferences change, you can register a NodeChangeListener or PreferenceChangeListener with little concern to your immediate health. The NodeChangeListener works to notify you when nodes are added and removed, while the PreferenceChangeListener tells you of value changes. These follow the basic JavaBeans component event handling structure with add/removeNodeChangeListener(NodeChangeListener) and add/removePreferenceChangeListener() methods. Basically, you implement the listener, then register the listener, and you'll find about future changes.


Complete example

That's really all there is to it. Listing 3 provides a complete example for you to try out the new capabilities (also available for download from Resources). The program cleans up after itself, so if you want to find the values in the registry, comment out the cleanup code at the end.


Listing 3. Complete example
package net.zukowski.ibm;

import java.io.*;
import java.util.prefs.*;

public class Prefs {
  public static void main(String args[]) {
    String denominations[] = 
      {"One", "Two", "Five", "Ten", "Twenty"};
    String pictures[] = 
      {"Washington", "Jefferson", "Lincoln", "Hamilton", "Jackson"};

    NodeChangeListener nodeChangeListener = 
      new NodeChangeListener() {
        public void childAdded(NodeChangeEvent event) {
          Preferences parent = event.getParent();
          Preferences child  = event.getChild();
          System.out.println(parent.name() + " has a new child " +
            child.name());
        }
        public void childRemoved(NodeChangeEvent event) {
          Preferences parent = event.getParent();
          Preferences child  = event.getChild();
          System.out.println(parent.name() + " lost a child " +
            child.name());
        }
      };

    PreferenceChangeListener preferenceChangeListener = 
      new PreferenceChangeListener() {
        public void preferenceChange(PreferenceChangeEvent event) {
          String key = event.getKey();
          String value = event.getNewValue();
          Preferences node = event.getNode();
          System.out.println(node.name() + " now has a value of " + 
            value + " for " + key);
        }
      };

    // Look up user root
    Preferences prefs = 
      Preferences.userRoot().node("/net/zukowski/ibm");

    // Add listeners
    prefs.addNodeChangeListener(nodeChangeListener);
    prefs.addPreferenceChangeListener(preferenceChangeListener);

    // Save a bunch of key-value pairs
    for (int i=0, n=denominations.length; i < n; i++) {
      prefs.put(denominations[i], pictures[i]);
    }

    // Display all the entries
    try {
      String keys[] = prefs.keys();
      for (int i=0, n=keys.length; i < n; i++) {
        System.out.println(keys[i] + ": " + prefs.get(keys[i], "Unknown"));
      }
    } catch (BackingStoreException e) {
      System.err.println("Unable to read backing store: " + e);
    }

    // Create child
    Preferences child = Preferences.userRoot().node("/net/zukowski/ibm/foo");

    // Save to XML file
    try {
      FileOutputStream fos = new FileOutputStream("prefs.out");
      prefs.exportNode(fos);
    } catch (Exception e) {
      System.err.println("Unable to export nodes: " + e);
    }

    // Clean up
    try {
      prefs.removeNode();
    } catch (BackingStoreException e) {
      System.err.println("Unable to access backing store: " + e);
    }

  }
}



Download

DescriptionNameSizeDownload method
Sample codej-prefs.zip1 KB HTTP

Information about download methods


Resources

About the author

Author photo

John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and serves as the resident guru for a number of jGuru's community-driven Java FAQs. His latest books are Java Collections and Definitive Guide to Swing for Java 2 (2nd ed) from Apress. Reach him at jaz@zukowski.net.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=10593
ArticleTitle=Magic with Merlin: Working with preferences
publish-date=10012001
author1-email=jaz@zukowski.net
author1-email-cc=jaloi@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers