Support free tutorials:











vogella training Training Books



Eclipse Preferences - Tutorial

Lars Vogel

Version 2.1

12.07.2013

Revision History
Revision 0.1 25.06.2009 Lars
Vogel
Created
Revision 0.2 - 2.1 15.09.2010 - 12.07.2013 Lars
Vogel
bug fixes and enhancements

Eclipse Preferences

This article describes the usage of Eclipse preferences and preference pages. Within this tutorial Eclipse 4.3 (Kepler) is used.


Table of Contents

1. Eclipse Preferences
1.1. Preferences and scopes
1.2. Storage of the preferences
1.3. Eclipse preference API
2. Persisting data with dependency injection
3. Preference handling in Eclipse 3.x
3.1. Preference Page
3.2. Secure storage of preferences
3.3. Access Preferences in different plug-ins
3.4. Reacting to changes in the preferences
4. Persistence of part state
5. Assumptions
6. Setting preferences via plugin_customization.ini
7. Tutorial: Preferences via code
8. Exercise: Contribute preference page to the Eclipse IDE
9. Tutorial: Secure storage of preferences
10. Support this website
10.1. Thank you
10.2. Questions and Discussion
11. Links and Literature
11.1. Source Code
11.2. vogella Resources

1. Eclipse Preferences

1.1. Preferences and scopes

The Eclipse platform supports preferences for persisting data between application restarts. Preferences are stored as key / value pairs. The key is an arbitrary String. The value can be a boolean, String, int or another primitive type. For example the user key may point to the value vogella.

The preference support in Eclipse is based on the Preferences class from the org.osgi.service.prefs package. Eclipse preferences are very similar to standard Java Preferences but use the Eclipse framework to save and retrieve the configuration and support scopes.

The scope defines how the preference data is stored and how it is changeable. The Eclipse runtime defines three scopes. The different scopes are explained in the following table.

Table 1. Eclipse Preference scope

Scope Description
Instance scope If the user runs the same program twice, the settings between the two programs may be different.
Configuration scope If the user runs the same program twice, then the settings between the two programs are identical.
Default scope Default values which can not be changed. Supplied via configuration files in plug-ins and product definitions.


1.2. Storage of the preferences

Eclipse stores the preferences in the workspace of your application in the .metadata/.plugins/org.eclipse.core.runtime/.settings/ directory in the <nodePath>.prefs file.

The <nodePath> is by default the Bundle-SymbolicName of the plug-in but can be specified via the preference API. The workspace is by default the directory in which the application starts.

You can configure the storage location of the preferences via the -data path launch parameter in Eclipse. To place the preferences in the user home directory use the -data @user.home parameter setting.

1.3. Eclipse preference API

You can create and manipulate preferences directly via Singletons provided by the Eclipse runtime. You have the InstanceScope, ConfigurationScope and DefaultScope classes which give access to the corresponding instance via the INSTANCE field.

Preference values are read and saved by get() and put() methods. In the get() method you specify a default value in case the key can not be found. The clear() method removes all preferences and the remove() method allows you to delete a selected preference value. Via the flush() method you persist the preferences to the file system.

// We access the instanceScope 
Preferences preferences = InstanceScope.INSTANCE
  .getNode("com.vogella.eclipse.preferences.test");

Preferences sub1 = preferences.node("node1");
Preferences sub2 = preferences.node("node2");
sub1.put("h1", "Hello");
sub1.put("h2", "Hello again");
sub2.put("h1", "Moin");
try {
  // forces the application to save the preferences
  preferences.flush();
  } catch (BackingStoreException e) {
    e.printStackTrace();
  }
} 

// read values from the instance scope
Preferences preferences = InstanceScope.INSTANCE
  .getNode("com.vogella.eclipse.preferences.test");
Preferences sub1 = preferences.node("node1");
Preferences sub2 = preferences.node("node2");
sub1.get("h1", "default");
sub1.get("h2", "default");
sub2.get("h1", "default"); 

2. Persisting data with dependency injection

The Eclipse platform allows you to use dependency injection for preferences handling.

Preference values are not stored directly in the IEclipseContext but contributed by an ExtendedObjectSupplier. This implies that you have to use a special annotation @Preference to access them. The @Preference must be used together with @Inject or one of the other annotations which implies dependency injection, e.g. @Execute.

The @Preference annotation allows you to specify the nodePath and the value as optional parameters.

The nodePath is the file name used to save the preference values to disk. By default this is the Bundle-SymbolicName of the plug-in. The value parameter specifies the preference key for the value which should be injected.

