X

Geertjan's Blog

  • January 22, 2011

Loosely Coupled Refresh

Geertjan Wielenga
Product Manager
You have a viewer window in one module, an editor window in a different module. When changes are saved in the editor window, the viewer window needs to be refreshed, presenting the updated data.

But we do not want the two modules to have any knowledge about each other, hence no dependency should be set in the editor module on the viewer module. The viewer module contains the "refresh" action, which the editor module needs to have access to.

Different solutions are available for this problem. On the mailing list, Ernest Lotter suggests creating a third module providing all database related code. That third module would have the save/refresh functionality. Edvin Syse suggests the same idea of a third module, with the firing of PropertyChangeEvents on a shared service. Timon Veenstra also suggests a third module, together with an event bus solution.

My solution is different and much simpler. No need for a third module at all. Though I like the idea of putting all database related code into a single module, i.e., isolating database code into a dedicated module.

However, this is my solution, very simple:

  1. In the editor window, at the end of your SaveCookie implementation, include this statement:
    NbPreferences.forModule(NbPreferences.class).putBoolean("refreshable", true);

    So, now, whenever you save the editor window, a property named "refreshable" is set to true. The property is found in a file within the Preferences folder in the user directory, which is available to all modules in the application.

  2. In the viewer window's constructor, include this:
    Preferences pref = NbPreferences.forModule(NbPreferences.class);
    pref.addPreferenceChangeListener(new PreferenceChangeListener() {
    @Override
    public void preferenceChange(PreferenceChangeEvent evt) {
    if (evt.getKey().equals("refreshable") && evt.getNewValue().equals("true")) {
    //call your refresh code here and then change the preference to false:
    NbPreferences.forModule(NbPreferences.class).putBoolean("refreshable", false);
    }
    }
    });

That's all. Works perfectly. And I can now remove the dependency in the editor module on the viewer module.

Join the discussion

Comments ( 6 )
  • Jesse Glick Saturday, January 22, 2011

    "NbPreferences.forModule(NbPreferences.class)" - don't do this! You are polluting the namespace of the org.openide.util module. Pick a class from a module which is a shared dep of the editor and viewer modules. Or use NbPreferences.root().node("com/mycom/mydomain/whatever") to prevent namespace clashes.


  • Geertjan Wielenga Saturday, January 22, 2011

    Right, that makes sense. I think the NbPreferences.root() would be better.


  • Oliver Rettig Monday, January 24, 2011

    I like your solution, because it eliminates the need of a third module. But on the other side it produces the risk that if somebody wants to add an additional view, it becomes unclear how the refresh works. There is specific documentation of this mechanism needed. Instead the solution with the third module does not need this documentation. If somebody wants to add a new view he will easy find that the existing view depends on the third module ...

    Preferences are not expected to be used for events.


  • Geertjan Wielenga Monday, January 24, 2011

    What do you mean, "preferences are not meant to be used for events"? If that's the case, then what's the point of the PreferenceChangeListener?


  • Oliver Rettig Monday, January 24, 2011

    Ok, excuse my unclear comment. I use the Preferences API only for key-value-pairs where the value is more than only a flag which often changes and where it makes sense that the value is also saved. But maybe others has not my expections to the preferences.


  • Jesse Glick Monday, January 24, 2011

    Oliver is right that using NbPreferences in this way is not really good style; usually only a single piece of code should read and write a given preferences node (or subtree). It is clearer and more direct to produce a third API module that exposes listenable state via a regular Java API; that third module might choose to also persist the state using NbPreferences, but should avoid documenting the key lest someone rely on it improperly.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.