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

commit 488009ac220f5c2a74f73a3b0ac6211d46c1fc5e
Author: Andrus Adamchik <[email protected]>
AuthorDate: Sat May 23 17:08:59 2026 -0400

    CAY-2949 CayenneModeler MCP: dbimport_run tool
    
    preliminary refactoring - sharing preferences between MCP and the Modeler
---
 cayenne-mcp-server/pom.xml                         |   6 +
 .../org/apache/cayenne/mcp/CayenneMcpServer.java   |   4 +-
 .../apache/cayenne/mcp/tools/cgen/CgenRunTool.java |   2 +-
 .../mcp/tools/openproject/HandshakeWatcher.java    |  64 +++--
 .../mcp/tools/openproject/OpenProjectTool.java     |  14 +-
 .../tools/openproject/HandshakeWatcherTest.java    |  40 ++-
 .../mcp/tools/openproject/OpenProjectStubIT.java   |   3 +-
 .../openproject/OpenProjectValidationTest.java     |   3 +-
 modeler/cayenne-modeler-prefs/pom.xml              |  49 ++++
 .../apache/cayenne/modeler/pref/PrefsAdapter.java} |   4 +-
 .../apache/cayenne/modeler/pref/PrefsLocator.java  |  39 ++-
 .../modeler/pref/adapters/ClasspathPrefs.java      |  12 +-
 .../modeler/pref/adapters/DBConnectorPrefs.java    |   8 +-
 .../modeler/pref/dbconnector/DBConnector.java      | 150 +++++++++++
 .../modeler/pref}/dbconnector/DBConnectors.java    |   2 +-
 modeler/cayenne-modeler/pom.xml                    |  47 ++--
 .../org/apache/cayenne/modeler/Application.java    |   4 +-
 .../cayenne/modeler/dbconnector/DBConnector.java   | 277 ---------------------
 .../modeler/dbconnector/DBConnectorFactory.java    | 156 ++++++++++++
 .../modeler/pref/adapters/CMTablePrefs.java        |   4 +-
 .../pref/adapters/ComponentGeometryPrefs.java      |   4 +-
 .../modeler/pref/adapters/DBGeneratorPrefs.java    |   4 +-
 .../modeler/pref/adapters/DataMapPrefs.java        |   6 +-
 .../modeler/pref/adapters/DataNodePrefs.java       |   4 +-
 .../modeler/pref/adapters/FileChooserPrefs.java    |   4 +-
 .../modeler/pref/adapters/GeneralPrefs.java        |   4 +-
 .../modeler/pref/adapters/LogConsolePrefs.java     |   4 +-
 .../modeler/pref/adapters/ProjectPrefs.java        |   4 +-
 .../modeler/pref/adapters/RecentProjectsPrefs.java |   4 +-
 .../modeler/pref/adapters/SplitPanePrefs.java      |   4 +-
 .../modeler/ui/action/DBConnectionAwareAction.java |   2 +-
 .../modeler/ui/datasource/DataSourceDialog.java    |  10 +-
 .../modeler/ui/dbgen/DBGeneratorOptionsDialog.java |   6 +-
 .../modeler/ui/dbmerge/MergerOptionsDialog.java    |   9 +-
 .../preferences/dbconnector/DBConnectorEditor.java |   2 +-
 .../dbconnector/DBConnectorPrefsPanel.java         |   4 +-
 .../creator/DBConnectorCreatorDialog.java          |   2 +-
 .../duplicator/DBConnectorDuplicatorDialog.java    |   2 +-
 .../datamap/dbimport/DatabaseSchemaLoader.java     |  13 +-
 .../dbimport/action/LoadDbSchemaAction.java        |   2 +-
 .../dbimport/action/ModelerDbImportAction.java     |   5 +-
 .../dbimport/runner/ModelerDbLoaderContext.java    |   7 +-
 .../editor/datanode/DataNodeEditorPanel.java       |   2 +-
 .../editor/datanode/jdbc/JDBCDataSourcePanel.java  |   2 +-
 modeler/pom.xml                                    |   1 +
 45 files changed, 555 insertions(+), 444 deletions(-)

diff --git a/cayenne-mcp-server/pom.xml b/cayenne-mcp-server/pom.xml
index 7eca6077f..cf8f52b54 100644
--- a/cayenne-mcp-server/pom.xml
+++ b/cayenne-mcp-server/pom.xml
@@ -44,6 +44,12 @@
             <artifactId>mcp</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.cayenne.modeler</groupId>
+            <artifactId>cayenne-modeler-prefs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.cayenne</groupId>
             <artifactId>cayenne-cgen</artifactId>
diff --git 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/CayenneMcpServer.java 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/CayenneMcpServer.java
index 6755fb5de..f0eb6971d 100644
--- 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/CayenneMcpServer.java
+++ 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/CayenneMcpServer.java
@@ -24,6 +24,7 @@ import io.modelcontextprotocol.server.McpServer;
 import io.modelcontextprotocol.server.McpSyncServer;
 import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
 import io.modelcontextprotocol.spec.McpSchema;
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.apache.cayenne.mcp.tools.cgen.CgenRunTool;
 import org.apache.cayenne.mcp.tools.openproject.OpenProjectTool;
 import org.slf4j.Logger;