Eclipse can also inject the IEclipsePreference object. You can use this object for storing values. If you use the value parameter, Eclipse injects the value directly. Use the value parameter for read access, while for storing or changing values, use the IEclipsePreference object.

Warning

For accessing the IEclipsePreference object you still have to use the @Preference annotation. @Inject alone is not sufficient.

The following code snippet demonstrates how to put values into the preferences store.

// get IEclipsePreferences injected to change a value
@Execute
public void execute
  (@Preference(nodePath = "com.example.e4.rcp.todo") IEclipsePreferences prefs) {
  // more stuff...
  prefs.put("user", "TestUser");
  prefs.put("password", "Password");
  // Persists
  try {
  prefs.flush();
    } catch (BackingStoreException e) {
      e.printStackTrace();
    }
} 

The next snippet demonstrates the read access of preference values.

@Inject
@Optional
public void trackUserSettings
  (@Preference(nodePath = "com.example.e4.rcp.todo", 
  value = "user") 
  String user) {
  System.out.println("New user: " + user);
}
  
@Inject
@Optional
public void trackPasswordSettings
    (@Preference(nodePath = "com.example.e4.rcp.todo", 
  value = "password") 
  String password) {
  System.out.println("New password: " + password);
} 

The Eclipse platform automatically tracks the values and re-injects them into fields and methods if they change. Eclipse tracks changes of preferences in the InstanceScope and ConfigurationScope scope. Preference values in the DefaultScope are not tracked.

If you use the injected IEclipseContext to store new preference values, these values are stored in the instance scope.

3. Preference handling in Eclipse 3.x

3.1. Preference Page

Eclipse 3.x provides a standard user interface to display and change preference values via a preference dialog.

To add a page to this preference dialog a plug-in must provide an contribution to the org.eclipse.ui.preferencePages extension point.

This extension point defines a class which is responsible for creating a user interface and storing the preference values. This class must implement IWorkbenchPreferencePage and must have a non-parameter constructor.

The PreferencePage class or one of its subclasses can get extended; a good template is usually FieldEditorPreferencePage.

To open the Preference dialog, you can use the org.eclipse.ui.window.preferences command.

3.2. Secure storage of preferences

Eclipse allows to encrypt preference values via the org.eclipse.equinox.security plug-in.

The key / value pairs will be stored in the secure.storage file in the .eclipse/org.eclipse.equinox.security folder of the users home directory. Eclipse uses a class of type PasswordProvider for encrypting the preferences and has a default class registered.

Via the org.eclipse.equinox.security.secureStorage extension point you can register your own PasswordProvider.

3.3. Access Preferences in different plug-ins

You can access preferences in other plug-ins via the PreferenceService service.

For example, to access the "MySTRING1" preference in the "de.vogella.preferences.page" plug-in, you can use the following:

String text = Platform.getPreferencesService().
  getString("de.vogella.preferences.page", "MySTRING1", "hello", null); 

3.4. Reacting to changes in the preferences

You can register IPropertyChangeListener instances to changes in the preference values. These listener are called by the Eclipse framework if the reference value changes.

Activator.getDefault().getPreferenceStore()
  .addPropertyChangeListener(new IPropertyChangeListener() {
    @Override
    public void propertyChange(PropertyChangeEvent event) {
      if (event.getProperty() == "MySTRING1") {
        String value = event.getNewValue().toString()
        // do something with the new value
      }
    }
  }); 

4. Persistence of part state

Eclipse provides the @PersistState annotation. This annotation can be applied to a method in a class referred to by a part.

Such an annotated method can be used to store the instance state of the part. The Eclipse framework calls such a method whenever the part or the application closes. The stored information can be used in the method annotated with the @PostConstruct annotation. A typical use case for such a method would be to store the state of a checkbox.

The usage of this annotation is demonstrated in the following example code.

@PostConstruct
public void createControl(MPart part) {
  Map<String, String> state = part.getPersistedState();
  String value = state.get("key");
  ...
}

@PersistState
public void persistState(MPart part) {
  Map<String, String> state = part.getPersistedState();
  state.put("key", "newValue");
  ...
} 

5. Assumptions

The following assumes that you know how to create simple Eclipse RCP applications and that you know how to create commands and add them to the menu. If not please have a look at the Eclipse RCP and Eclipse Commands tutorial .

6. Setting preferences via plugin_customization.ini

You can use a file to set the default values of preferences. The file which contains these defaults is typically named plugin_customization.ini.

