This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/master by this push:
     new ea47c9bfb Modeler Preferences refactoring
ea47c9bfb is described below

commit ea47c9bfb9c152f74d5bb9fa7813e15916307613
Author: Andrus Adamchik <[email protected]>
AuthorDate: Tue May 19 20:16:01 2026 -0400

    Modeler Preferences refactoring
    
    ... pulling prefs locator that should be emulated by the MCP server
    out of the prefs repository that has a lot of MOdeler lifecycle logic
---
 .../org/apache/cayenne/modeler/Application.java    |  31 +++--
 .../cayenne/modeler/NameGeneratorPreferences.java  |   2 +-
 .../cayenne/modeler/mcp/McpHandshakeWriter.java    |  19 +--
 .../cayenne/modeler/pref/ClasspathPrefs.java       |   4 +-
 .../cayenne/modeler/pref/DBConnectorPrefs.java     |   4 +-
 .../apache/cayenne/modeler/pref/DataMapPrefs.java  |   2 +-
 .../apache/cayenne/modeler/pref/DataNodePrefs.java |   4 +-
 .../apache/cayenne/modeler/pref/GeneralPrefs.java  |   4 +-
 .../cayenne/modeler/pref/PreferenceMigration.java  |   4 +-
 .../apache/cayenne/modeler/pref/PrefsLocator.java  | 100 ++++++++++++++
 ...erencesRepository.java => PrefsRepository.java} | 152 +++++++++------------
 .../cayenne/modeler/pref/RecentProjectsPrefs.java  |   4 +-
 .../migration/toV5/_1_DbConnectorsMigration.java   |   6 +-
 .../pref/migration/toV5/_2_ClasspathMigration.java |   6 +-
 .../migration/toV5/_3_GeneralPrefsMigration.java   |   6 +-
 .../migration/toV5/_4_RecentProjectsMigration.java |   6 +-
 .../migration/toV5/_5_FrameGeometryMigration.java  |   6 +-
 .../toV5/_6_ProjectSplitPaneMigration.java         |   6 +-
 .../toV5/_7_EntityTablePrefsMigration.java         |  10 +-
 .../cayenne/modeler/project/ProjectPrefs.java      |   4 +-
 .../cayenne/modeler/project/ProjectSession.java    |   8 +-
 .../component/CMComponentGeometryPrefs.java        |   6 +-
 .../toolkit/filechooser/CMFileChooserPrefs.java    |   6 +-
 .../toolkit/splitpane/CMSplitPanePrefs.java        |   6 +-
 .../modeler/toolkit/table/CMTablePrefs.java        |   6 +-
 .../org/apache/cayenne/modeler/ui/MainFrame.java   |  14 +-
 .../org/apache/cayenne/modeler/ui/MainMenuBar.java |   2 +-
 .../modeler/ui/action/DBConnectionAwareAction.java |   2 +-
 .../modeler/ui/action/ImportDataMapAction.java     |   2 +-
 .../modeler/ui/action/ImportEOModelAction.java     |   2 +-
 .../cayenne/modeler/ui/action/ProjectOpener.java   |   2 +-
 .../cayenne/modeler/ui/action/SaveAsAction.java    |   4 +-
 .../modeler/ui/action/ShowLogConsoleAction.java    |   2 +-
 .../ui/confirmremove/ConfirmRemoveDialog.java      |   4 +-
 .../modeler/ui/datasource/DataSourceDialog.java    |   8 +-
 .../modeler/ui/dbgen/DBGeneratorOptionsDialog.java |   2 +-
 .../cayenne/modeler/ui/dbgen/DBGeneratorPrefs.java |   4 +-
 .../ui/dbrelationship/DbRelationshipDialog.java    |   2 +-
 .../cayenne/modeler/ui/logconsole/LogConsole.java  |   4 +-
 .../modeler/ui/logconsole/LogConsolePrefs.java     |   6 +-
 .../preferences/classpath/ClasspathPrefsPanel.java |   6 +-
 .../ui/preferences/general/GeneralPrefsPanel.java  |   4 +-
 .../ui/preferences/more/MorePrefsPanel.java        |   6 +-
 .../cayenne/modeler/ui/project/ProjectView.java    |   2 +-
 .../editor/datadomain/cgen/DataDomainCgenTab.java  |   2 +-
 .../editor/datadomain/main/DataDomainMainView.java |   2 +-
 .../ui/project/editor/datamap/cgen/CgenPanel.java  |   2 +-
 .../cgen/templateeditor/TemplateEditor.java        |   4 +-
 .../editor/datamap/main/DataMapMainView.java       |   4 +-
 .../editor/datanode/DataNodeEditorPanel.java       |   4 +-
 .../editor/datanode/jdbc/JDBCDataSourcePanel.java  |   2 +-
 .../dbentity/properties/DbAttributePanel.java      |   2 +-
 .../properties/DbEntityPropertiesView.java         |   2 +-
 .../dbentity/properties/DbRelationshipPanel.java   |   2 +-
 .../attributes/EmbeddableAttributesView.java       |   2 +-
 .../objentity/attrinfo/ObjAttributeInfoDialog.java |   2 +-
 .../callbacks/ObjEntityCallbacksView.java          |   4 +-
 .../objentity/properties/ObjAttributePanel.java    |   2 +-
 .../properties/ObjEntityPropertiesView.java        |   2 +-
 .../objentity/properties/ObjRelationshipPanel.java |   2 +-
 .../editor/procedure/ProcedureParameterTab.java    |   2 +-
 .../query/selectquery/SelectQueryOrderingTab.java  |   2 +-
 .../query/sqltemplate/SQLTemplatePrefetchTab.java  |   2 +-
 .../cayenne/modeler/ui/welcome/WelcomeScreen.java  |   2 +-
 .../modeler/mcp/McpHandshakeWriterTest.java        |  19 ++-
 65 files changed, 321 insertions(+), 236 deletions(-)

diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
index d68690917..f5c943c75 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
@@ -30,14 +30,15 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.modeler.dbconnector.DBConnectors;
 import org.apache.cayenne.modeler.log.ModelerLogFactory;
+import org.apache.cayenne.modeler.platform.UIInitializer;
 import org.apache.cayenne.modeler.pref.ClasspathPrefs;
 import org.apache.cayenne.modeler.pref.DBConnectorPrefs;
 import org.apache.cayenne.modeler.pref.GeneralPrefs;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 import org.apache.cayenne.modeler.pref.RecentProjectsPrefs;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
 import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
-import org.apache.cayenne.modeler.platform.UIInitializer;
 import 
org.apache.cayenne.modeler.service.validator.ConfigurableProjectValidator;
 import org.apache.cayenne.modeler.ui.MainFrame;
 import org.apache.cayenne.modeler.ui.action.OpenProjectAction;