@@ -49,12 +50,13 @@ public class CayenneMcpServer {
                 .get();
 
         StdioServerTransportProvider transport = new 
StdioServerTransportProvider(jsonMapper, in, out);
+        PrefsLocator prefsLocator = new PrefsLocator();
 
         McpSyncServer server = McpServer.sync(transport)
                 .serverInfo("cayenne-mcp-server", version)
                 
.capabilities(McpSchema.ServerCapabilities.builder().tools(true).build())
                 .tools(CgenRunTool.spec(jsonMapper))
-                .tools(OpenProjectTool.spec(jsonMapper))
+                .tools(OpenProjectTool.spec(jsonMapper, prefsLocator))
                 .build();
 
         Runtime.getRuntime().addShutdownHook(new Thread(() -> {
diff --git 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/cgen/CgenRunTool.java
 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/cgen/CgenRunTool.java
index 50a247a79..2f766baab 100644
--- 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/cgen/CgenRunTool.java
+++ 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/cgen/CgenRunTool.java
@@ -166,7 +166,7 @@ public class CgenRunTool {
                             + "Configure code generation for this DataMap in 
CayenneModeler before invoking the tool.",
                     new CgenValidation(true, true, false, null, null));
         }
-        CgenConfiguration cgenConfig = configList.getAll().get(0);
+        CgenConfiguration cgenConfig = configList.getAll().getFirst();
 
         // Step 5 — destDir specified?
         Path destDir = cgenConfig.buildOutputPath();
diff --git 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcher.java
 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcher.java
index 041bbc448..358987f4b 100644
--- 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcher.java
+++ 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcher.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.mcp.tools.openproject;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,21 +36,20 @@ import java.util.prefs.Preferences;
  *
  * @since 5.0
  */
-final class HandshakeWatcher {
+class HandshakeWatcher {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(HandshakeWatcher.class);
 
-    /** Must match {@code McpHandshakeWriter.NODE_PREFIX} on the Modeler side. 
*/
-    static final String NODE_PREFIX = 
"/org/apache/cayenne/modeler/mcp-handshake";
-
     private static final long POLL_INTERVAL_MS = 200L;
     private static final Duration STALE_NODE_TTL = Duration.ofHours(24);
 
-    enum Outcome { HANDSHAKE_RECEIVED, SPAWNED_PROCESS_EXITED, TIMEOUT }
+    enum Outcome {HANDSHAKE_RECEIVED, SPAWNED_PROCESS_EXITED, TIMEOUT}
 
-    record WatchResult(Outcome outcome, HandshakeData data, long waitMs) {}
+    record WatchResult(Outcome outcome, HandshakeData data, long waitMs) {
+    }
 
-    record HandshakeData(long pid, String startedAt, String 
resolvedProjectPath) {}
+    record HandshakeData(long pid, String startedAt, String 
resolvedProjectPath) {
+    }
 
     private HandshakeWatcher() {
     }
@@ -59,16 +59,20 @@ final class HandshakeWatcher {
      * the spawned process exits (when that signal is meaningful) or the 
timeout is hit.
      * Regardless of outcome, the nonce's subnode is removed and stale 
siblings are pruned.
      */
-    static WatchResult await(String nonce, BooleanSupplier 
spawnedProcessAlive, Duration timeout) {
+    public static WatchResult await(
+            String nonce,
+            BooleanSupplier spawnedProcessAlive,
+            Duration timeout,
+            PrefsLocator locator) {
+
         long start = System.currentTimeMillis();
         long deadline = start + timeout.toMillis();
-        String nodePath = NODE_PREFIX + "/" + nonce;
 
-        WatchResult result = null;
+        WatchResult result;
         try {
             while (true) {
-                if (nodeExists(nodePath)) {
-                    HandshakeData data = readHandshake(nodePath);
+                if (locator.handshakeNodeExists(nonce)) {
+                    HandshakeData data = 
readHandshake(locator.handshakeNode(nonce));
                     long waitMs = System.currentTimeMillis() - start;
                     result = new WatchResult(Outcome.HANDSHAKE_RECEIVED, data, 
waitMs);
                     break;
@@ -96,36 +100,26 @@ final class HandshakeWatcher {
                 }
             }
         } finally {
-            removeNode(nodePath);
-            pruneStaleSiblings();
+            removeNode(locator, nonce);
+            pruneStaleSiblings(locator);
         }
         return result;
     }
 
-    private static boolean nodeExists(String absolutePath) {
-        try {
-            return Preferences.userRoot().nodeExists(absolutePath);
-        } catch (BackingStoreException e) {
-            LOGGER.warn("Failed to query preferences for {}: {}", 
absolutePath, e.toString());
-            return false;
-        }
-    }
-
-    private static HandshakeData readHandshake(String absolutePath) {
-        Preferences node = Preferences.userRoot().node(absolutePath);
+    private static HandshakeData readHandshake(Preferences node) {
         long pid = node.getLong("pid", -1L);
         String startedAt = node.get("startedAt", null);
         String resolvedProjectPath = node.get("projectPath", null);
         return new HandshakeData(pid, startedAt, resolvedProjectPath);
     }
 
-    private static void removeNode(String absolutePath) {
+    private static void removeNode(PrefsLocator locator, String nonce) {
         try {
-            if (Preferences.userRoot().nodeExists(absolutePath)) {
-                Preferences.userRoot().node(absolutePath).removeNode();
+            if (locator.handshakeNodeExists(nonce)) {
+                locator.handshakeNode(nonce).removeNode();
             }
         } catch (BackingStoreException | IllegalStateException e) {
-            LOGGER.warn("Failed to remove handshake node {}: {}", 
absolutePath, e.toString());
+            LOGGER.warn("Failed to remove handshake node for nonce {}: {}", 
nonce, e.toString());
         }
     }
 
@@ -134,13 +128,13 @@ final class HandshakeWatcher {
      * Belt-and-suspenders cleanup against an MCP server that crashed between 
launching
      * the Modeler and reading the handshake.
      */
-    private static void pruneStaleSiblings() {
+    private static void pruneStaleSiblings(PrefsLocator locator) {
+        if (!locator.handshakeRootNodeExists()) {
+            return;
+        }
+
         try {
-            Preferences root = Preferences.userRoot();
-            if (!root.nodeExists(NODE_PREFIX)) {
-                return;
-            }
-            Preferences parent = root.node(NODE_PREFIX);
+            Preferences parent = locator.handshakeRootNode();
             Instant cutoff = Instant.now().minus(STALE_NODE_TTL);
             for (String child : parent.childrenNames()) {
                 Preferences childNode = parent.node(child);
diff --git 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectTool.java
 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectTool.java
index ced9e3a21..82de61236 100644
--- 
a/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectTool.java
+++ 
b/cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectTool.java
@@ -34,6 +34,8 @@ import 
org.apache.cayenne.mcp.tools.openproject.protocol.OpenProjectResolved;
 import org.apache.cayenne.mcp.tools.openproject.protocol.OpenProjectResult;
 import org.apache.cayenne.mcp.tools.openproject.protocol.OpenProjectValidation;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
+
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -57,8 +59,14 @@ public class OpenProjectTool {
 
     static final Duration HANDSHAKE_TIMEOUT = Duration.ofSeconds(15);
 
-    public static McpServerFeatures.SyncToolSpecification spec(McpJsonMapper 
jsonMapper) {
-        OpenProjectTool tool = new OpenProjectTool();
+    private final PrefsLocator prefsLocator;
+
+    public OpenProjectTool(PrefsLocator prefsLocator) {
+        this.prefsLocator = prefsLocator;
+    }
+
+    public static McpServerFeatures.SyncToolSpecification spec(McpJsonMapper 
jsonMapper, PrefsLocator prefsLocator) {
+        OpenProjectTool tool = new OpenProjectTool(prefsLocator);
 
         McpSchema.Tool descriptor = new McpSchema.Tool(
                 NAME,
@@ -172,7 +180,7 @@ public class OpenProjectTool {
                 launch.command());
 
         // Step 5 — wait for the handshake.
-        WatchResult watch = HandshakeWatcher.await(nonce, () -> true, 
HANDSHAKE_TIMEOUT);
+        WatchResult watch = HandshakeWatcher.await(nonce, () -> true, 
HANDSHAKE_TIMEOUT, prefsLocator);
 
         return switch (watch.outcome()) {
             case HANDSHAKE_RECEIVED -> {
diff --git 
a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcherTest.java
 
b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcherTest.java
index a429405a6..ea553fa17 100644
--- 
a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcherTest.java
+++ 
b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/HandshakeWatcherTest.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.mcp.tools.openproject;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.apache.cayenne.mcp.tools.openproject.HandshakeWatcher.Outcome;
 import org.apache.cayenne.mcp.tools.openproject.HandshakeWatcher.WatchResult;
 import org.junit.jupiter.api.AfterEach;
@@ -40,27 +41,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 public class HandshakeWatcherTest {
 
     private static final BooleanSupplier ALIVE = () -> true;
+    private static final PrefsLocator LOCATOR = new PrefsLocator();
     private final String nonce = "test-" + 
UUID.randomUUID().toString().replace("-", "");
 
     @AfterEach
     public void cleanup() throws BackingStoreException {
-        Preferences root = Preferences.userRoot();
-        if (root.nodeExists(HandshakeWatcher.NODE_PREFIX + "/" + nonce)) {
-            root.node(HandshakeWatcher.NODE_PREFIX + "/" + nonce).removeNode();
+        if (LOCATOR.handshakeNodeExists(nonce)) {
+            LOCATOR.handshakeNode(nonce).removeNode();
         }
     }
 
     @Test
     public void handshakeReceivedReadsPidAndPath() throws 
BackingStoreException {
-        Preferences node = Preferences
-                .userRoot()
-                .node(HandshakeWatcher.NODE_PREFIX + "/" + nonce);
+        Preferences node = LOCATOR.handshakeNode(nonce);
         node.putLong("pid", 4242L);
         node.put("startedAt", "2026-05-17T10:00:00Z");
         node.put("projectPath", "/abs/cayenne-project.xml");
         node.flush();
 
-        WatchResult result = HandshakeWatcher.await(nonce, ALIVE, 
Duration.ofSeconds(2));
+        WatchResult result = HandshakeWatcher.await(nonce, ALIVE, 
Duration.ofSeconds(2), LOCATOR);
 
         assertEquals(Outcome.HANDSHAKE_RECEIVED, result.outcome());
         assertNotNull(result.data());
@@ -70,12 +69,12 @@ public class HandshakeWatcherTest {
         assertTrue(result.waitMs() >= 0);
 
         // Watcher must remove the node after reading.
-        
assertFalse(Preferences.userRoot().nodeExists(HandshakeWatcher.NODE_PREFIX + 
"/" + nonce));
+        assertFalse(LOCATOR.handshakeNodeExists(nonce));
     }
 
     @Test
     public void timeoutOnMissingHandshake() {
-        WatchResult result = HandshakeWatcher.await(nonce, ALIVE, 
Duration.ofMillis(400));
+        WatchResult result = HandshakeWatcher.await(nonce, ALIVE, 
Duration.ofMillis(400), LOCATOR);
 
         assertEquals(Outcome.TIMEOUT, result.outcome());
         assertNull(result.data());
@@ -97,7 +96,7 @@ public class HandshakeWatcherTest {
         }, "test-killer").start();
 
         long start = System.currentTimeMillis();
-        WatchResult result = HandshakeWatcher.await(nonce, alive::get, 
Duration.ofSeconds(10));
+        WatchResult result = HandshakeWatcher.await(nonce, alive::get, 
Duration.ofSeconds(10), LOCATOR);
         long elapsed = System.currentTimeMillis() - start;
 
         assertEquals(Outcome.SPAWNED_PROCESS_EXITED, result.outcome());
@@ -111,30 +110,27 @@ public class HandshakeWatcherTest {
         String freshNonce = "test-fresh-" + 
UUID.randomUUID().toString().replace("-", "");
         String staleNonce = "test-stale-" + 
UUID.randomUUID().toString().replace("-", "");
         try {
-            Preferences fresh = Preferences.userRoot()
-                    .node(HandshakeWatcher.NODE_PREFIX + "/" + freshNonce);
+            Preferences fresh = LOCATOR.handshakeNode(freshNonce);
             fresh.put("startedAt", Instant.now().toString());
             fresh.flush();
 
-            Preferences stale = Preferences.userRoot()
-                    .node(HandshakeWatcher.NODE_PREFIX + "/" + staleNonce);
+            Preferences stale = LOCATOR.handshakeNode(staleNonce);
             stale.put("startedAt", 
Instant.now().minus(Duration.ofDays(2)).toString());
             stale.flush();
 
             // Trigger pruning by running the watcher with a missing-handshake 
nonce.
-            HandshakeWatcher.await(nonce, ALIVE, Duration.ofMillis(200));
+            HandshakeWatcher.await(nonce, ALIVE, Duration.ofMillis(200), 
LOCATOR);
 
-            
assertTrue(Preferences.userRoot().nodeExists(HandshakeWatcher.NODE_PREFIX + "/" 
+ freshNonce),
+            assertTrue(LOCATOR.handshakeNodeExists(freshNonce),
                     "Recent sibling must be preserved");
-            
assertFalse(Preferences.userRoot().nodeExists(HandshakeWatcher.NODE_PREFIX + 
"/" + staleNonce),
+            assertFalse(LOCATOR.handshakeNodeExists(staleNonce),
                     "Stale sibling must be pruned");
         } finally {
-            Preferences root = Preferences.userRoot();
-            if (root.nodeExists(HandshakeWatcher.NODE_PREFIX + "/" + 
freshNonce)) {
-                root.node(HandshakeWatcher.NODE_PREFIX + "/" + 
freshNonce).removeNode();
+            if (LOCATOR.handshakeNodeExists(freshNonce)) {
+                LOCATOR.handshakeNode(freshNonce).removeNode();
             }
-            if (root.nodeExists(HandshakeWatcher.NODE_PREFIX + "/" + 
staleNonce)) {
-                root.node(HandshakeWatcher.NODE_PREFIX + "/" + 
staleNonce).removeNode();
+            if (LOCATOR.handshakeNodeExists(staleNonce)) {
+                LOCATOR.handshakeNode(staleNonce).removeNode();
             }
         }
     }
diff --git 
a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectStubIT.java
 
b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectStubIT.java
index 72a3a9919..6a32d24f9 100644
--- 
a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectStubIT.java
+++ 
b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectStubIT.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.mcp.tools.openproject;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.apache.cayenne.mcp.tools.openproject.HandshakeWatcher.Outcome;
 import org.apache.cayenne.mcp.tools.openproject.HandshakeWatcher.WatchResult;
 import org.apache.cayenne.mcp.tools.openproject.ModelerLauncher.LaunchResult;
@@ -59,7 +60,7 @@ public class OpenProjectStubIT {
 
         try {
             WatchResult watch = HandshakeWatcher.await(
-                    nonce, () -> launch.process().isAlive(), 
Duration.ofSeconds(15));
+                    nonce, () -> launch.process().isAlive(), 
Duration.ofSeconds(15), new PrefsLocator());
 
             assertEquals(Outcome.HANDSHAKE_RECEIVED, watch.outcome(),
                     "expected stub to write handshake within 15s");
diff --git 
a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectValidationTest.java
 
b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectValidationTest.java
index f17c91057..b13e12c2a 100644
--- 
a/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectValidationTest.java
+++ 
b/cayenne-mcp-server/src/test/java/org/apache/cayenne/mcp/tools/openproject/OpenProjectValidationTest.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.mcp.tools.openproject;
 
+import org.apache.cayenne.modeler.pref.PrefsLocator;
 import org.apache.cayenne.mcp.tools.openproject.protocol.OpenProjectErrorCode;
 import org.apache.cayenne.mcp.tools.openproject.protocol.OpenProjectResult;
 import org.junit.jupiter.api.Test;
@@ -28,7 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 
 public class OpenProjectValidationTest {
 
-    private final OpenProjectTool tool = new OpenProjectTool();
+    private final OpenProjectTool tool = new OpenProjectTool(new 
PrefsLocator());
 
     @Test
     public void projectNotFound() {
diff --git a/modeler/cayenne-modeler-prefs/pom.xml 
b/modeler/cayenne-modeler-prefs/pom.xml
new file mode 100644
index 000000000..174e489d3
--- /dev/null
+++ b/modeler/cayenne-modeler-prefs/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+       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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.cayenne.modeler</groupId>
+        <artifactId>cayenne-modeler-parent</artifactId>
+        <version>5.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>cayenne-modeler-prefs</artifactId>
+    <name>cayenne-modeler-prefs: Shared Modeler Preferences API</name>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cayenne</groupId>
+            <artifactId>cayenne</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceAdapter.java
 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PrefsAdapter.java
similarity index 92%
rename from 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceAdapter.java
rename to 
modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PrefsAdapter.java
index ce0667f25..3fb1d3952 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceAdapter.java
+++ 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PrefsAdapter.java
@@ -24,11 +24,11 @@ import java.util.prefs.Preferences;
 /**
  * Superclass of objects linking preferences with components.
  */
-public abstract class PreferenceAdapter {
+public abstract class PrefsAdapter {
 
     protected final Preferences prefs;
 
-    protected PreferenceAdapter(Preferences prefs) {
+    protected PrefsAdapter(Preferences prefs) {
         this.prefs = prefs;
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
similarity index 75%
rename from 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
rename to 
modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
index a466ddf40..73897618f 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
+++ 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PrefsLocator.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.pref;
 
+import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 
 /**
@@ -82,13 +83,39 @@ public final class PrefsLocator {
         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);
     }
+
+    /**
+     * Returns the handshake namespace root node. Only call this after 
confirming the
+     * node exists via {@link #handshakeRootNodeExists()}.
+     */
+    public Preferences handshakeRootNode() {
+        return root.node(HANDSHAKE_ROOT);
+    }
+
+    /**
+     * Returns {@code true} if the per-nonce handshake node exists without 
creating it.
+     * Returns {@code false} if the backing store cannot be queried.
+     */
+    public boolean handshakeNodeExists(String nonce) {
+        try {
+            return root.nodeExists(HANDSHAKE_ROOT + "/" + nonce);
+        } catch (BackingStoreException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns {@code true} if the handshake namespace root node exists 
without creating it.
+     * Returns {@code false} if the backing store cannot be queried.
+     */
+    public boolean handshakeRootNodeExists() {
+        try {
+            return root.nodeExists(HANDSHAKE_ROOT);
+        } catch (BackingStoreException e) {
+            return false;
+        }
+    }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ClasspathPrefs.java
 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/adapters/ClasspathPrefs.java
similarity index 88%
rename from 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ClasspathPrefs.java
rename to 
modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/adapters/ClasspathPrefs.java
index c514f3513..87e868658 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ClasspathPrefs.java
+++ 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/adapters/ClasspathPrefs.java
@@ -19,9 +19,8 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -29,9 +28,7 @@ import java.util.List;
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 
-public final class ClasspathPrefs extends PreferenceAdapter {
-
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(ClasspathPrefs.class);
+public final class ClasspathPrefs extends PrefsAdapter {
 
     public static final String NODE = "classpath";
 
@@ -84,8 +81,7 @@ public final class ClasspathPrefs extends PreferenceAdapter {
         try {
             return prefs.keys();
         } catch (BackingStoreException e) {
-            LOGGER.info("Error loading preferences", e);
-            return new String[0];
+            throw new CayenneRuntimeException("Error loading classpath 
preferences", e);
         }
     }
 }
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBConnectorPrefs.java
 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBConnectorPrefs.java
similarity index 94%
rename from 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBConnectorPrefs.java
rename to 
modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBConnectorPrefs.java
index 4259f3729..21c42bb34 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBConnectorPrefs.java
+++ 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBConnectorPrefs.java
@@ -20,9 +20,9 @@
 package org.apache.cayenne.modeler.pref.adapters;
 
 import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
-import org.apache.cayenne.modeler.dbconnector.DBConnectors;
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnectors;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
@@ -31,7 +31,7 @@ import java.util.prefs.Preferences;
  * Loads {@link DBConnectors} from the user prefs and binds the registry's
  * change events to the prefs node, so registry mutations are mirrored to disk.
  */
-public class DBConnectorPrefs extends PreferenceAdapter {
+public class DBConnectorPrefs extends PrefsAdapter {
 
     public static final String NODE = "dbConnectors";
 
diff --git 
a/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/dbconnector/DBConnector.java
 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/dbconnector/DBConnector.java
new file mode 100644
index 000000000..b5db35869
--- /dev/null
+++ 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/dbconnector/DBConnector.java
@@ -0,0 +1,150 @@
+/*****************************************************************
+ *   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.dbconnector;
+
+import org.apache.cayenne.configuration.DataSourceDescriptor;
+import org.apache.cayenne.util.Util;
+
+/**
+ * Configuration record for a named database connection profile stored in user 
preferences.
+ * Holds the five connection parameters (adapter, driver, url, user, 
password). Runtime
+ * operations (creating a live {@code DataSource} or {@code DbAdapter}) are in
+ * {@code DBConnectorFactory} in the Modeler module.
+ */
+public class DBConnector {
+
+    private static final String EMPTY_STRING = "";
+    public static final String DB_ADAPTER_PROPERTY = "dbAdapter";
+    public static final String JDBC_DRIVER_PROPERTY = "jdbcDriver";
+    public static final String PASSWORD_PROPERTY = "password";
+    public static final String URL_PROPERTY = "url";
+    public static final String USER_NAME_PROPERTY = "userName";
+
+    private String dbAdapter;
+    private String jdbcDriver;
+    private String password;
+    private String url;
+    private String userName;
+
+    public String getDbAdapter() {
+        return dbAdapter;
+    }
+
+    public void setDbAdapter(final String dbAdapter) {
+        this.dbAdapter = dbAdapter;
+    }
+
+    public String getJdbcDriver() {
+        return jdbcDriver;
+    }
+
+    public void setJdbcDriver(final String jdbcDriver) {
+        this.jdbcDriver = jdbcDriver;
+    }
+
+    public String getPassword() {
+        return password == null ? EMPTY_STRING : password;
+    }
+
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(final String url) {
+        this.url = url;
+    }
+
+    public String getUserName() {
+        return userName == null ? EMPTY_STRING : userName;
+    }
+
+    public void setUserName(final String userName) {
+        this.userName = userName;
+    }
+
+    /**
+     * Copies this connector's values into another {@link DBConnector}.
+     * Returns {@code true} if any field changed.
+     */
+    public boolean copyTo(DBConnector connector) {
+        boolean updated = false;
+
+        if (!Util.nullSafeEquals(connector.getUrl(), getUrl())) {
+            connector.setUrl(getUrl());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(connector.getUserName(), getUserName())) {
+            connector.setUserName(getUserName());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(connector.getPassword(), getPassword())) {
+            connector.setPassword(getPassword());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(connector.getJdbcDriver(), getJdbcDriver())) {
+            connector.setJdbcDriver(getJdbcDriver());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(connector.getDbAdapter(), getDbAdapter())) {
+            connector.setDbAdapter(getDbAdapter());
+            updated = true;
+        }
+
+        return updated;
+    }
+
+    /**
+     * Updates a {@link DataSourceDescriptor} with this connector's values.
+     * Returns {@code true} if any field changed.
+     */
+    public boolean copyTo(final DataSourceDescriptor dataSourceInfo) {
+        boolean updated = false;
+
+        if (!Util.nullSafeEquals(dataSourceInfo.getDataSourceUrl(), getUrl())) 
{
+            dataSourceInfo.setDataSourceUrl(getUrl());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(dataSourceInfo.getUserName(), getUserName())) 
{
+            dataSourceInfo.setUserName(getUserName());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(dataSourceInfo.getPassword(), getPassword())) 
{
+            dataSourceInfo.setPassword(getPassword());
+            updated = true;
+        }
+
+        if (!Util.nullSafeEquals(dataSourceInfo.getJdbcDriver(), 
getJdbcDriver())) {
+            dataSourceInfo.setJdbcDriver(getJdbcDriver());
+            updated = true;
+        }
+
+        return updated;
+    }
+}
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnectors.java
 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/dbconnector/DBConnectors.java
similarity index 97%
rename from 
modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnectors.java
rename to 
modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/dbconnector/DBConnectors.java
index 57534ea5a..b694df69b 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnectors.java
+++ 
b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/dbconnector/DBConnectors.java
@@ -17,7 +17,7 @@
  *  under the License.
  ****************************************************************/
 
-package org.apache.cayenne.modeler.dbconnector;
+package org.apache.cayenne.modeler.pref.dbconnector;
 
 import org.apache.cayenne.modeler.pref.adapters.DBConnectorPrefs;
 
diff --git a/modeler/cayenne-modeler/pom.xml b/modeler/cayenne-modeler/pom.xml
index 5936a08cd..b690f264a 100644
--- a/modeler/cayenne-modeler/pom.xml
+++ b/modeler/cayenne-modeler/pom.xml
@@ -32,68 +32,63 @@
        <packaging>jar</packaging>
 
        <dependencies>
-
-               <dependency>
-                       <groupId>org.slf4j</groupId>
-                       <artifactId>slf4j-api</artifactId>
-               </dependency>
-
-               <dependency>
-                       <groupId>com.jgoodies</groupId>
-                       <artifactId>forms</artifactId>
-               </dependency>
-
-               <dependency>
-                       <groupId>com.jgoodies</groupId>
-                       <artifactId>jgoodies-looks</artifactId>
-               </dependency>
-
                <dependency>
                        <groupId>org.apache.cayenne</groupId>
                        <artifactId>cayenne</artifactId>
                        <version>${project.version}</version>
                </dependency>
-
                <dependency>
                        <groupId>org.apache.cayenne</groupId>
                        <artifactId>cayenne-project</artifactId>
                        <version>${project.version}</version>
                </dependency>
-
                <dependency>
                        <groupId>org.apache.cayenne</groupId>
                        <artifactId>cayenne-cgen</artifactId>
                        <version>${project.version}</version>
                </dependency>
-
                <dependency>
                        <groupId>org.apache.cayenne</groupId>
                        <artifactId>cayenne-dbsync</artifactId>
                        <version>${project.version}</version>
                </dependency>
-
                <dependency>
                        <groupId>org.apache.cayenne.modeler</groupId>
                        <artifactId>cayenne-wocompat</artifactId>
                        <version>${project.version}</version>
                </dependency>
-
                <dependency>
-                       <groupId>org.junit.jupiter</groupId>
-                       <artifactId>junit-jupiter</artifactId>
-                       <scope>test</scope>
+                       <groupId>org.apache.cayenne.modeler</groupId>
+                       <artifactId>cayenne-modeler-prefs</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.jgoodies</groupId>
+                       <artifactId>forms</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.jgoodies</groupId>
+                       <artifactId>jgoodies-looks</artifactId>
                </dependency>
-
                <dependency>
                        <groupId>com.fifesoft</groupId>
                        <artifactId>rsyntaxtextarea</artifactId>
                </dependency>
 
+               <!-- Test dependencies -->
+               <dependency>
+                       <groupId>org.junit.jupiter</groupId>
+                       <artifactId>junit-jupiter</artifactId>
+                       <scope>test</scope>
+               </dependency>
                <dependency>
                        <groupId>org.mockito</groupId>
                        <artifactId>mockito-core</artifactId>
                        <scope>test</scope>
                </dependency>
-
        </dependencies>
 </project>
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 d0dc916c0..8311aee3b 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
@@ -28,7 +28,7 @@ import org.apache.cayenne.dbsync.DbSyncModule;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.modeler.dbconnector.DBConnectors;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnectors;
 import org.apache.cayenne.modeler.log.ModelerLogFactory;
 import org.apache.cayenne.modeler.platform.UIInitializer;
 import org.apache.cayenne.modeler.toolkit.filechooser.FileChooserFactory;
@@ -206,7 +206,7 @@ public class Application {
         this.undoManager = new CayenneUndoManager(this);
         this.frame = new MainFrame(this);
         this.platformInit.afterFrameCreated(this);
-        
+
         // open up
         frame.onStartup();
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnector.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnector.java
deleted file mode 100644
index c0f397057..000000000
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnector.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*****************************************************************
- *   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.dbconnector;
-
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.configuration.DataSourceDescriptor;
-import org.apache.cayenne.configuration.runtime.DbAdapterFactory;
-import org.apache.cayenne.datasource.DriverDataSource;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
-import org.apache.cayenne.util.Util;
-
-import javax.sql.DataSource;
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.logging.Logger;
-
-public class DBConnector {
-
-    private static final String EMPTY_STRING = "";
-    public static final String DB_ADAPTER_PROPERTY = "dbAdapter";
-    public static final String JDBC_DRIVER_PROPERTY = "jdbcDriver";
-    public static final String PASSWORD_PROPERTY = "password";
-    public static final String URL_PROPERTY = "url";
-    public static final String USER_NAME_PROPERTY = "userName";
-
-    private String dbAdapter;
-    private String jdbcDriver;
-    private String password;
-    private String url;
-    private String userName;
-
-    private boolean allowDataSourceFailure;
-
-    public void setAllowDataSourceFailure(boolean allowDataSourceFailure) {
-        this.allowDataSourceFailure = allowDataSourceFailure;
-    }
-
-    public String getDbAdapter() {
-        return dbAdapter;
-    }
-
-    public void setDbAdapter(final String dbAdapter) {
-        this.dbAdapter = dbAdapter;
-    }
-
-    public String getJdbcDriver() {
-        return jdbcDriver;
-    }
-
-    public void setJdbcDriver(final String jdbcDriver) {
-        this.jdbcDriver = jdbcDriver;
-    }
-
-    public String getPassword() {
-        return password == null ? EMPTY_STRING : password;
-    }
-
-    public void setPassword(final String password) {
-        this.password = password;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(final String url) {
-        this.url = url;
-    }
-
-    public String getUserName() {
-        return userName == null ? EMPTY_STRING : userName;
-    }
-
-    public void setUserName(final String userName) {
-        this.userName = userName;
-    }
-
-    /**
-     * Creates a DbAdapter based on configured values.
-     */
-    public DbAdapter makeAdapter(ModelerClassLoader classLoader, 
DbAdapterFactory adapterFactory) throws Exception {
-        DataNodeDescriptor descriptor = new DataNodeDescriptor();
-        descriptor.setAdapterType(getDbAdapter());
-        DataSource dataSource = makeDataSource(classLoader);
-        return adapterFactory.createAdapter(descriptor, dataSource);
-    }
-
-    /**
-     * Returns a DataSource that uses connection information from this object.
-     * Returned DataSource is not pooling its connections. It can be wrapped in
-     * PoolManager if pooling is needed.
-     */
-    public DataSource makeDataSource(ModelerClassLoader classLoader) throws 
SQLException {
-
-        // validate...
-        if (getJdbcDriver() == null) {
-            if (allowDataSourceFailure) {
-                return new DeferredDataSource(classLoader);
-            }
-            throw new SQLException("No JDBC driver set.");
-        }
-
-        if (getUrl() == null) {
-            if (allowDataSourceFailure) {
-                return new DeferredDataSource(classLoader);
-            }
-            throw new SQLException("No DB URL set.");
-        }
-
-        if (!Util.isBlank(getPassword()) && Util.isBlank(getUserName())) {
-            throw new SQLException("No username when password is set.");
-        }
-
-        // load driver...
-        Driver driver;
-
-        try {
-            driver = classLoader.loadClass(Driver.class, 
getJdbcDriver()).getDeclaredConstructor().newInstance();
-        } catch (Throwable th) {
-            throw new SQLException("Driver load error: " + 
Util.unwindException(th).getLocalizedMessage());
-        }
-
-        return new DriverDataSource(driver, getUrl(), getUserName(), 
getPassword());
-    }
-
-    /**
-     * Updates another DBConnectionInfo with this object's values.
-     */
-    public boolean copyTo(DBConnector connector) {
-        boolean updated = false;
-
-        if (!Util.nullSafeEquals(connector.getUrl(), getUrl())) {
-            connector.setUrl(getUrl());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(connector.getUserName(), getUserName())) {
-            connector.setUserName(getUserName());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(connector.getPassword(), getPassword())) {
-            connector.setPassword(getPassword());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(connector.getJdbcDriver(), getJdbcDriver())) {
-            connector.setJdbcDriver(getJdbcDriver());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(connector.getDbAdapter(), getDbAdapter())) {
-            connector.setDbAdapter(getDbAdapter());
-            updated = true;
-        }
-
-        return updated;
-    }
-
-    /**
-     * Updates DataSourceInfo with this object's values.
-     * <p>
-     * <i>Currently doesn't set the adapter property. Need to change the UI to
-     * handle adapter via DataSourceInfo first, and then it should be safe to 
do
-     * an adapter update here. </i>
-     * </p>
-     */
-    public boolean copyTo(final DataSourceDescriptor dataSourceInfo) {
-        boolean updated = false;
-
-        if (!Util.nullSafeEquals(dataSourceInfo.getDataSourceUrl(), getUrl())) 
{
-            dataSourceInfo.setDataSourceUrl(getUrl());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(dataSourceInfo.getUserName(), getUserName())) 
{
-            dataSourceInfo.setUserName(getUserName());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(dataSourceInfo.getPassword(), getPassword())) 
{
-            dataSourceInfo.setPassword(getPassword());
-            updated = true;
-        }
-
-        if (!Util.nullSafeEquals(dataSourceInfo.getJdbcDriver(), 
getJdbcDriver())) {
-            dataSourceInfo.setJdbcDriver(getJdbcDriver());
-            updated = true;
-        }
-
-        return updated;
-    }
-
-    private class DeferredDataSource implements DataSource {
-
-        private final ModelerClassLoader classLoader;
-
-        public DeferredDataSource(ModelerClassLoader classLoader) {
-            this.classLoader = classLoader;
-        }
-
-        DataSource getDeferredDataSource() throws SQLException {
-            allowDataSourceFailure = false;
-            return makeDataSource(classLoader);
-        }
-
-        @Override
-        public Connection getConnection() throws SQLException {
-            return getDeferredDataSource().getConnection();
-        }
-
-        @Override
-        public Connection getConnection(String username, String password) 
throws SQLException {
-            return getDeferredDataSource().getConnection(username, password);
-        }
-
-        @Override
-        public PrintWriter getLogWriter() throws SQLException {
-            return getDeferredDataSource().getLogWriter();
-        }
-
-        @Override
-        public void setLogWriter(PrintWriter out) throws SQLException {
-            getDeferredDataSource().setLogWriter(out);
-        }
-
-        @Override
-        public void setLoginTimeout(int seconds) throws SQLException {
-            getDeferredDataSource().setLoginTimeout(seconds);
-        }
-
-        @Override
-        public int getLoginTimeout() throws SQLException {
-            return getDeferredDataSource().getLoginTimeout();
-        }
-
-        @Override
-        public <T> T unwrap(Class<T> iface) throws SQLException {
-            return getDeferredDataSource().unwrap(iface);
-        }
-
-        @Override
-        public boolean isWrapperFor(Class<?> iface) throws SQLException {
-            return getDeferredDataSource().isWrapperFor(iface);
-        }
-
-        @Override
-        public Logger getParentLogger() throws SQLFeatureNotSupportedException 
{
-            try {
-                return getDeferredDataSource().getParentLogger();
-            } catch (SQLException e) {
-                throw new SQLFeatureNotSupportedException(e);
-            }
-        }
-    }
-}
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnectorFactory.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnectorFactory.java
new file mode 100644
index 000000000..24c111b7b
--- /dev/null
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dbconnector/DBConnectorFactory.java
@@ -0,0 +1,156 @@
+/*****************************************************************
+ *   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.dbconnector;
+
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.runtime.DbAdapterFactory;
+import org.apache.cayenne.datasource.DriverDataSource;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
+import org.apache.cayenne.util.Util;
+
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+
+/**
+ * Creates live {@code DataSource} and {@code DbAdapter} instances from a 
{@link DBConnector}
+ * configuration, using a {@link ModelerClassLoader} to load the JDBC driver 
at runtime.
+ */
+public class DBConnectorFactory {
+
+    private final ModelerClassLoader classLoader;
+
+    public DBConnectorFactory(ModelerClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    public DbAdapter makeAdapter(DBConnector connector, DbAdapterFactory 
adapterFactory) throws Exception {
+        return makeAdapter(connector, adapterFactory, false);
+    }
+
+    public DbAdapter makeAdapter(DBConnector connector, DbAdapterFactory 
adapterFactory,
+                                 boolean allowDataSourceFailure) throws 
Exception {
+        DataNodeDescriptor descriptor = new DataNodeDescriptor();
+        descriptor.setAdapterType(connector.getDbAdapter());
+        DataSource dataSource = makeDataSource(connector, 
allowDataSourceFailure);
+        return adapterFactory.createAdapter(descriptor, dataSource);
+    }
+
+    public DataSource makeDataSource(DBConnector connector) throws 
SQLException {
+        return makeDataSource(connector, false);
+    }
+
+    public DataSource makeDataSource(DBConnector connector, boolean 
allowDataSourceFailure) throws SQLException {
+        if (connector.getJdbcDriver() == null) {
+            if (allowDataSourceFailure) {
+                return new DeferredDataSource(connector);
+            }
+            throw new SQLException("No JDBC driver set.");
+        }
+
+        if (connector.getUrl() == null) {
+            if (allowDataSourceFailure) {
+                return new DeferredDataSource(connector);
+            }
+            throw new SQLException("No DB URL set.");
+        }
+
+        if (!Util.isBlank(connector.getPassword()) && 
Util.isBlank(connector.getUserName())) {
+            throw new SQLException("No username when password is set.");
+        }
+
+        Driver driver;
+        try {
+            driver = classLoader.loadClass(Driver.class, 
connector.getJdbcDriver()).getDeclaredConstructor().newInstance();
+        } catch (Throwable th) {
+            throw new SQLException("Driver load error: " + 
Util.unwindException(th).getLocalizedMessage());
+        }
+
+        return new DriverDataSource(driver, connector.getUrl(), 
connector.getUserName(), connector.getPassword());
+    }
+
+    private class DeferredDataSource implements DataSource {
+
+        private final DBConnector connector;
+
+        DeferredDataSource(DBConnector connector) {
+            this.connector = connector;
+        }
+
+        DataSource getDelegate() throws SQLException {
+            return makeDataSource(connector, false);
+        }
+
+        @Override
+        public Connection getConnection() throws SQLException {
+            return getDelegate().getConnection();
+        }
+
+        @Override
+        public Connection getConnection(String username, String password) 
throws SQLException {
+            return getDelegate().getConnection(username, password);
+        }
+
+        @Override
+        public PrintWriter getLogWriter() throws SQLException {
+            return getDelegate().getLogWriter();
+        }
+
+        @Override
+        public void setLogWriter(PrintWriter out) throws SQLException {
+            getDelegate().setLogWriter(out);
+        }
+
+        @Override
+        public void setLoginTimeout(int seconds) throws SQLException {
+            getDelegate().setLoginTimeout(seconds);
+        }
+
+        @Override
+        public int getLoginTimeout() throws SQLException {
+            return getDelegate().getLoginTimeout();
+        }
+
+        @Override
+        public <T> T unwrap(Class<T> iface) throws SQLException {
+            return getDelegate().unwrap(iface);
+        }
+
+        @Override
+        public boolean isWrapperFor(Class<?> iface) throws SQLException {
+            return getDelegate().isWrapperFor(iface);
+        }
+
+        @Override
+        public Logger getParentLogger() throws SQLFeatureNotSupportedException 
{
+            try {
+                return getDelegate().getParentLogger();
+            } catch (SQLException e) {
+                throw new SQLFeatureNotSupportedException(e);
+            }
+        }
+    }
+}
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/CMTablePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/CMTablePrefs.java
index 7d23c14e4..90c957337 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/CMTablePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/CMTablePrefs.java
@@ -18,7 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 import org.apache.cayenne.modeler.toolkit.table.CMTable;
 
 import javax.swing.event.ChangeEvent;
@@ -31,7 +31,7 @@ import javax.swing.table.TableModel;
 import java.util.Map;
 import java.util.prefs.Preferences;
 
-public final class CMTablePrefs extends PreferenceAdapter {
+public final class CMTablePrefs extends PrefsAdapter {
 
     private static final String SORT_COLUMN_KEY = "sortColumn";
     private static final String SORT_ORDER_KEY = "sortOrder";
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ComponentGeometryPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ComponentGeometryPrefs.java
index 6acf954a6..7097c6805 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ComponentGeometryPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ComponentGeometryPrefs.java
@@ -19,14 +19,14 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.awt.*;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.util.prefs.Preferences;
 
-public final class ComponentGeometryPrefs extends PreferenceAdapter {
+public final class ComponentGeometryPrefs extends PrefsAdapter {
 
     private static final String HEIGHT_PROPERTY = "height";
     private static final String WIDTH_PROPERTY = "width";
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBGeneratorPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBGeneratorPrefs.java
index 699fef1f0..af2d0f9ee 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBGeneratorPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DBGeneratorPrefs.java
@@ -18,14 +18,14 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.util.prefs.Preferences;
 
 /**
  * Persistence for the DB Generator dialog's checkbox options.
  */
-public class DBGeneratorPrefs extends PreferenceAdapter {
+public class DBGeneratorPrefs extends PrefsAdapter {
 
     public static final String NODE = "dbGenerator";
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataMapPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataMapPrefs.java
index 83926e8c4..31da2ff49 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataMapPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataMapPrefs.java
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.util.prefs.Preferences;
 
-public final class DataMapPrefs extends PreferenceAdapter {
+public final class DataMapPrefs extends PrefsAdapter {
 
     public static final String SUPERCLASS_PACKAGE_PROPERTY = 
"superclassPackage";
     public static final String DEFAULT_SUPERCLASS_PACKAGE_SUFFIX = "auto";
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataNodePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataNodePrefs.java
index b3b449e79..b723affcc 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataNodePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/DataNodePrefs.java
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 import org.apache.cayenne.modeler.pref.PrefsCopier;
 
 import java.util.prefs.Preferences;
 
-public final class DataNodePrefs extends PreferenceAdapter {
+public final class DataNodePrefs extends PrefsAdapter {
 
     public static final String LOCAL_DATA_SOURCE_PROPERTY = "localDataSource";
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/FileChooserPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/FileChooserPrefs.java
index 1a339f489..2b345f6da 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/FileChooserPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/FileChooserPrefs.java
@@ -19,7 +19,7 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import javax.swing.JFileChooser;
 import java.awt.FileDialog;
@@ -28,7 +28,7 @@ import java.awt.event.ComponentEvent;
 import java.io.File;
 import java.util.prefs.Preferences;
 
-public final class FileChooserPrefs extends PreferenceAdapter {
+public final class FileChooserPrefs extends PrefsAdapter {
 
     private static final String PATH_PROPERTY = "path";
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/GeneralPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/GeneralPrefs.java
index 95b58f99d..55fc0a2e6 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/GeneralPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/GeneralPrefs.java
@@ -19,11 +19,11 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.util.prefs.Preferences;
 
-public final class GeneralPrefs extends PreferenceAdapter {
+public final class GeneralPrefs extends PrefsAdapter {
 
     public static final String NODE = "general";
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/LogConsolePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/LogConsolePrefs.java
index 3e371264b..70026e5f7 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/LogConsolePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/LogConsolePrefs.java
@@ -19,11 +19,11 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import java.util.prefs.Preferences;
 
-public final class LogConsolePrefs extends PreferenceAdapter {
+public final class LogConsolePrefs extends PrefsAdapter {
 
     public static final String NODE = "logConsole";
     static final String SHOW_CONSOLE = "showLogConsole";
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ProjectPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ProjectPrefs.java
index b9da3f04e..f6328ce70 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ProjectPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/ProjectPrefs.java
@@ -52,7 +52,7 @@ import 
org.apache.cayenne.modeler.event.display.ObjRelationshipDisplayEvent;
 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.PrefsAdapter;
 import org.apache.cayenne.modeler.project.ProjectSession;
 import org.apache.cayenne.util.CayenneMapEntry;
 
@@ -65,7 +65,7 @@ import java.util.prefs.Preferences;
  * Binding-style handler for the Modeler's last project selection. Loaded on 
project
  * open to restore selection, flushed on project close or Modeler close to 
persist it.
  */
-public final class ProjectPrefs extends PreferenceAdapter {
+public final class ProjectPrefs extends PrefsAdapter {
 
     private static final String EVENT_KEY = "event";
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/RecentProjectsPrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/RecentProjectsPrefs.java
index 924211b40..41f43a557 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/RecentProjectsPrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/RecentProjectsPrefs.java
@@ -19,7 +19,7 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -29,7 +29,7 @@ import java.util.List;
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 
-public final class RecentProjectsPrefs extends PreferenceAdapter {
+public final class RecentProjectsPrefs extends PrefsAdapter {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(RecentProjectsPrefs.class);
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/SplitPanePrefs.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/SplitPanePrefs.java
index 30bb7bb6d..35335ee3d 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/SplitPanePrefs.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/adapters/SplitPanePrefs.java
@@ -19,13 +19,13 @@
 
 package org.apache.cayenne.modeler.pref.adapters;
 
-import org.apache.cayenne.modeler.pref.PreferenceAdapter;
+import org.apache.cayenne.modeler.pref.PrefsAdapter;
 
 import javax.swing.*;
 import java.beans.PropertyChangeListener;
 import java.util.prefs.Preferences;
 
-public final class SplitPanePrefs extends PreferenceAdapter {
+public final class SplitPanePrefs extends PrefsAdapter {
 
     private PropertyChangeListener listener;
 
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 349396b29..6c8c90365 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
@@ -23,7 +23,7 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.toolkit.AppAction;
 import org.apache.cayenne.modeler.ui.datasource.DataSourceDialog;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.apache.cayenne.modeler.pref.adapters.DataMapPrefs;
 
 /**
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 14a604a0a..726b37cd2 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
@@ -23,8 +23,9 @@ import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
-import org.apache.cayenne.modeler.dbconnector.DBConnectors;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.dbconnector.DBConnectorFactory;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnectors;
 import org.apache.cayenne.modeler.pref.adapters.DataMapPrefs;
 import org.apache.cayenne.modeler.pref.adapters.GeneralPrefs;
 import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
@@ -175,8 +176,9 @@ public class DataSourceDialog extends ProjectDialog {
         // doing connection testing...
         try {
             try {
-                this.adapter = info.makeAdapter(classLoader, 
app.getDbAdapterFactory());
-                this.dataSource = info.makeDataSource(classLoader);
+                DBConnectorFactory factory = new 
DBConnectorFactory(classLoader);
+                this.adapter = factory.makeAdapter(info, 
app.getDbAdapterFactory());
+                this.dataSource = factory.makeDataSource(info);
             } catch (SQLException ignore) {
                 showNoConnectorDialog("Unable to load driver '" + 
info.getJdbcDriver() + "'");
                 return;
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 318676d51..500e7759f 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
@@ -27,7 +27,8 @@ import org.apache.cayenne.access.DbGenerator;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.log.NoopJdbcEventLogger;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.dbconnector.DBConnectorFactory;
 import org.apache.cayenne.modeler.pref.adapters.DBGeneratorPrefs;
 import org.apache.cayenne.modeler.toolkit.border.TopBorder;
 import org.apache.cayenne.modeler.toolkit.ProjectDialog;
@@ -105,7 +106,6 @@ public class DBGeneratorOptionsDialog extends ProjectDialog 
{
         this.tables = new TableSelectorPanel(app);
 
         this.connector = new DBConnector();
-        this.connector.setAllowDataSourceFailure(true);
         this.generatorDefaults = new 
DBGeneratorPrefs(app.getPrefsManager().projectPref(session.project(), 
DBGeneratorPrefs.NODE));
 
         // create widgets — set initial state before wiring listeners so we
@@ -259,7 +259,7 @@ public class DBGeneratorOptionsDialog extends ProjectDialog 
{
 
     private void prepareGenerator() {
         try {
-            DbAdapter adapter = connector.makeAdapter(app.getClassLoader(), 
app.getDbAdapterFactory());
+            DbAdapter adapter = new 
DBConnectorFactory(app.getClassLoader()).makeAdapter(connector, 
app.getDbAdapterFactory(), true);
             generators = new ArrayList<>();
             for (DataMap dataMap : dataMaps) {
                 generators.add(new DbGenerator(
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java
index 5bad5ae0e..6a18bc636 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java
@@ -46,7 +46,8 @@ import 
org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.dbconnector.DBConnectorFactory;
 import org.apache.cayenne.modeler.event.model.DataMapEvent;
 import org.apache.cayenne.modeler.toolkit.border.TopBorder;
 import org.apache.cayenne.modeler.toolkit.text.CMTextArea;
@@ -192,7 +193,7 @@ public class MergerOptionsDialog extends ProjectDialog {
 
     private void prepareMigrator() {
         try {
-            adapter = connectionInfo.makeAdapter(app.getClassLoader(), 
app.getDbAdapterFactory());
+            adapter = new 
DBConnectorFactory(app.getClassLoader()).makeAdapter(connectionInfo, 
app.getDbAdapterFactory());
 
             MergerTokenFactory mergerTokenFactory = 
mergerTokenFactoryProvider.get(adapter);
             tokens.setMergerTokenFactory(mergerTokenFactory);
@@ -207,7 +208,7 @@ public class MergerOptionsDialog extends ProjectDialog {
             DbLoaderConfiguration config = new DbLoaderConfiguration();
             config.setFiltersConfig(filters);
 
-            DataSource dataSource = 
connectionInfo.makeDataSource(app.getClassLoader());
+            DataSource dataSource = new 
DBConnectorFactory(app.getClassLoader()).makeDataSource(connectionInfo);
 
             DataMap dbImport;
             try (Connection conn = dataSource.getConnection()) {
@@ -263,7 +264,7 @@ public class MergerOptionsDialog extends ProjectDialog {
 
         DataSource dataSource;
         try {
-            dataSource = connectionInfo.makeDataSource(app.getClassLoader());
+            dataSource = new 
DBConnectorFactory(app.getClassLoader()).makeDataSource(connectionInfo);
         } catch (SQLException ex) {
             reportError("Migration Error", ex);
             return;
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorEditor.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorEditor.java
index f7d7b9728..1598be025 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorEditor.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorEditor.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.modeler.ui.preferences.dbconnector;
 
 import com.jgoodies.forms.builder.DefaultFormBuilder;
 import com.jgoodies.forms.layout.FormLayout;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.apache.cayenne.modeler.toolkit.text.CMPasswordField;
 import org.apache.cayenne.modeler.toolkit.text.CMTextField;
 import org.apache.cayenne.modeler.dbadapter.DbAdapters;
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorPrefsPanel.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorPrefsPanel.java
index 9d5be1253..576e205f6 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorPrefsPanel.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/DBConnectorPrefsPanel.java
@@ -24,8 +24,8 @@ import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.datasource.DriverDataSource;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
-import org.apache.cayenne.modeler.dbconnector.DBConnectors;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnectors;
 import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
 import org.apache.cayenne.modeler.toolkit.AppPanel;
 import org.apache.cayenne.modeler.ui.preferences.classpath.ClasspathPrefsPanel;
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/creator/DBConnectorCreatorDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/creator/DBConnectorCreatorDialog.java
index 8aa13a172..1ceff0120 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/creator/DBConnectorCreatorDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/creator/DBConnectorCreatorDialog.java
@@ -22,7 +22,7 @@ package 
org.apache.cayenne.modeler.ui.preferences.dbconnector.creator;
 import com.jgoodies.forms.builder.DefaultFormBuilder;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.apache.cayenne.modeler.toolkit.AppDialog;
 import 
org.apache.cayenne.modeler.ui.preferences.dbconnector.DBConnectorPrefsPanel;
 import org.apache.cayenne.modeler.dbadapter.DbAdapters;
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/duplicator/DBConnectorDuplicatorDialog.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/duplicator/DBConnectorDuplicatorDialog.java
index d1de2130e..f66105333 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/duplicator/DBConnectorDuplicatorDialog.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/dbconnector/duplicator/DBConnectorDuplicatorDialog.java
@@ -22,7 +22,7 @@ package 
org.apache.cayenne.modeler.ui.preferences.dbconnector.duplicator;
 import com.jgoodies.forms.builder.DefaultFormBuilder;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.apache.cayenne.modeler.toolkit.AppDialog;
 import 
org.apache.cayenne.modeler.ui.preferences.dbconnector.DBConnectorPrefsPanel;
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DatabaseSchemaLoader.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DatabaseSchemaLoader.java
index a0e6e0851..00e86de0a 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DatabaseSchemaLoader.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DatabaseSchemaLoader.java
@@ -41,7 +41,8 @@ import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
 import org.apache.cayenne.dbsync.reverse.dbimport.SchemaContainer;
 import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
 import 
org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.tree.DbImportTreeNode;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.dbconnector.DBConnectorFactory;
 
 public class DatabaseSchemaLoader {
 
@@ -57,8 +58,8 @@ public class DatabaseSchemaLoader {
 
     public ReverseEngineering load(DBConnector connectionInfo,
                                    ModelerClassLoader loadingService) throws 
Exception {
-        DbAdapter dbAdapter = connectionInfo.makeAdapter(loadingService, 
adapterFactory);
-        try (Connection connection = 
connectionInfo.makeDataSource(loadingService).getConnection()) {
+        DbAdapter dbAdapter = new 
DBConnectorFactory(loadingService).makeAdapter(connectionInfo, adapterFactory);
+        try (Connection connection = new 
DBConnectorFactory(loadingService).makeDataSource(connectionInfo).getConnection())
 {
             processCatalogs(connection, dbAdapter);
         }
 
@@ -131,7 +132,7 @@ public class DatabaseSchemaLoader {
                                          String[] tableTypesFromConfig) throws 
Exception {
         int pathIndex = 1;
         String catalogName = null, schemaName = null;
-        DbAdapter adapter = connectionInfo.makeAdapter(loadingService, 
adapterFactory);
+        DbAdapter adapter = new 
DBConnectorFactory(loadingService).makeAdapter(connectionInfo, adapterFactory);
 
         Object userObject = getUserObjectOrNull(path, pathIndex);
         if (userObject != null) {
@@ -149,7 +150,7 @@ public class DatabaseSchemaLoader {
             }
         }
 
-        try (Connection connection = 
connectionInfo.makeDataSource(loadingService).getConnection()) {
+        try (Connection connection = new 
DBConnectorFactory(loadingService).makeDataSource(connectionInfo).getConnection())
 {
             String[] types = tableTypesFromConfig != null && 
tableTypesFromConfig.length != 0 ?
                     tableTypesFromConfig :
                     new String[]{"TABLE", "VIEW", "SYSTEM TABLE",
@@ -193,7 +194,7 @@ public class DatabaseSchemaLoader {
         }
 
         String tableName = processTable(userObject);
-        try (Connection connection = 
connectionInfo.makeDataSource(loadingService).getConnection()) {
+        try (Connection connection = new 
DBConnectorFactory(loadingService).makeDataSource(connectionInfo).getConnection())
 {
             try (ResultSet rs = 
connection.getMetaData().getColumns(catalogName, schemaName, tableName, null)) {
                 while (rs.next()) {
                     String column = rs.getString("COLUMN_NAME");
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/LoadDbSchemaAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/LoadDbSchemaAction.java
index fc690bbde..59e3b846e 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/LoadDbSchemaAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/LoadDbSchemaAction.java
@@ -32,7 +32,7 @@ import 
org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.DbImportVie
 import 
org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.DBSchemaPanel;
 import 
org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.PrintColumnsBiFunction;
 import 
org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.PrintTablesBiFunction;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/ModelerDbImportAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/ModelerDbImportAction.java
index f04fa4586..4c59f1228 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/ModelerDbImportAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/action/ModelerDbImportAction.java
@@ -28,7 +28,8 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.dbconnector.DBConnectorFactory;
 import org.apache.cayenne.modeler.project.DataMapOps;
 import 
org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.progress.DbImportProgressDialog;
 import org.apache.cayenne.modeler.ui.action.DBConnectionAwareAction;
@@ -81,7 +82,7 @@ public class ModelerDbImportAction extends 
DBConnectionAwareAction {
         }
 
         try {
-            
context.setConnection(connectionInfo.makeDataSource(app.getClassLoader()).getConnection());
+            context.setConnection(new 
DBConnectorFactory(app.getClassLoader()).makeDataSource(connectionInfo).getConnection());
         } catch (SQLException ex) {
             JOptionPane.showMessageDialog(
                     app.getFrame(),
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/runner/ModelerDbLoaderContext.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/runner/ModelerDbLoaderContext.java
index 3aefca96d..98c107b31 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/runner/ModelerDbLoaderContext.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/runner/ModelerDbLoaderContext.java
@@ -25,7 +25,8 @@ import 
org.apache.cayenne.dbsync.reverse.dbload.DbLoaderDelegate;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.dbconnector.DBConnectorFactory;
 import org.apache.cayenne.modeler.service.classloader.ModelerClassLoader;
 import org.apache.cayenne.modeler.project.ProjectSession;
 import org.apache.cayenne.util.Util;
@@ -137,8 +138,8 @@ public class ModelerDbLoaderContext {
         try {
             ModelerClassLoader classLoader = application.getClassLoader();
             config.getDbLoaderConfig().setFiltersConfig(new 
FiltersConfigBuilder(reverseEngineering)
-                    .dataSource(connectionInfo.makeDataSource(classLoader))
-                    .dbAdapter(connectionInfo.makeAdapter(classLoader, 
application.getDbAdapterFactory()))
+                    .dataSource(new 
DBConnectorFactory(classLoader).makeDataSource(connectionInfo))
+                    .dbAdapter(new 
DBConnectorFactory(classLoader).makeAdapter(connectionInfo, 
application.getDbAdapterFactory()))
                     .build());
         } catch (Exception e) {
             processException(e, "Fail while building configs.");
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 8c8e4d997..e9d1f8b90 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
@@ -28,7 +28,7 @@ import 
org.apache.cayenne.access.dbsync.ThrowOnPartialSchemaStrategy;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.runtime.XMLPoolingDataSourceFactory;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.apache.cayenne.modeler.event.model.DataNodeEvent;
 import org.apache.cayenne.modeler.pref.adapters.DataNodePrefs;
 import org.apache.cayenne.modeler.project.ProjectSession;
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 4e5a22ea1..25427ee2d 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
@@ -25,7 +25,7 @@ import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.DataSourceDescriptor;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dbconnector.DBConnector;
+import org.apache.cayenne.modeler.pref.dbconnector.DBConnector;
 import org.apache.cayenne.modeler.pref.adapters.DataNodePrefs;
 import org.apache.cayenne.modeler.toolkit.text.CMPasswordField;
 import org.apache.cayenne.modeler.toolkit.text.CMUndoableTextField;
diff --git a/modeler/pom.xml b/modeler/pom.xml
index 2db49f95b..3ff2d3e9b 100644
--- a/modeler/pom.xml
+++ b/modeler/pom.xml
@@ -34,6 +34,7 @@
        
        <modules>
                <module>cayenne-wocompat</module>
+               <module>cayenne-modeler-prefs</module>
                <module>cayenne-modeler</module>
                <module>cayenne-modeler-generic</module>
                <module>cayenne-modeler-mac</module>


Reply via email to