Such a file needs to be registered via the preferenceCustomization property on the product extension point in the plugin.xml file. This is demonstrated in the following screenshot.

Referring to the plugin_customization.ini file in the product extension

The format to use is <plugin id>/<setting>=<value>, e.g. com.example.e4.rcp.todo/user=vogella.

Tip

To find the correct keys, just start your Eclipse application, switch to the .metadata directory in your workspace directory (by default the directory your application is starting in) and search for files ending with .pref.

7. Tutorial: Preferences via code

You can create, store and retrieve preference values directly via your coding. The following gives an example for this. Create an Eclipse composite with three buttons. Use this composite in one of your parts (View or Editor).

The first Button will set the preference values. The next will display the values and the last will clear the preference values.

package de.vogella.preferences.test.ui;

import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

public class ButtonComposite extends Composite {

  public ButtonComposite(Composite parent, int style) {
    super(parent, style);
    Button write = new Button(parent, SWT.PUSH);
    write.setText("Write");
    write.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {

        Preferences preferences = ConfigurationScope.INSTANCE
            .getNode("de.vogella.preferences.test");
        Preferences sub1 = preferences.node("node1");
        Preferences sub2 = preferences.node("node2");
        sub1.put("h1", "Hello");
        sub1.put("h2", "Hello again");
        sub2.put("h1", "Moin");

        try {
          // forces the application to save the preferences
          preferences.flush();
        } catch (BackingStoreException e2) {
          e2.printStackTrace();
        }
      }
    });
    Button read = new Button(parent, SWT.PUSH);
    read.setText("Read");
    read.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        Preferences preferences = ConfigurationScope.INSTANCE
            .getNode("de.vogella.preferences.test");
        Preferences sub1 = preferences.node("node1");
        Preferences sub2 = preferences.node("node2");
        System.out.println(sub1.get("h1", "default"));
        System.out.println(sub1.get("h2", "default"));
        System.out.println(sub2.get("h1", "default"));

      }
    });

    Button clear = new Button(parent, SWT.PUSH);
    clear.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        Preferences preferences = ConfigurationScope.INSTANCE
            .getNode("de.vogella.preferences.test");
        Preferences sub1 = preferences.node("node1");
        Preferences sub2 = preferences.node("node2");
        // Delete the existing settings
        try {
          sub1.clear();
          sub2.clear();
          preferences.flush();
        } catch (BackingStoreException e1) {
          e1.printStackTrace();
        }
      }
    });
    clear.setText("clear");
  }
} 

Run and test your program.

8. Exercise: Contribute preference page to the Eclipse IDE

In the following exercise you create a plug-in with a preference pages which allows the user to maintain certain settings. This exercise assumes that you are already familiar with Eclipse plug-in development for the Eclipse IDE.

Create a new plug-in project called de.vogella.preferences.page. Make sure you flag the "Generate an activator..." during the project creation. Use no template.

Go to the plugin.xml file and add the extension org.eclipse.ui.preferencePages with the following settings.

Enter the following code for your class MyPreferencePage1. Method init() sets the preferences store and the method createFieldEditors() registers pre-defined editors for values. checkState() allows to perform a validations. To get notified about value changes you need to override the propertyChange method.

package de.vogella.preferences.page.preferencepage;

import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.DirectoryFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import de.vogella.preferences.page.Activator;

public class MyPreferencePage1 extends FieldEditorPreferencePage implements
    IWorkbenchPreferencePage {

  public MyPreferencePage1() {
    super(GRID);

  }

  public void createFieldEditors() {
    addField(new DirectoryFieldEditor("PATH", "&Directory preference:",
        getFieldEditorParent()));
    addField(new BooleanFieldEditor("BOOLEAN_VALUE",
        "&An example of a boolean preference", getFieldEditorParent()));

    addField(new RadioGroupFieldEditor("CHOICE",
        "An example of a multiple-choice preference", 1,
        new String[][] { { "&Choice 1", "choice1" },
            { "C&hoice 2", "choice2" } }, getFieldEditorParent()));
    addField(new StringFieldEditor("MySTRING1", "A &text preference:",
        getFieldEditorParent()));
    addField(new StringFieldEditor("MySTRING2", "A &text preference:",
        getFieldEditorParent()));
  }

  @Override
  public void init(IWorkbench workbench) {
    setPreferenceStore(Activator.getDefault().getPreferenceStore());
    setDescription("A demonstration of a preference page implementation");
  }
} 