@@ -88,7 +89,8 @@ public class Application {
     private final Injector injector;
     private final UIInitializer platformInit;
     private final ModelerClassLoader classLoader;
-    private final PreferencesRepository preferencesRepository;
+    private final PrefsLocator prefsLocator;
+    private final PrefsRepository prefsRepository;
     private final ProjectValidator projectValidator;
     private final CliArgs cli;
     private GlobalActions actionManager;
@@ -103,7 +105,8 @@ public class Application {
         this.cli = cli;
 
         this.classLoader = new ModelerClassLoader();
-        this.preferencesRepository = new 
PreferencesRepository(injector.getInstance(ConfigurationNameMapper.class));
+        this.prefsLocator = new PrefsLocator();
+        this.prefsRepository = new 
PrefsRepository(injector.getInstance(ConfigurationNameMapper.class), 
prefsLocator);
         this.projectValidator = new ConfigurableProjectValidator(this);
     }
 
@@ -182,9 +185,9 @@ public class Application {
         this.logConsole = new LogConsole(this);
         ModelerLogFactory.setAppender(logConsole);
 
-        getPreferencesRepository().runMigrations();
+        getPrefsRepository().runMigrations();
 
-        this.dbConnectors = new 
DBConnectorPrefs(getPreferencesRepository()).getConnectors();
+        this.dbConnectors = new DBConnectorPrefs(prefsLocator).getConnectors();
 
         refreshClassLoader();
 
@@ -223,15 +226,19 @@ public class Application {
         return dbConnectors;
     }
 
-    public PreferencesRepository getPreferencesRepository() {
-        return preferencesRepository;
+    public PrefsRepository getPrefsRepository() {
+        return prefsRepository;
+    }
+
+    public PrefsLocator getPrefsLocator() {
+        return prefsLocator;
     }
 
     /**
      * Reinitializes ModelerClassLoader from preferences.
      */
     public void refreshClassLoader() {
-        List<String> values = new 
ClasspathPrefs(getPreferencesRepository()).getEntries();
+        List<String> values = new ClasspathPrefs(prefsLocator).getEntries();
         if (!values.isEmpty()) {
             
getClassLoader().setFiles(values.stream().map(File::new).collect(Collectors.toList()));
         }
@@ -239,10 +246,10 @@ public class Application {
 
     private File initialProjectFromPreferences() {
 
-        if (new GeneralPrefs(getPreferencesRepository()).isAutoLoadProject()) {
-            List<File> files = new 
RecentProjectsPrefs(getPreferencesRepository()).getFiles();
+        if (new GeneralPrefs(prefsLocator).isAutoLoadProject()) {
+            List<File> files = new 
RecentProjectsPrefs(prefsLocator).getFiles();
             if (!files.isEmpty()) {
-                return files.get(0);
+                return files.getFirst();
             }
         }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NameGeneratorPreferences.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NameGeneratorPreferences.java
index 759bf43a1..7d0fdac0c 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NameGeneratorPreferences.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/NameGeneratorPreferences.java
@@ -48,7 +48,7 @@ public class NameGeneratorPreferences {
     }
 
     Preferences getPreference(Application application) {
-        return 
application.getPreferencesRepository().projectPref(application.getFrame().getProjectSession().project(),
 null);
+        return 
application.getPrefsRepository().projectPref(application.getFrame().getProjectSession().project(),
 null);
     }
 
     /**
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriter.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriter.java
index 10d9547cc..3270ad53f 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriter.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriter.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.modeler.mcp;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,33 +31,25 @@ import java.util.prefs.Preferences;
  * Writes a "Modeler is up and the requested project is loaded" handshake 
entry into
  * {@link Preferences} under a nonce-scoped node. Used by the MCP server's 
{@code open_project}
  * tool to confirm the launch succeeded without polling {@code 
Process.isAlive()}.
- * <p>
- * Note the namespace: handshake entries live at {@code 
/org/apache/cayenne/modeler/mcp-handshake/...},
- * a sibling of the Modeler's regular {@code 
/org/apache/cayenne/modeler/v5/...} preferences tree.
  */
-public final class McpHandshakeWriter {
+public class McpHandshakeWriter {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(McpHandshakeWriter.class);
 
-    static final String NODE_PREFIX = 
"/org/apache/cayenne/modeler/mcp-handshake/";
-
-    private McpHandshakeWriter() {
-    }
-
     /**
      * Asynchronously writes the handshake. Returns immediately; the actual 
write happens
      * on a short-lived daemon thread so the EDT is not blocked by a slow 
preferences backend.
      */
-    public static void write(String nonce, String[] originalArgs, String 
resolvedProjectPath) {
-        Thread t = new Thread(() -> doWrite(nonce, originalArgs, 
resolvedProjectPath),
+    public static void write(PrefsLocator locator, String nonce, String[] 
originalArgs, String resolvedProjectPath) {
+        Thread t = new Thread(() -> doWrite(locator, nonce, originalArgs, 
resolvedProjectPath),
                 "mcp-handshake-writer");
         t.setDaemon(true);
         t.start();
     }
 
-    private static void doWrite(String nonce, String[] originalArgs, String 
resolvedProjectPath) {
+    private static void doWrite(PrefsLocator locator, String nonce, String[] 
originalArgs, String resolvedProjectPath) {
         try {
-            Preferences prefs = Preferences.userRoot().node(NODE_PREFIX + 
nonce);
+            Preferences prefs = locator.handshakeNode(nonce);
             prefs.put("startedAt", Instant.now().toString());
             prefs.putLong("pid", ProcessHandle.current().pid());
             prefs.put("args", originalArgs != null ? String.join(" ", 
originalArgs) : "");
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/ClasspathPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/ClasspathPrefs.java
index ebce558f7..c256fed4a 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/ClasspathPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/ClasspathPrefs.java
@@ -33,8 +33,8 @@ public final class ClasspathPrefs extends PreferenceAdapter {
 
     public static final String NODE = "classpath";
 
-    public ClasspathPrefs(PreferencesRepository repository) {
-        super(repository.appPref(NODE));
+    public ClasspathPrefs(PrefsLocator locator) {
+        super(locator.appNode(NODE));
     }
 
     // Returns classpath entries in numeric-key order. Defensive against any
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DBConnectorPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DBConnectorPrefs.java
index ce47a50db..9d700cb39 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DBConnectorPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DBConnectorPrefs.java
@@ -40,8 +40,8 @@ public class DBConnectorPrefs extends PreferenceAdapter {
     private static final String URL_PROPERTY = "url";
     private static final String USER_NAME_PROPERTY = "userName";
 
-    public DBConnectorPrefs(PreferencesRepository repository) {
-        super(repository.appPref(NODE));
+    public DBConnectorPrefs(PrefsLocator locator) {
+        super(locator.appNode(NODE));
     }
 
     public DBConnectors getConnectors() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataMapPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataMapPrefs.java
index a6bf7799d..8e48efb2f 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataMapPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataMapPrefs.java
@@ -26,7 +26,7 @@ public final class DataMapPrefs extends PreferenceAdapter {
     public static final String SUPERCLASS_PACKAGE_PROPERTY = 
"superclassPackage";
     public static final String DEFAULT_SUPERCLASS_PACKAGE_SUFFIX = "auto";
 
-    public DataMapPrefs(PreferencesRepository repository, DataMap dataMap) {
+    public DataMapPrefs(PrefsRepository repository, DataMap dataMap) {
         super(repository.dataMapPref(dataMap, null));
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataNodePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataNodePrefs.java
index d4122fbf0..649dd2f10 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataNodePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/DataNodePrefs.java
@@ -26,12 +26,12 @@ public final class DataNodePrefs extends PreferenceAdapter {
 
     static final String NODE = "dataNode";
 
-    private final PreferencesRepository repository;
+    private final PrefsRepository repository;
     private final Project project;
 
     private String localDataSource;
 
-    public DataNodePrefs(PreferencesRepository repository, Project project, 
String dataNodeName) {
+    public DataNodePrefs(PrefsRepository repository, Project project, String 
dataNodeName) {
         super(repository.projectPref(project, NODE + "/" + dataNodeName));
 
         // capture repo and project for the sake of "rename"
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/GeneralPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/GeneralPrefs.java
index 9cc7dbbf5..877b14bbd 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/GeneralPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/GeneralPrefs.java
@@ -28,8 +28,8 @@ public final class GeneralPrefs extends PreferenceAdapter {
     public static final String ENCODING = "encoding";
     public static final String FAVOURITE_DATA_SOURCE = "favouriteDataSource";
 
-    public GeneralPrefs(PreferencesRepository repository) {
-        super(repository.appPref(NODE));
+    public GeneralPrefs(PrefsLocator locator) {
+        super(locator.appNode(NODE));
     }
 
     public boolean isAutoLoadProject() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceMigration.java
index 793b01191..126aec70e 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceMigration.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.pref;
 
 /**
- * One-time data migration applied by {@link 
PreferencesRepository#runMigrations()}.
+ * One-time data migration applied by {@link PrefsRepository#runMigrations()}.
  */
 public interface PreferenceMigration {
 
@@ -30,5 +30,5 @@ public interface PreferenceMigration {
      */
     int version();
 
-    void apply(PreferencesRepository repo);
+    void apply(PrefsLocator locator);
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
new file mode 100644
index 000000000..0e35c4558
--- /dev/null
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
@@ -0,0 +1,100 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.modeler.pref;
+
+import java.util.prefs.Preferences;
+
+/**
+ * Maps logical Modeler preference locations to {@link Preferences} nodes. Pure
+ * JDK; holds the layout constants for {@code 
org/apache/cayenne/modeler/v5/...}
+ * (the regular preferences tree) and {@code 
org/apache/cayenne/modeler/mcp-handshake/...}
+ * (the sibling MCP launch-handshake namespace). All Modeler code that 
addresses
+ * a preferences node should go through this class.
+ */
+public final class PrefsLocator {
+
+    private static final String ALL_ROOT = "org/apache/cayenne/modeler";
+
+    // TODO: move under MODELER_ROOT?
+    private static final String HANDSHAKE_ROOT = ALL_ROOT + "/mcp-handshake";
+
+    private static final String MODELER_ROOT = ALL_ROOT + "/v5";
+    private static final String APP_ROOT = MODELER_ROOT + "/app";
+    private static final String PROJECT_ROOT = MODELER_ROOT + "/project";
+    private static final String DATAMAP_ROOT = MODELER_ROOT + "/datamap";
+
+
+    private final Preferences root;
+
+    public PrefsLocator() {
+        this.root = Preferences.userRoot();
+    }
+
+    /**
+     * The root of the Modeler's preferences' tree.
+     */
+    public Preferences modelerRoot() {
+        return root.node(MODELER_ROOT);
+    }
+
+    /**
+     * Returns a node under {@code v5/app}, optionally descending into a 
subtree.
+     * Pass {@code null} or empty for the {@code app} node itself.
+     */
+    public Preferences appNode(String relativePath) {
+        Preferences appRoot = root.node(APP_ROOT);
+        return relativePath == null || relativePath.isEmpty() ? appRoot : 
appRoot.node(relativePath);
+    }
+
+    /**
+     * Returns the preferences node for the project with the given id. The id 
is preferences node name derived from
+     * the project's absolute XML path — a truncated SHA-256 hash with a 
sanitized basename suffix.
+     */
+    public Preferences projectNode(String projectId) {
+        return root.node(PROJECT_ROOT).node(projectId);
+    }
+
+    /**
+     * Returns the preferences node for the DataMap with the given id. The id 
is preferences node name derived from
+     * the DataMap absolute XML path — a truncated SHA-256 hash with a 
sanitized basename suffix.
+     */
+    public Preferences dataMapNode(String dataMapId) {
+        return root.node(DATAMAP_ROOT).node(dataMapId);
+    }
+
+    /**
+     * Returns the per-nonce node under the MCP launch-handshake namespace
+     * ({@code org/apache/cayenne/modeler/mcp-handshake/<nonce>}). This subtree
+     * is intentionally a sibling of {@link #modelerRoot()} so that 
Modeler-wide
+     * resets do not clobber in-flight handshakes.
+     */
+    public Preferences handshakeNode(String nonce) {
+        return root.node(HANDSHAKE_ROOT).node(nonce);
+    }
+
+    /**
+     * Serializes the entire Modeler preferences subtree ({@link 
#modelerRoot()})
+     * as a pretty-printed JSON string. Each {@link Preferences} node becomes 
a JSON
+     * object whose own keys map to string values and whose child node names 
map to
+     * nested objects.
+     */
+    public String exportAsJson() {
+        return PreferencesJsonExporter.exportAsJson(modelerRoot());
+    }
+}
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferencesRepository.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsRepository.java
similarity index 74%
rename from 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferencesRepository.java
rename to 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsRepository.java
index 6399b1a3a..1fef1f666 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferencesRepository.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsRepository.java
@@ -39,6 +39,7 @@ import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 import java.util.stream.Collectors;
@@ -46,34 +47,30 @@ import java.util.stream.Stream;
 
 
 /**
- * App-wide preferences service for the Modeler. Owns the layout under
- * {@code org/apache/cayenne/modeler/v5} and resolves project / DataMap nodes
- * from their on-disk file paths (or stable per-runtime ids while still 
unsaved).
+ * App-wide preferences service for the Modeler. Delegates preferences-node
+ * location to {@link PrefsLocator} and adds Modeler-specific lifecycle
+ * on top: tracking unsaved projects/DataMaps with in-memory ids, staging
+ * renames/moves so they can be replayed on save, running version-gated
+ * preference migrations, and resetting the subtree.
  */
-public class PreferencesRepository {
+public class PrefsRepository {
 
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(PreferencesRepository.class);
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(PrefsRepository.class);
 
-    private static final String VERSION = "v5";
-    private static final String ROOT_PATH = "org/apache/cayenne/modeler/" + 
VERSION;
+    private static final String PROJECT_INDEX_NODE = "projectIndex";
+    private static final String DATAMAP_INDEX_NODE = "dataMapIndex";
+    private static final String UNSAVED_PREFIX = "unsaved-";
 
-    static final String APP_NODE = "app";
-    static final String PROJECT_NODE = "project";
-    static final String DATAMAP_NODE = "datamap";
+    private static final String UI_NODE = "ui";
+    private static final String META_NODE = "_meta";
 
-    static final String META_NODE = "_meta";
-    static final String UI_NODE = "ui";
-    static final String PROJECT_INDEX_NODE = "projectIndex";
-    static final String DATAMAP_INDEX_NODE = "dataMapIndex";
-
-    static final String MIGRATIONS_VERSION_KEY = "migrationsAppliedVersion";
-    static final String PATH_KEY = "path";
-    static final String UNSAVED_PREFIX = "unsaved-";
+    private static final String MIGRATIONS_VERSION_KEY = 
"migrationsAppliedVersion";
+    private static final String PATH_KEY = "path";
 
     private final ConfigurationNameMapper nameMapper;
     private final List<PreferenceMigration> migrations;
 
-    private final Preferences root;
+    private final PrefsLocator locator;
     private final Map<Project, String> newProjectIds;
     private final Map<DataMap, String> newDataMapIds;
     private final Map<String, String> stagingDataMap;
@@ -94,9 +91,9 @@ public class PreferencesRepository {
                 .collect(Collectors.toList());
     }
 
-    public PreferencesRepository(ConfigurationNameMapper nameMapper) {
+    public PrefsRepository(ConfigurationNameMapper nameMapper, PrefsLocator 
locator) {
         this.nameMapper = nameMapper;
-        this.root = Preferences.userRoot().node(ROOT_PATH);
+        this.locator = locator;
         this.migrations = toV5Migrations();
         this.newProjectIds = new IdentityHashMap<>();
         this.newDataMapIds = new IdentityHashMap<>();
@@ -104,53 +101,49 @@ public class PreferencesRepository {
         this.stagingProject = new HashMap<>();
     }
 
-    public Preferences appPref(String relativePath) {
-        Preferences appRoot = root.node(APP_NODE);
-        return relativePath == null || relativePath.isEmpty() ? appRoot : 
appRoot.node(relativePath);
-    }
-
     /**
-     * Per-component UI preferences node, addressed by a short stable path
-     * chosen by the caller (e.g. {@code "splitPane/templateEditor"}). Pass
-     * {@code null} or an empty string to get the {@code ui} base node itself.
+     * Returns the preferences node for the given {@link Project}, optionally 
descending into a subtree within it.
      */
-    public Preferences uiPref(String relativePath) {
-        Preferences uiRoot = appPref(UI_NODE);
-        return relativePath == null || relativePath.isEmpty() ? uiRoot : 
uiRoot.node(relativePath);
+    public Preferences projectPref(Project project, String relativePath) {
+        Preferences node;
+        String path = projectPath(project);
+        if (path != null) {
+            String id = PreferenceNodeIds.idForPath(path);
+            node = locator.projectNode(id);
+            recordPath(node, id, path, PROJECT_INDEX_NODE);
+        } else {
+            String id = newProjectIds.computeIfAbsent(project, p -> 
newUnsavedId());
+            node = locator.projectNode(id);
+        }
+        return relativePath == null || relativePath.isEmpty() ? node : 
node.node(relativePath);
     }
 
     /**
-     * Returns the preferences node for the given {@link Project}, optionally 
descending into a subtree within it.
+     * Returns a node under {@code v5/app/ui}, optionally descending into a 
subtree.
+     * Pass {@code null} or empty for the {@code ui} node itself. This is the 
conventional
+     * home for UI-state preferences (frame geometry, split-pane positions, 
table columns,
+     * file-chooser last-dirs) — anything not tied to a specific project or 
DataMap.
      */
-    public Preferences projectPref(Project project, String relativePath) {
-        String id = projectId(project);
-        Preferences node = root.node(PROJECT_NODE).node(id);
-        recordPath(node, projectPath(project), PROJECT_INDEX_NODE, id);
-        return relativePath == null || relativePath.isEmpty() ? node : 
node.node(relativePath);
+    public Preferences uiNode(String relativePath) {
+        Preferences uiRoot = locator.appNode(UI_NODE);
+        return relativePath == null || relativePath.isEmpty() ? uiRoot : 
uiRoot.node(relativePath);
     }
 
     /**
      * Returns the preferences node for the given {@link DataMap}, optionally 
descending into a subtree within it.
      */
     public Preferences dataMapPref(DataMap map, String relativePath) {
-        String id = dataMapId(map);
-        Preferences node = root.node(DATAMAP_NODE).node(id);
-        recordPath(node, dataMapPath(map), DATAMAP_INDEX_NODE, id);
-        return relativePath == null || relativePath.isEmpty() ? node : 
node.node(relativePath);
-    }
-
-    private String projectId(Project project) {
-        String path = projectPath(project);
-        return path != null
-                ? PreferenceNodeIds.idForPath(path)
-                : newProjectIds.computeIfAbsent(project, p -> newUnsavedId());
-    }
-
-    private String dataMapId(DataMap map) {
+        Preferences node;
         String path = dataMapPath(map);
-        return path != null
-                ? PreferenceNodeIds.idForPath(path)
-                : newDataMapIds.computeIfAbsent(map, m -> newUnsavedId());
+        if (path != null) {
+            String id = PreferenceNodeIds.idForPath(path);
+            node = locator.dataMapNode(id);
+            recordPath(node, id, path, DATAMAP_INDEX_NODE);
+        } else {
+            String id = newDataMapIds.computeIfAbsent(map, m -> 
newUnsavedId());
+            node = locator.dataMapNode(id);
+        }
+        return relativePath == null || relativePath.isEmpty() ? node : 
node.node(relativePath);
     }
 
     /**
@@ -240,16 +233,6 @@ public class PreferencesRepository {
         stagingProject.clear();
     }
 
-    /**
-     * Serializes the entire preferences subtree owned by this repository as a
-     * pretty-printed JSON string. Each {@link Preferences} node becomes a JSON
-     * object whose own keys map to string values and whose child node names 
map
-     * to nested objects.
-     */
-    public String exportAsJson() {
-        return PreferencesJsonExporter.exportAsJson(root);
-    }
-
     /**
      * Removes every child node of the repository root, wiping all Modeler
      * preferences. Also clears in-memory unsaved-id bookkeeping so subsequent
@@ -267,6 +250,7 @@ public class PreferencesRepository {
      * already applied so legacy preferences are not re-imported on next 
startup.
      */
     public void resetToDefaults(boolean importLegacyPreferences) {
+        Preferences root = locator.modelerRoot();
         try {
             for (String childName : root.childrenNames()) {
                 root.node(childName).removeNode();
@@ -279,8 +263,8 @@ public class PreferencesRepository {
         newDataMapIds.clear();
 
         if (!importLegacyPreferences && !migrations.isEmpty()) {
-            int highest = migrations.get(migrations.size() - 1).version();
-            Preferences meta = appPref(META_NODE);
+            int highest = migrations.getLast().version();
+            Preferences meta = locator.appNode(META_NODE);
             meta.putInt(MIGRATIONS_VERSION_KEY, highest);
             try {
                 meta.flush();
@@ -295,13 +279,13 @@ public class PreferencesRepository {
      * version exceeds {@code app/_meta/migrationsAppliedVersion}.
      */
     public void runMigrations() {
-        Preferences meta = appPref(META_NODE);
+        Preferences meta = locator.appNode(META_NODE);
         int applied = meta.getInt(MIGRATIONS_VERSION_KEY, 0);
         int max = applied;
         for (PreferenceMigration m : migrations) {
             if (m.version() > applied) {
                 try {
-                    m.apply(this);
+                    m.apply(locator);
                 } catch (RuntimeException e) {
                     LOGGER.warn("Migration v{} failed: {}", m.version(), 
e.getMessage(), e);
                 }
@@ -326,18 +310,18 @@ public class PreferencesRepository {
         if (stagedOldPath != null) {
             String oldId = PreferenceNodeIds.idForPath(stagedOldPath);
             if (!oldId.equals(savedId)) {
-                relocate(PROJECT_NODE, oldId, savedId, PROJECT_INDEX_NODE, 
currentPath);
+                relocate(locator::projectNode, oldId, savedId, 
PROJECT_INDEX_NODE, currentPath);
             } else {
-                recordPath(root.node(PROJECT_NODE).node(savedId), currentPath, 
PROJECT_INDEX_NODE, savedId);
+                recordPath(locator.projectNode(savedId), savedId, currentPath, 
PROJECT_INDEX_NODE);
             }
             return;
         }
 
         String oldId = newProjectIds.remove(project);
         if (oldId != null && !oldId.equals(savedId)) {
-            relocate(PROJECT_NODE, oldId, savedId, PROJECT_INDEX_NODE, 
currentPath);
+            relocate(locator::projectNode, oldId, savedId, PROJECT_INDEX_NODE, 
currentPath);
         } else {
-            recordPath(root.node(PROJECT_NODE).node(savedId), currentPath, 
PROJECT_INDEX_NODE, savedId);
+            recordPath(locator.projectNode(savedId), savedId, currentPath, 
PROJECT_INDEX_NODE);
         }
     }
 
@@ -352,35 +336,35 @@ public class PreferencesRepository {
         if (stagedOldPath != null) {
             String oldId = PreferenceNodeIds.idForPath(stagedOldPath);
             if (!oldId.equals(savedId)) {
-                relocate(DATAMAP_NODE, oldId, savedId, DATAMAP_INDEX_NODE, 
currentPath);
+                relocate(locator::dataMapNode, oldId, savedId, 
DATAMAP_INDEX_NODE, currentPath);
             } else {
-                recordPath(root.node(DATAMAP_NODE).node(savedId), currentPath, 
DATAMAP_INDEX_NODE, savedId);
+                recordPath(locator.dataMapNode(savedId), savedId, currentPath, 
DATAMAP_INDEX_NODE);
             }
             return;
         }
 
         String oldId = newDataMapIds.remove(map);
         if (oldId != null && !oldId.equals(savedId)) {
-            relocate(DATAMAP_NODE, oldId, savedId, DATAMAP_INDEX_NODE, 
currentPath);
+            relocate(locator::dataMapNode, oldId, savedId, DATAMAP_INDEX_NODE, 
currentPath);
         } else {
-            recordPath(root.node(DATAMAP_NODE).node(savedId), currentPath, 
DATAMAP_INDEX_NODE, savedId);
+            recordPath(locator.dataMapNode(savedId), savedId, currentPath, 
DATAMAP_INDEX_NODE);
         }
     }
 
-    private void relocate(String parentNode, String oldId, String newId, 
String indexNode, String path) {
-        Preferences src = root.node(parentNode).node(oldId);
-        Preferences dst = root.node(parentNode).node(newId);
+    private void relocate(Function<String, Preferences> nodeForId, String 
oldId, String newId, String indexNode, String path) {
+        Preferences src = nodeForId.apply(oldId);
+        Preferences dst = nodeForId.apply(newId);
         PreferencesCopier.move(src, dst);
-        appPref(indexNode).remove(oldId);
-        recordPath(dst, path, indexNode, newId);
+        locator.appNode(indexNode).remove(oldId);
+        recordPath(dst, newId, path, indexNode);
     }
 
-    private void recordPath(Preferences node, String path, String indexNode, 
String id) {
+    private void recordPath(Preferences node, String id, String path, String 
indexNode) {
         if (path == null) {
             return;
         }
         node.put(PATH_KEY, path);
-        appPref(indexNode).put(id, path);
+        locator.appNode(indexNode).put(id, path);
     }
 
     private static String projectPath(Project project) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/RecentProjectsPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/RecentProjectsPrefs.java
index bff699ee4..729a85134 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/RecentProjectsPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/RecentProjectsPrefs.java
@@ -35,8 +35,8 @@ public final class RecentProjectsPrefs extends 
PreferenceAdapter {
 
     public static final String NODE = "lastProjects";
 
-    public RecentProjectsPrefs(PreferencesRepository repository) {
-        super(repository.appPref(NODE));
+    public RecentProjectsPrefs(PrefsLocator locator) {
+        super(locator.appNode(NODE));
     }
 
     public List<File> getFiles() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_1_DbConnectorsMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_1_DbConnectorsMigration.java
index 61dc97152..5aa0bf1f2 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_1_DbConnectorsMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_1_DbConnectorsMigration.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
 import org.apache.cayenne.modeler.pref.PreferencesCopier;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,7 +44,7 @@ public class _1_DbConnectorsMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         Preferences legacy;
         try {
             if (!Preferences.userRoot().nodeExists(LEGACY_PATH)) {
@@ -56,7 +56,7 @@ public class _1_DbConnectorsMigration implements 
PreferenceMigration {
             return;
         }
 
-        Preferences target = repo.appPref("dbConnectors");
+        Preferences target = locator.appNode("dbConnectors");
         PreferencesCopier.copy(legacy, target);
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_2_ClasspathMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_2_ClasspathMigration.java
index f98815fd6..5ffe91621 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_2_ClasspathMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_2_ClasspathMigration.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.ClasspathPrefs;
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +46,7 @@ public class _2_ClasspathMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         Preferences legacy;
         String[] legacyKeys;
         try {
@@ -60,7 +60,7 @@ public class _2_ClasspathMigration implements 
PreferenceMigration {
             return;
         }
 
-        Preferences target = repo.appPref(ClasspathPrefs.NODE);
+        Preferences target = locator.appNode(ClasspathPrefs.NODE);
         for (String key : legacyKeys) {
             try {
                 Integer.parseInt(key);
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_3_GeneralPrefsMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_3_GeneralPrefsMigration.java
index 6f0103cc8..de337e68b 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_3_GeneralPrefsMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_3_GeneralPrefsMigration.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.GeneralPrefs;
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,7 +47,7 @@ public class _3_GeneralPrefsMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         Preferences legacy;
         try {
             if (!Preferences.userRoot().nodeExists(LEGACY_PATH)) {
@@ -59,7 +59,7 @@ public class _3_GeneralPrefsMigration implements 
PreferenceMigration {
             return;
         }
 
-        Preferences target = repo.appPref(GeneralPrefs.NODE);
+        Preferences target = locator.appNode(GeneralPrefs.NODE);
         target.putBoolean(GeneralPrefs.AUTO_LOAD_PROJECT, 
legacy.getBoolean("autoLoadProject", false));
         String encoding = normalizeEncoding(legacy.get("encoding", ""));
         if (encoding != null) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_4_RecentProjectsMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_4_RecentProjectsMigration.java
index fcca8ca28..902015893 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_4_RecentProjectsMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_4_RecentProjectsMigration.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
 import org.apache.cayenne.modeler.pref.PreferencesCopier;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.apache.cayenne.modeler.pref.RecentProjectsPrefs;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,7 +46,7 @@ public class _4_RecentProjectsMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         Preferences legacy;
         try {
             if (!Preferences.userRoot().nodeExists(LEGACY_PATH)) {
@@ -58,7 +58,7 @@ public class _4_RecentProjectsMigration implements 
PreferenceMigration {
             return;
         }
 
-        Preferences target = repo.appPref(RecentProjectsPrefs.NODE);
+        Preferences target = locator.appNode(RecentProjectsPrefs.NODE);
         PreferencesCopier.copy(legacy, target);
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_5_FrameGeometryMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_5_FrameGeometryMigration.java
index f22f64e2d..38fbfcdfb 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_5_FrameGeometryMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_5_FrameGeometryMigration.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +46,7 @@ public class _5_FrameGeometryMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         Preferences legacy;
         try {
             if (!Preferences.userRoot().nodeExists(LEGACY_PATH)) {
@@ -58,7 +58,7 @@ public class _5_FrameGeometryMigration implements 
PreferenceMigration {
             return;
         }
 
-        Preferences target = repo.uiPref("frame/geometry");
+        Preferences target = locator.appNode("ui").node("frame/geometry");
         copyInt(legacy, target, "width");
         copyInt(legacy, target, "height");
         copyInt(legacy, target, "x");
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_6_ProjectSplitPaneMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_6_ProjectSplitPaneMigration.java
index 3c0bdaa66..1c0130616 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_6_ProjectSplitPaneMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_6_ProjectSplitPaneMigration.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +46,7 @@ public class _6_ProjectSplitPaneMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         Preferences legacy;
         try {
             if (!Preferences.userRoot().nodeExists(LEGACY_PATH)) {
@@ -60,7 +60,7 @@ public class _6_ProjectSplitPaneMigration implements 
PreferenceMigration {
 
         int dividerLocation = legacy.getInt(DIVIDER_LOCATION, 
Integer.MIN_VALUE);
         if (dividerLocation != Integer.MIN_VALUE) {
-            repo.uiPref("project/splitPane").putInt(DIVIDER_LOCATION, 
dividerLocation);
+            
locator.appNode("ui").node("project/splitPane").putInt(DIVIDER_LOCATION, 
dividerLocation);
         }
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_7_EntityTablePrefsMigration.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_7_EntityTablePrefsMigration.java
index 980445266..6696effe8 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_7_EntityTablePrefsMigration.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/migration/toV5/_7_EntityTablePrefsMigration.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.pref.migration.toV5;
 
 import org.apache.cayenne.modeler.pref.PreferenceMigration;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -58,13 +58,13 @@ public class _7_EntityTablePrefsMigration implements 
PreferenceMigration {
     }
 
     @Override
-    public void apply(PreferencesRepository repo) {
+    public void apply(PrefsLocator locator) {
         for (String[] pair : PATHS) {
-            copyTable(repo, pair[0], pair[1]);
+            copyTable(locator, pair[0], pair[1]);
         }
     }
 
-    private static void copyTable(PreferencesRepository repo, String 
legacyPath, String uiPath) {
+    private static void copyTable(PrefsLocator locator, String legacyPath, 
String uiPath) {
         Preferences legacy;
         String[] legacyKeys;
         try {
@@ -78,7 +78,7 @@ public class _7_EntityTablePrefsMigration implements 
PreferenceMigration {
             return;
         }
 
-        Preferences target = repo.uiPref(uiPath);
+        Preferences target = locator.appNode("ui").node(uiPath);
         for (String key : legacyKeys) {
             switch (key) {
                 case LEGACY_SORT_COLUMN:
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectPrefs.java
index ef63ab6a1..581d2cb3d 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectPrefs.java
@@ -53,7 +53,7 @@ import 
org.apache.cayenne.modeler.event.display.ProcedureDisplayEvent;
 import org.apache.cayenne.modeler.event.display.ProcedureParameterDisplayEvent;
 import org.apache.cayenne.modeler.event.display.QueryDisplayEvent;
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 import org.apache.cayenne.project.Project;
 import org.apache.cayenne.util.CayenneMapEntry;
 
@@ -96,7 +96,7 @@ public final class ProjectPrefs extends PreferenceAdapter {
         query, multipleObjects
     }
 
-    public ProjectPrefs(PreferencesRepository repository, Project project) {
+    public ProjectPrefs(PrefsRepository repository, Project project) {
         super(repository.projectPref(project, null));
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectSession.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectSession.java
index 6b03d8bfa..7d9e07ef3 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectSession.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/ProjectSession.java
@@ -182,7 +182,7 @@ public class ProjectSession {
     public void projectClosed() {
 
         setDirty(false);
-        app.getPreferencesRepository().resetTransientState();
+        app.getPrefsRepository().resetTransientState();
 
         this.project = null;
         this.entityResolver = null;
@@ -201,14 +201,14 @@ public class ProjectSession {
         if (project == null) {
             return;
         }
-        new ProjectPrefs(app.getPreferencesRepository(), project).flush(this);
+        new ProjectPrefs(app.getPrefsRepository(), project).flush(this);
     }
 
     public void restoreSelectionFromPrefs() {
         if (project == null) {
             return;
         }
-        new ProjectPrefs(app.getPreferencesRepository(), project).load(this);
+        new ProjectPrefs(app.getPrefsRepository(), project).load(this);
     }
 
     public boolean isDirty() {
@@ -550,7 +550,7 @@ public class ProjectSession {
 
     public void fireProjectAfterSaveEvent(ProjectAfterSaveEvent e) {
         fileChangeTracker.reset();
-        app.getPreferencesRepository().commitProject(project);
+        app.getPrefsRepository().commitProject(project);
         for (ProjectAfterSaveListener eventListener : 
listeners.getListeners(ProjectAfterSaveListener.class)) {
             eventListener.projectSaved(e);
         }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/component/CMComponentGeometryPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/component/CMComponentGeometryPrefs.java
index 89b7ad4a0..d48a68dd2 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/component/CMComponentGeometryPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/component/CMComponentGeometryPrefs.java
@@ -20,7 +20,7 @@
 package org.apache.cayenne.modeler.toolkit.component;
 
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 
 import java.awt.*;
 import java.awt.event.ComponentAdapter;
@@ -33,8 +33,8 @@ public final class CMComponentGeometryPrefs extends 
PreferenceAdapter {
     private static final String X_PROPERTY = "x";
     private static final String Y_PROPERTY = "y";
 
-    public CMComponentGeometryPrefs(PreferencesRepository repository, String 
path) {
-        super(repository.uiPref(path));
+    public CMComponentGeometryPrefs(PrefsRepository repository, String path) {
+        super(repository.uiNode(path));
     }
 
     public void bind(Component c, int defaultWidth, int defaultHeight) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/filechooser/CMFileChooserPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/filechooser/CMFileChooserPrefs.java
index b11804963..b3f349736 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/filechooser/CMFileChooserPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/filechooser/CMFileChooserPrefs.java
@@ -20,7 +20,7 @@
 package org.apache.cayenne.modeler.toolkit.filechooser;
 
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 
 import javax.swing.JFileChooser;
 import java.io.File;
@@ -29,8 +29,8 @@ public final class CMFileChooserPrefs extends 
PreferenceAdapter {
 
     private static final String PATH_PROPERTY = "path";
 
-    public CMFileChooserPrefs(PreferencesRepository repository, String path) {
-        super(repository.uiPref(path));
+    public CMFileChooserPrefs(PrefsRepository repository, String path) {
+        super(repository.uiNode(path));
     }
 
     public void bind(JFileChooser chooser) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/splitpane/CMSplitPanePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/splitpane/CMSplitPanePrefs.java
index ab3e66f7a..fd2b91384 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/splitpane/CMSplitPanePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/splitpane/CMSplitPanePrefs.java
@@ -20,7 +20,7 @@
 package org.apache.cayenne.modeler.toolkit.splitpane;
 
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 
 import javax.swing.*;
 import java.beans.PropertyChangeListener;
@@ -29,8 +29,8 @@ public final class CMSplitPanePrefs extends PreferenceAdapter 
{
 
     private PropertyChangeListener listener;
 
-    public CMSplitPanePrefs(PreferencesRepository repository, String path) {
-        super(repository.uiPref(path));
+    public CMSplitPanePrefs(PrefsRepository repository, String path) {
+        super(repository.uiNode(path));
     }
 
     public void bind(JSplitPane pane, int defaultLocation) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMTablePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMTablePrefs.java
index 4b40b04de..78b4a545b 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMTablePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMTablePrefs.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.toolkit.table;
 
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ListSelectionEvent;
@@ -38,8 +38,8 @@ public final class CMTablePrefs extends PreferenceAdapter {
     private static final String ORDER_KEY = "colOrder";
     private static final String LISTENER_PROPERTY = "TablePrefs.listener";
 
-    public CMTablePrefs(PreferencesRepository repository, String path) {
-        super(repository.uiPref(path));
+    public CMTablePrefs(PrefsRepository repository, String path) {
+        super(repository.uiNode(path));
     }
 
     /**
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainFrame.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainFrame.java
index 9e812c344..a96536731 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainFrame.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainFrame.java
@@ -114,7 +114,7 @@ public class MainFrame extends AppFrame {
         splitPane.getInsets().right = 5;
         splitPane.setResizeWeight(0.7);
 
-        this.splitPanePrefs = new 
CMSplitPanePrefs(app.getPreferencesRepository(), "frame/splitPane");
+        this.splitPanePrefs = new CMSplitPanePrefs(app.getPrefsRepository(), 
"frame/splitPane");
 
         JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 3, 1));
         statusBar.setBorder(TopBorder.create());
@@ -238,7 +238,7 @@ public class MainFrame extends AppFrame {
             }
         });
 
-        new CMComponentGeometryPrefs(app.getPreferencesRepository(), 
"frame/geometry").bind(this, 1200, 720);
+        new CMComponentGeometryPrefs(app.getPrefsRepository(), 
"frame/geometry").bind(this, 1200, 720);
 
         setVisible(true);
     }
@@ -316,7 +316,11 @@ public class MainFrame extends AppFrame {
         }
 
         if (mcpHandshakeNonce != null) {
-            McpHandshakeWriter.write(mcpHandshakeNonce, 
app.getCli().rawArgs(), getProjectLocationString());
+            McpHandshakeWriter.write(
+                    app.getPrefsLocator(),
+                    mcpHandshakeNonce,
+                    app.getCli().rawArgs(),
+                    getProjectLocationString());
         }
     }
 
@@ -324,11 +328,11 @@ public class MainFrame extends AppFrame {
      * Adds path to the list of last opened projects in preferences.
      */
     public void addToLastProjListAction(File file) {
-        new RecentProjectsPrefs(app.getPreferencesRepository()).addFile(file);
+        new RecentProjectsPrefs(app.getPrefsLocator()).addFile(file);
     }
 
     public void changePathInLastProjListAction(File oldFile, File newFile) {
-        RecentProjectsPrefs prefs = new 
RecentProjectsPrefs(app.getPreferencesRepository());
+        RecentProjectsPrefs prefs = new 
RecentProjectsPrefs(app.getPrefsLocator());
         prefs.removeFile(oldFile);
         prefs.addFile(newFile);
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainMenuBar.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainMenuBar.java
index 08ddea2e2..1ec537238 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainMenuBar.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/MainMenuBar.java
@@ -149,7 +149,7 @@ class MainMenuBar extends JMenuBar {
          */
         public void rebuildFromPreferences() {
 
-            List<File> files = new 
RecentProjectsPrefs(app.getPreferencesRepository()).getFiles();
+            List<File> files = new 
RecentProjectsPrefs(app.getPrefsLocator()).getFiles();
 
             // read menus
             Component[] comps = getMenuComponents();
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/DBConnectionAwareAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/DBConnectionAwareAction.java
index 543c84bcb..237f6364e 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/DBConnectionAwareAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/DBConnectionAwareAction.java
@@ -73,6 +73,6 @@ public abstract class DBConnectionAwareAction extends 
AppAction {
     }
 
     private DataMapPrefs dataMapPrefs(DataMap dataMap) {
-        return new DataMapPrefs(app.getPreferencesRepository(), dataMap);
+        return new DataMapPrefs(app.getPrefsRepository(), dataMap);
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportDataMapAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportDataMapAction.java
index 0a2cb5509..83fd71be8 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportDataMapAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportDataMapAction.java
@@ -102,7 +102,7 @@ public class ImportDataMapAction extends AppAction {
         JFileChooser chooser = new JFileChooser();
         chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
-        new CMFileChooserPrefs(app.getPreferencesRepository(), 
"importDataMap/lastDir").bind(chooser);
+        new CMFileChooserPrefs(app.getPrefsRepository(), 
"importDataMap/lastDir").bind(chooser);
 
         chooser.addChoosableFileFilter(FileFilters.getDataMapFilter());
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportEOModelAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportEOModelAction.java
index dfae9a328..19b0dcb8c 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportEOModelAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ImportEOModelAction.java
@@ -325,7 +325,7 @@ public class ImportEOModelAction extends AppAction {
             eoModelChooser = new EOModelChooser("Select EOModel");
         }
 
-        new CMFileChooserPrefs(app.getPreferencesRepository(), 
"importEOModel/lastDir").bind(eoModelChooser);
+        new CMFileChooserPrefs(app.getPrefsRepository(), 
"importEOModel/lastDir").bind(eoModelChooser);
 
         return eoModelChooser;
     }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ProjectOpener.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ProjectOpener.java
index 3384d1073..10d860c28 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ProjectOpener.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ProjectOpener.java
@@ -137,7 +137,7 @@ class ProjectOpener extends JFileChooser {
     }
 
     private File getDefaultStartDir(Application application) {
-        List<File> recent = new 
RecentProjectsPrefs(application.getPreferencesRepository()).getFiles();
+        List<File> recent = new 
RecentProjectsPrefs(application.getPrefsLocator()).getFiles();
         if (!recent.isEmpty()) {
             File parent = recent.get(0).getParentFile();
             if (parent != null && parent.isDirectory()) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/SaveAsAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/SaveAsAction.java
index 5a86f8ea8..9de070a7d 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/SaveAsAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/SaveAsAction.java
@@ -26,7 +26,7 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.event.model.ProjectBeforeSaveEvent;
 import org.apache.cayenne.modeler.event.model.ProjectAfterSaveEvent;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 import org.apache.cayenne.modeler.toolkit.AppAction;
 import org.apache.cayenne.project.Project;
 import org.apache.cayenne.project.ProjectSaver;
@@ -83,7 +83,7 @@ public class SaveAsAction extends AppAction {
 
         getProjectSession().pauseFileChangeTracking();
 
-        PreferencesRepository repo = app.getPreferencesRepository();
+        PrefsRepository repo = app.getPrefsRepository();
         repo.stageProjectMove(p, projectDir);
         DataChannelDescriptor descriptor = (DataChannelDescriptor) 
p.getRootNode();
         if (descriptor != null) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ShowLogConsoleAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ShowLogConsoleAction.java
index 23da4b304..7239ce0ad 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ShowLogConsoleAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ShowLogConsoleAction.java
@@ -44,6 +44,6 @@ public class ShowLogConsoleAction extends AppAction {
     }
 
     private Boolean isConsoleShown() {
-        return new 
LogConsolePrefs(app.getPreferencesRepository()).isShowConsole();
+        return new LogConsolePrefs(app.getPrefsLocator()).isShowConsole();
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java
index 9eb94d967..edc7fe5a5 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java
@@ -63,7 +63,7 @@ public class ConfirmRemoveDialog {
         // If the user clicks "cancel" or window close button, we'll just 
ignore whatever's in the checkbox because
         // it's non-sensical.
         if (shouldDelete) {
-            new 
GeneralPrefs(application.getPreferencesRepository()).setNoDeletePrompt(neverPromptAgainBox.isSelected());
+            new 
GeneralPrefs(application.getPrefsLocator()).setNoDeletePrompt(neverPromptAgainBox.isSelected());
         }
     }
 
@@ -72,7 +72,7 @@ public class ConfirmRemoveDialog {
     }
 
     public boolean shouldDelete(String name) {
-        if (allowAsking && !new 
GeneralPrefs(application.getPreferencesRepository()).isNoDeletePrompt()) {
+        if (allowAsking && !new 
GeneralPrefs(application.getPrefsLocator()).isNoDeletePrompt()) {
             showDialog(name);
         }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/datasource/DataSourceDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/datasource/DataSourceDialog.java
index 6e0591305..bead6be27 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/datasource/DataSourceDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/datasource/DataSourceDialog.java
@@ -84,7 +84,7 @@ public class DataSourceDialog extends ProjectDialog {
         refreshDataSources();
         initFavouriteDataSource();
 
-        DataMapPrefs dataMapPrefs = new 
DataMapPrefs(app.getPreferencesRepository(), session.getSelectedDataMap());
+        DataMapPrefs dataMapPrefs = new DataMapPrefs(app.getPrefsRepository(), 
session.getSelectedDataMap());
         if (dataMapPrefs.hasDbAdapter()) {
             getConnectionInfoFromPreferences().copyTo(connector);
         }
@@ -155,7 +155,7 @@ public class DataSourceDialog extends ProjectDialog {
     }
 
     private void initFavouriteDataSource() {
-        String favourite = new 
GeneralPrefs(app.getPreferencesRepository()).getFavouriteDataSource();
+        String favourite = new 
GeneralPrefs(app.getPrefsLocator()).getFavouriteDataSource();
         if (favourite != null && connectors.containsKey(favourite)) {
             setSelectedDataSource(favourite);
             dataSources.setSelectedItem(dataSourceKey);
@@ -163,7 +163,7 @@ public class DataSourceDialog extends ProjectDialog {
     }
 
     private DBConnector getConnectionInfoFromPreferences() {
-        DataMapPrefs dataMapPrefs = new 
DataMapPrefs(app.getPreferencesRepository(), session.getSelectedDataMap());
+        DataMapPrefs dataMapPrefs = new DataMapPrefs(app.getPrefsRepository(), 
session.getSelectedDataMap());
         DBConnector c = dataMapPrefs.getConnector();
         return c != null ? c : new DBConnector();
     }
@@ -197,7 +197,7 @@ public class DataSourceDialog extends ProjectDialog {
         this.canceled = canceled;
         dispose();
         if (!canceled) {
-            new 
GeneralPrefs(app.getPreferencesRepository()).setFavouriteDataSource(dataSourceKey);
+            new 
GeneralPrefs(app.getPrefsLocator()).setFavouriteDataSource(dataSourceKey);
         }
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java
index bef78b2b1..4204a5642 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java
@@ -106,7 +106,7 @@ public class DBGeneratorOptionsDialog extends ProjectDialog 
{
 
         this.connector = new DBConnector();
         this.connector.setAllowDataSourceFailure(true);
-        this.generatorDefaults = new 
DBGeneratorPrefs(app.getPreferencesRepository(), session.project());
+        this.generatorDefaults = new 
DBGeneratorPrefs(app.getPrefsRepository(), session.project());
 
         // create widgets — set initial state before wiring listeners so we
         // don't fire spurious refresh events during construction.
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorPrefs.java
index 00e2f65ff..17a436d72 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorPrefs.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.ui.dbgen;
 
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsRepository;
 import org.apache.cayenne.project.Project;
 
 /**
@@ -35,7 +35,7 @@ public class DBGeneratorPrefs extends PreferenceAdapter {
     private static final String DROP_PK_PROPERTY = "dropPK";
     private static final String DROP_TABLES_PROPERTY = "dropTables";
 
-    public DBGeneratorPrefs(PreferencesRepository repository, Project project) 
{
+    public DBGeneratorPrefs(PrefsRepository repository, Project project) {
         super(repository.projectPref(project, NODE));
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java
index 53c274b0b..5384c1ef6 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java
@@ -321,7 +321,7 @@ public class DbRelationshipDialog extends ProjectDialog {
         AutoCompletion.enable(targetCombo, session::getSelectedDataMap);
         targetColumn.setCellEditor(new CMComboBoxCellEditor(targetCombo));
 
-        new CMTablePrefs(app.getPreferencesRepository(), 
"dbEntity/dbjoinTable")
+        new CMTablePrefs(app.getPrefsRepository(), "dbEntity/dbjoinTable")
                 .bind(table, null, DbJoinTableModel.SOURCE);
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsole.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsole.java
index bc8808be1..9862ba6c1 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsole.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsole.java
@@ -158,7 +158,7 @@ public class LogConsole extends AppPanel implements 
LogAppender {
     }
 
     public void toggle() {
-        if (new 
LogConsolePrefs(app.getPreferencesRepository()).toggleShowConsole()) {
+        if (new LogConsolePrefs(app.getPrefsLocator()).toggleShowConsole()) {
             appear();
         } else {
             disappear();
@@ -166,7 +166,7 @@ public class LogConsole extends AppPanel implements 
LogAppender {
     }
 
     public void showConsoleIfNeeded() {
-        if (new 
LogConsolePrefs(app.getPreferencesRepository()).isShowConsole()) {
+        if (new LogConsolePrefs(app.getPrefsLocator()).isShowConsole()) {
             appear();
         }
     }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsolePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsolePrefs.java
index 0e97d0fd5..af1fabcf2 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsolePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsolePrefs.java
@@ -20,15 +20,15 @@
 package org.apache.cayenne.modeler.ui.logconsole;
 
 import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 
 public final class LogConsolePrefs extends PreferenceAdapter {
 
     static final String NODE = "logConsole";
     static final String SHOW_CONSOLE = "showLogConsole";
 
-    public LogConsolePrefs(PreferencesRepository repository) {
-        super(repository.appPref(NODE));
+    public LogConsolePrefs(PrefsLocator locator) {
+        super(locator.appNode(NODE));
     }
 
     public boolean isShowConsole() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/ClasspathPrefsPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/ClasspathPrefsPanel.java
index 2dc548994..27ad31874 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/ClasspathPrefsPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/ClasspathPrefsPanel.java
@@ -54,7 +54,7 @@ public class ClasspathPrefsPanel extends AppPanel {
     public ClasspathPrefsPanel(Application app) {
         super(app);
 
-        this.entries = new ArrayList<>(new 
ClasspathPrefs(app.getPreferencesRepository()).getEntries());
+        this.entries = new ArrayList<>(new 
ClasspathPrefs(app.getPrefsLocator()).getEntries());
         this.tableModel = new ClasspathTableModel();
         this.table = new CMTable();
         this.table.setRowMargin(3);
@@ -70,7 +70,7 @@ public class ClasspathPrefsPanel extends AppPanel {
     }
 
     public void commit() {
-        new ClasspathPrefs(app.getPreferencesRepository()).setEntries(entries);
+        new ClasspathPrefs(app.getPrefsLocator()).setEntries(entries);
         app.refreshClassLoader();
     }
 
@@ -139,7 +139,7 @@ public class ClasspathPrefsPanel extends AppPanel {
         chooser.setDialogType(JFileChooser.OPEN_DIALOG);
         chooser.setAcceptAllFileFilterUsed(true);
 
-        new CMFileChooserPrefs(app.getPreferencesRepository(), 
"classpath/lastDir").bind(chooser);
+        new CMFileChooserPrefs(app.getPrefsRepository(), 
"classpath/lastDir").bind(chooser);
         if (filter != null) {
             chooser.addChoosableFileFilter(filter);
             chooser.setFileFilter(filter);
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/general/GeneralPrefsPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/general/GeneralPrefsPanel.java
index 61f4c88ac..c7d1f3973 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/general/GeneralPrefsPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/general/GeneralPrefsPanel.java
@@ -55,7 +55,7 @@ public class GeneralPrefsPanel extends AppPanel {
         this.systemEncoding = Charset.defaultCharset().name();
         this.defaultLabel = systemEncoding + " (default)";
 
-        GeneralPrefs prefs = new GeneralPrefs(app.getPreferencesRepository());
+        GeneralPrefs prefs = new GeneralPrefs(app.getPrefsLocator());
 
         this.encodingChoices = new JComboBox<>(new 
DefaultComboBoxModel<>(encodingLabels()));
         selectEncoding(prefs.getEncoding());
@@ -70,7 +70,7 @@ public class GeneralPrefsPanel extends AppPanel {
     }
 
     public void commit() {
-        GeneralPrefs prefs = new GeneralPrefs(app.getPreferencesRepository());
+        GeneralPrefs prefs = new GeneralPrefs(app.getPrefsLocator());
         prefs.setEncoding(selectedEncoding());
         prefs.setAutoLoadProject(autoLoadProject.isSelected());
         prefs.setNoDeletePrompt(noDeletePrompt.isSelected());
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/more/MorePrefsPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/more/MorePrefsPanel.java
index 727106b80..eef56edf9 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/more/MorePrefsPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/more/MorePrefsPanel.java
@@ -23,7 +23,6 @@ import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.pref.PreferencesRepository;
 import org.apache.cayenne.modeler.toolkit.AppPanel;
 import org.apache.cayenne.modeler.ui.action.CloseProjectAction;
 
@@ -81,8 +80,7 @@ public class MorePrefsPanel extends AppPanel {
     }
 
     private void copyAllClicked() {
-        PreferencesRepository repository = app.getPreferencesRepository();
-        String json = repository.exportAsJson();
+        String json = app.getPrefsLocator().exportAsJson();
         Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new 
StringSelection(json), null);
     }
 
@@ -113,7 +111,7 @@ public class MorePrefsPanel extends AppPanel {
         }
         app.getFrame().dispose();
 
-        app.getPreferencesRepository().resetToDefaults(importLegacy);
+        app.getPrefsRepository().resetToDefaults(importLegacy);
 
         // Defer the rebuild to a later EDT tick so the in-flight action 
handler
         // (and any pending dispose events) drain first.
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/ProjectView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/ProjectView.java
index 3e131e64f..7d27ae244 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/ProjectView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/ProjectView.java
@@ -102,7 +102,7 @@ public class ProjectView extends ProjectPanel {
 
         this.filterPopup = new TreeFilterPopup(treePanel);
 
-        new CMSplitPanePrefs(app.getPreferencesRepository(), 
"project/splitPane").bind(splitPane, 300);
+        new CMSplitPanePrefs(app.getPrefsRepository(), 
"project/splitPane").bind(splitPane, 300);
     }
 
     public EditorPanelView getEditorPanel() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenTab.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenTab.java
index aade11a88..99cea6e66 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenTab.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenTab.java
@@ -88,7 +88,7 @@ public class DataDomainCgenTab extends 
DataDomainGeneratorsTab<CgenConfiguration
         CgenConfiguration cgenConfiguration = new CgenConfiguration();
         cgenConfiguration.setDataMap(dataMap);
         cgenConfiguration.updateOutputPath(CgenOps.baseDir(session));
-        cgenConfiguration.setEncoding(new 
GeneralPrefs(app.getPreferencesRepository()).getEncoding());
+        cgenConfiguration.setEncoding(new 
GeneralPrefs(app.getPrefsLocator()).getEncoding());
 
         cgenConfiguration.resolveExcludedEntities();
         cgenConfiguration.resolveExcludedEmbeddables();
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java
index 85208bba0..e0808270f 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java
@@ -203,7 +203,7 @@ public class DataDomainMainView extends ProjectPanel 
implements DomainDisplayLis
                 this,
                 dataChannelDescriptor,
                 dataChannelDescriptor.getName());
-        app.getPreferencesRepository().stageProjectRename(session.project(), 
newName);
+        app.getPrefsRepository().stageProjectRename(session.project(), 
newName);
         dataChannelDescriptor.setName(newName);
 
         session.fireDomainEvent(e);
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java
index 85ece23f9..70c7a0d7c 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java
@@ -447,7 +447,7 @@ public class CgenPanel extends ProjectPanel
             configuration.setRootPath(Utils.getRootPathForDataMap(map));
             configuration.updateOutputPath(basePath);
         }
-        configuration.setEncoding(new 
GeneralPrefs(app.getPreferencesRepository()).getEncoding());
+        configuration.setEncoding(new 
GeneralPrefs(app.getPrefsLocator()).getEncoding());
         return configuration;
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditor.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditor.java
index ba463f75d..befe628c9 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditor.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditor.java
@@ -256,8 +256,8 @@ public class TemplateEditor extends AppFrame {
     }
 
     private void bindGeometry() {
-        new CMSplitPanePrefs(app.getPreferencesRepository(), 
"templateEditor/splitPane").bind(split, 600);
-        new CMComponentGeometryPrefs(app.getPreferencesRepository(), 
"templateEditor/geometry").bind(this, 1200, 700);
+        new CMSplitPanePrefs(app.getPrefsRepository(), 
"templateEditor/splitPane").bind(split, 600);
+        new CMComponentGeometryPrefs(app.getPrefsRepository(), 
"templateEditor/geometry").bind(this, 1200, 700);
     }
 
     private void mapVelocityTokenMaker() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
index 567ca0e33..f204586eb 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
@@ -241,7 +241,7 @@ public class DataMapMainView extends ProjectPanel {
         dataMap.setDefaultPackage(newDefaultPackage);
 
         // update class generation preferences
-        new DataMapPrefs(app.getPreferencesRepository(), dataMap)
+        new DataMapPrefs(app.getPrefsRepository(), dataMap)
                 .setSuperclassPackage(newDefaultPackage, 
DataMapPrefs.DEFAULT_SUPERCLASS_PACKAGE_SUFFIX);
 
         session.fireDataMapEvent(DataMapEvent.ofChange(this, dataMap));
@@ -343,7 +343,7 @@ public class DataMapMainView extends ProjectPanel {
                 nodesUsingMap.add(node);
             }
         }
-        app.getPreferencesRepository().stageDataMapRename(map, newName);
+        app.getPrefsRepository().stageDataMapRename(map, newName);
         map.setName(newName);
         for (DataNodeDescriptor node : nodesUsingMap) {
             node.getDataMapNames().remove(oldName);
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/DataNodeEditorPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/DataNodeEditorPanel.java
index 5b6b4bee6..cfaf3d569 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/DataNodeEditorPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/DataNodeEditorPanel.java
@@ -231,7 +231,7 @@ public class DataNodeEditorPanel extends ProjectPanel {
         String oldName = node.getName();
         node.setName(newName);
 
-        new DataNodePrefs(app.getPreferencesRepository(), session.project(), 
oldName).rename(newName);
+        new DataNodePrefs(app.getPrefsRepository(), session.project(), 
oldName).rename(newName);
     }
 
     private DataNodePrefs nodePrefs() {
@@ -239,7 +239,7 @@ public class DataNodeEditorPanel extends ProjectPanel {
         if (selected == null) {
             throw new IllegalStateException("No DataNode selected");
         }
-        return new DataNodePrefs(app.getPreferencesRepository(), 
session.project(), selected.getName());
+        return new DataNodePrefs(app.getPrefsRepository(), session.project(), 
selected.getName());
     }
 
     private void dataSourceConfigAction() {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/jdbc/JDBCDataSourcePanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/jdbc/JDBCDataSourcePanel.java
index a1adfea4e..c38552fcb 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/jdbc/JDBCDataSourcePanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datanode/jdbc/JDBCDataSourcePanel.java
@@ -159,7 +159,7 @@ public class JDBCDataSourcePanel extends DataSourcePanel {
         DataSourceDescriptor projectDataSourceDescriptor = 
getNode().getDataSourceDescriptor();
 
         String key = new DataNodePrefs(
-                app.getPreferencesRepository(),
+                app.getPrefsRepository(),
                 frame.getProjectSession().project(),
                 getNode().getName()).getLocalDataSource();
         if (key == null) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
index 6060a49b7..38c815c0d 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
@@ -185,7 +185,7 @@ public class DbAttributePanel extends JPanel implements 
DbEntityDisplayListener,
         TableColumn typeColumn = 
table.getColumnModel().getColumn(DbAttributeTableModel.DB_ATTRIBUTE_TYPE);
         typeColumn.setCellEditor(new CMComboBoxCellEditor(comboBox));
 
-        new CMTablePrefs(session.app().getPreferencesRepository(), 
"dbEntity/attributeTable")
+        new CMTablePrefs(session.app().getPrefsRepository(), 
"dbEntity/attributeTable")
                 .bind(table, null, DbAttributeTableModel.DB_ATTRIBUTE_NAME);
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
index 9938f52a3..d562470f2 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
@@ -71,7 +71,7 @@ public class DbEntityPropertiesView extends ProjectPanel 
implements DbEntityDisp
 
         splitPane.setOneTouchExpandable(true);
         splitPane.setResizeWeight(0.5);
-        new CMSplitPanePrefs(app.getPreferencesRepository(), 
"dbEntity/splitPane").bind(splitPane, -1);
+        new CMSplitPanePrefs(app.getPrefsRepository(), 
"dbEntity/splitPane").bind(splitPane, -1);
         add(splitPane);
 
         toolBar.setFloatable(false);
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
index 0a1ac9e04..555022f72 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
@@ -193,7 +193,7 @@ public class DbRelationshipPanel extends JPanel implements 
DbEntityDisplayListen
         TableColumn toDepPkColumn = 
table.getColumnModel().getColumn(DbRelationshipTableModel.TO_DEPENDENT_KEY);
         toDepPkColumn.setCellRenderer(new CheckBoxCellRenderer());
 
-        new CMTablePrefs(session.app().getPreferencesRepository(), 
"dbEntity/relationshipTable")
+        new CMTablePrefs(session.app().getPrefsRepository(), 
"dbEntity/relationshipTable")
                 .bind(table, null, DbRelationshipTableModel.NAME);
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
index 1e745680f..a47638c6a 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
@@ -171,7 +171,7 @@ public class EmbeddableAttributesView extends ProjectPanel 
implements
         AutoCompletion.enable(javaTypesCombo, false, true, 
session::getSelectedDataMap);
         typeColumn.setCellEditor(new CMComboBoxCellEditor(javaTypesCombo));
 
-        new CMTablePrefs(app.getPreferencesRepository(), 
"embeddable/attributeTable")
+        new CMTablePrefs(app.getPrefsRepository(), "embeddable/attributeTable")
                 .bind(table, null, 
EmbeddableAttributeTableModel.OBJ_ATTRIBUTE);
 
     }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialog.java
index ff21852d8..55f3f1850 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialog.java
@@ -411,7 +411,7 @@ public class ObjAttributeInfoDialog extends ProjectDialog 
implements TreeSelecti
                 
.getColumn(OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE_TYPE);
         dbAttrTypeColumn.setCellRenderer(renderer);
 
-        new CMTablePrefs(app.getPreferencesRepository(), 
"objEntity/overrideAttributeTable")
+        new CMTablePrefs(app.getPrefsRepository(), 
"objEntity/overrideAttributeTable")
                 .bind(overrideAttributeTable, null,
                         OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE);
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
index 03fd81a77..7cd8ba9d8 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
@@ -219,7 +219,7 @@ public class ObjEntityCallbacksView extends ProjectPanel {
         }
 
         for (CMTable table : tables) {
-            new CMTablePrefs(app.getPreferencesRepository(), 
"objEntity/callbackTable")
+            new CMTablePrefs(app.getPrefsRepository(), 
"objEntity/callbackTable")
                     .bind(table, MIN_SIZES);
         }
     }
@@ -513,7 +513,7 @@ public class ObjEntityCallbacksView extends ProjectPanel {
 
         public void mouseDragged(MouseEvent e) {
             if (table.getColumnWidthChanged()) {
-                new CMTablePrefs(app.getPreferencesRepository(), 
"objEntity/callbackTable")
+                new CMTablePrefs(app.getPrefsRepository(), 
"objEntity/callbackTable")
                         .bind(table, MIN_SIZES);
                 for (CMTable nextTable : tables) {
                     if (!table.equals(nextTable)) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
index 4451c36b2..e3d61c040 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
@@ -318,7 +318,7 @@ public class ObjAttributePanel extends JPanel implements 
ObjEntityDisplayListene
         
table.getColumnModel().getColumn(ObjAttributeTableModel.DB_ATTRIBUTE).setCellRenderer(new
 DbAttributePathComboBoxRenderer());
         
table.getColumnModel().getColumn(ObjAttributeTableModel.DB_ATTRIBUTE).setCellEditor(new
 DbAttributePathComboBoxEditor(session::getSelectedDataMap));
 
-        new CMTablePrefs(session.app().getPreferencesRepository(), 
"objEntity/attributeTable")
+        new CMTablePrefs(session.app().getPrefsRepository(), 
"objEntity/attributeTable")
                 .bind(table, minSizes, ObjAttributeTableModel.OBJ_ATTRIBUTE);
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
index 717b2dd67..45937608d 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
@@ -67,7 +67,7 @@ public class ObjEntityPropertiesView extends ProjectPanel 
implements ObjEntityDi
 
         splitPane.setOneTouchExpandable(true);
         splitPane.setResizeWeight(0.5);
-        new CMSplitPanePrefs(app.getPreferencesRepository(), 
"objEntity/splitPane").bind(splitPane, -1);
+        new CMSplitPanePrefs(app.getPrefsRepository(), 
"objEntity/splitPane").bind(splitPane, -1);
         add(splitPane);
 
         toolBar.setFloatable(false);
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
index d2fbdaf1e..e224efe5e 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
@@ -276,7 +276,7 @@ public class ObjRelationshipPanel extends JPanel implements 
ObjEntityDisplayList
         deleteRulesCombo.setSelectedIndex(0); // Default to the first value
         col.setCellEditor(new CMComboBoxCellEditor(deleteRulesCombo));
 
-        new CMTablePrefs(session.app().getPreferencesRepository(), 
"objEntity/relationshipTable")
+        new CMTablePrefs(session.app().getPrefsRepository(), 
"objEntity/relationshipTable")
                 .bind(table, null, ObjRelationshipTableModel.REL_NAME);
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
index 22aef111c..6422d91a7 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
@@ -287,7 +287,7 @@ public class ProcedureParameterTab extends ProjectPanel 
implements ProcedurePara
         moveUp.setEnabled(false);
         moveDown.setEnabled(false);
 
-        new CMTablePrefs(app.getPreferencesRepository(), 
"procedure/parameterTable").bind(table, null);
+        new CMTablePrefs(app.getPrefsRepository(), 
"procedure/parameterTable").bind(table, null);
     }
 
     public void procedureParameterAdded(ProcedureParameterEvent e) {
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
index 79c10a1b6..e836bbd3c 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
@@ -81,7 +81,7 @@ public class SelectQueryOrderingTab extends ProjectPanel {
 
         //As of CAY-888 #3 main pane is now a JSplitPane. Top component is a 
bit larger.
         JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
-        new CMSplitPanePrefs(app.getPreferencesRepository(), 
"selectQuery/orderingSplit").bind(mainPanel, defLocation);
+        new CMSplitPanePrefs(app.getPrefsRepository(), 
"selectQuery/orderingSplit").bind(mainPanel, defLocation);
 
         mainPanel.setTopComponent(createEditorPanel());
         mainPanel.setBottomComponent(createSelectorPanel());
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
index 7c99300dd..0f4afabbb 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
@@ -92,7 +92,7 @@ public class SQLTemplatePrefetchTab extends ProjectPanel {
 
         //As of CAY-888 #3 main pane is now a JSplitPane. Top component is a 
bit larger.
         JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
-        new CMSplitPanePrefs(app.getPreferencesRepository(), 
"sqlTemplate/prefetchSplit").bind(mainPanel, defLocation);
+        new CMSplitPanePrefs(app.getPrefsRepository(), 
"sqlTemplate/prefetchSplit").bind(mainPanel, defLocation);
 
         mainPanel.setTopComponent(createEditorPanel());
         mainPanel.setBottomComponent(createSelectorPanel());
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
index 5e0784f03..941651044 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
@@ -126,7 +126,7 @@ public class WelcomeScreen extends AppPanel implements 
RecentFileListener, Recen
 
     @Override
     public void recentFileListChanged() {
-        List<File> arr = new 
RecentProjectsPrefs(app.getPreferencesRepository()).getFiles();
+        List<File> arr = new 
RecentProjectsPrefs(app.getPrefsLocator()).getFiles();
         recentProjectsList.setModel(new RecentFileListModel(arr));
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriterTest.java
 
b/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriterTest.java
index f0a89e8cf..02b48fa90 100644
--- 
a/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriterTest.java
+++ 
b/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/mcp/McpHandshakeWriterTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.modeler.mcp;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
 
@@ -36,10 +37,11 @@ public class McpHandshakeWriterTest {
 
     // Unique per test method - keeps parallel runs and prior aborted runs 
from colliding.
     private final String nonce = UUID.randomUUID().toString().replace("-", "");
+    private final PrefsLocator locator = new PrefsLocator();
 
     @AfterEach
     public void cleanup() throws BackingStoreException {
-        Preferences node = 
Preferences.userRoot().node(McpHandshakeWriter.NODE_PREFIX + nonce);
+        Preferences node = locator.handshakeNode(nonce);
         if (node != null) {
             node.removeNode();
             Preferences.userRoot().flush();
@@ -51,7 +53,7 @@ public class McpHandshakeWriterTest {
         String[] argv = {"--mcp-handshake", nonce, "/path/to/cayenne-foo.xml"};
         long before = System.currentTimeMillis() - 1;
 
-        McpHandshakeWriter.write(nonce, argv, "/path/to/cayenne-foo.xml");
+        McpHandshakeWriter.write(locator, nonce, argv, 
"/path/to/cayenne-foo.xml");
 
         Preferences prefs = pollForNode();
 
@@ -72,14 +74,14 @@ public class McpHandshakeWriterTest {
 
     @Test
     public void nullArgvWritesEmptyArgsString() throws Exception {
-        McpHandshakeWriter.write(nonce, null, "/p");
+        McpHandshakeWriter.write(locator, nonce, null, "/p");
         Preferences prefs = pollForNode();
         assertEquals("", prefs.get("args", null));
     }
 
     @Test
     public void nullProjectPathWritesEmptyString() throws Exception {
-        McpHandshakeWriter.write(nonce, new String[]{"x"}, null);
+        McpHandshakeWriter.write(locator, nonce, new String[]{"x"}, null);
         Preferences prefs = pollForNode();
         assertEquals("", prefs.get("projectPath", null));
     }
@@ -90,14 +92,11 @@ public class McpHandshakeWriterTest {
      * race the writer's sequential puts.
      */
     private Preferences pollForNode() throws Exception {
-        String fullPath = McpHandshakeWriter.NODE_PREFIX + nonce;
+        Preferences node = locator.handshakeNode(nonce);
         long deadline = System.currentTimeMillis() + 5_000;
         while (System.currentTimeMillis() < deadline) {
-            if (Preferences.userRoot().nodeExists(fullPath)) {
-                Preferences node = Preferences.userRoot().node(fullPath);
-                if (hasAllKeys(node)) {
-                    return node;
-                }
+            if (hasAllKeys(node)) {
+                return node;
             }
             Thread.sleep(25);
         }

Reply via email to