Start a runtime Eclipse IDE with your plug-in and ensure that you see your preference page in the preference settings of the Eclipse IDE. Validate that maintained values are stored even if you restart your application.

Add a command showPreferenceValues with the following handler to the menu. This command demonstrates how to access preferences values from the preferencePage.

package de.vogella.preferences.page.handler;

import org.eclipse.core.commands.AbstractHandler;

public class ShowPreferenceValues extends AbstractHandler {

  @Override
  public Object execute(ExecutionEvent event) throws ExecutionException {
    Shell shell = HandlerUtil.getActiveWorkbenchWindowChecked(event)
        .getShell();
    String myPrefString = Activator.getDefault().getPreferenceStore()
        .getString("MySTRING1");
    MessageDialog.openInformation(shell, "Info", myPrefString);
    Boolean myPrefBoolean = Activator.getDefault().getPreferenceStore()
        .getBoolean("BOOLEAN_VALUE");
    // RadioGroupFieldEditor can get access
    String choice = Activator.getDefault().getPreferenceStore().getString("CHOICE");
    System.out.println(choice);
    MessageDialog.openInformation(shell, "Info", myPrefBoolean.toString());
    // I assume you get the rest by yourself
    return null;
  }

} 

To set the default values for preferences use the extension point org.eclipse.core.runtime.preferences. Create a new initializer with the following class de.vogella.preferences.page.preferencepage.MyInitializer.

package de.vogella.preferences.page.preferencepage;

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;

import de.vogella.preferences.page.Activator;

public class MyInitializer extends AbstractPreferenceInitializer {

  public MyInitializer() {
  }

  @Override
  public void initializeDefaultPreferences() {
    IPreferenceStore store = Activator.getDefault().getPreferenceStore();
    store.setDefault("MySTRING1", "http://www.vogella.com");
  }

} 

Finally create a new view to show one of the preference values. Also register a PropertyChangeListener to the preferences store to get informed in case the preference settings change.

package de.vogella.preferences.page;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {

  private Label label;

  public void createPartControl(Composite parent) {
    IPreferenceStore preferenceStore = Activator.getDefault()
        .getPreferenceStore();
    String string = preferenceStore.getString("MySTRING1");

    label = new Label(parent, SWT.NONE);
    label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false,
        false));
    label.setText(string);
    // add change listener to the preferences store so that we are notified
    // in case of changes
    Activator.getDefault().getPreferenceStore()
        .addPropertyChangeListener(new IPropertyChangeListener() {
          @Override
          public void propertyChange(PropertyChangeEvent event) {
            if (event.getProperty() == "MySTRING1") {
              label.setText(event.getNewValue().toString());
            }
          }
        });
  }

  public void setFocus() {
  }
} 

9. Tutorial: Secure storage of preferences

To test the secure storage of preferences create the project de.vogella.preferences.security with a view and add the org.eclipse.equinox.security plug-in as a dependency to it.

Change the code of your view to the following.

package de.vogella.preferences.security;

import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
import org.eclipse.equinox.security.storage.StorageException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
  public void createPartControl(Composite parent) {
    Button buttonPut = new Button(parent, SWT.PUSH);
    buttonPut.setText("Save values");
    buttonPut.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        ISecurePreferences preferences = SecurePreferencesFactory
            .getDefault();
        ISecurePreferences node = preferences.node("info");
        try {
          node.put("user", "vogella", true);
          node.put("password", "123", true);
        } catch (StorageException e1) {
          e1.printStackTrace();
        }
      }
    });
    Button buttonGet = new Button(parent, SWT.PUSH);
    buttonGet.setText("Get values");
    buttonGet.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        ISecurePreferences preferences = SecurePreferencesFactory
            .getDefault();
        if (preferences.nodeExists("info")) {
          ISecurePreferences node = preferences.node("info");
          try {
            String user = node.get("user", "n/a");
            String password = node.get("password", "n/a");
            System.out.println(user);
            System.out.println(password);
          } catch (StorageException e1) {
            e1.printStackTrace();
          }
        }
      }
    });

  }

  
/** * Passing the focus request to the viewer's control. */
public void setFocus() { } }

10. Support this website

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

10.1. Thank you

Please consider a contribution if this article helped you.

Flattr this

10.2. Questions and Discussion

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

11. Links and Literature

11.1. Source Code

Source Code of Examples

11.2. vogella Resources

vogella Training Android and Eclipse Training from the vogella team

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java, compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put all your files in a distributed version control system