How to Build a Custom JDBC Database Driver for DBX
DBX loads JDBC drivers as runtime plug-in artifacts from a dedicated jdbc directory, allowing you to import local JARs, install from Maven, or bundle them as plugins using the core functions in crates/dbx-core/src/jdbc.rs.
The DBX project (t8y2/dbx) implements a dynamic driver architecture that treats JDBC drivers as first-class plug-in artifacts. The driver management system lives in crates/dbx-core/src/jdbc.rs, providing Rust functions for listing, importing, installing, and deleting driver JARs. This guide walks through building and registering a custom JDBC database driver for DBX.
Implement the Driver in Java
Creating a custom JDBC driver for DBX starts with a standard Java implementation packaged as a JAR file.
Create the Driver Class
Implement the java.sql.Driver interface and register your driver statically so that DriverManager can discover it automatically:
package com.example;
import java.sql.*;
import java.util.Properties;
public class MyDriver implements Driver {
static {
try {
DriverManager.registerDriver(new MyDriver());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Connection connect(String url, Properties info) throws SQLException {
// Implement connection logic here
return DriverManager.getConnection("jdbc:h2:mem:test");
}
@Override
public boolean acceptsURL(String url) {
return url.startsWith("jdbc:mydb:");
}
@Override
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
return new DriverPropertyInfo[0];
}
@Override
public int getMajorVersion() { return 1; }
@Override
public int getMinorVersion() { return 0; }
@Override
public boolean jdbcCompliant() { return false; }
@Override
public java.util.logging.Logger getParentLogger() {
return null;
}
}
Package the JAR
Compile your classes and package them into a JAR file. Ensure the manifest contains the Driver entry point so that ServiceLoader can discover the class:
javac -d out src/com/example/MyDriver.java
jar cf my-driver.jar -C out .
The JAR should contain a META-INF/services/java.sql.Driver file listing your driver class name, or you must specify the class explicitly in the DBX connection configuration.
Add the JAR to DBX
DBX offers three methods to make your custom JDBC driver available at runtime. All methods eventually call the unique_target_path helper in crates/dbx-core/src/jdbc.rs to prevent filename collisions when storing JARs in the plugins directory.
Import a Local JAR
Copy your compiled JAR into the <plugins_root>/jdbc/drivers directory using the import_jdbc_drivers function. This creates a local bundle for easier management:
use std::path::PathBuf;
use dbx_core::jdbc::import_jdbc_drivers;
let plugins_root = PathBuf::from("/path/to/dbx/plugins");
let jar_path = "/path/to/my-driver.jar".to_string();
let drivers = import_jdbc_drivers(&plugins_root, &[jar_path])?;
According to the source code in crates/dbx-core/src/jdbc.rs, this function handles multiple JARs and groups them into a local bundle for centralized management.
Install from Maven
Resolve and download a driver artifact directly from Maven repositories using install_jdbc_driver_from_maven:
use dbx_core::jdbc::{install_jdbc_driver_from_maven, JdbcMavenInstallRequest};
let req = JdbcMavenInstallRequest {
coordinate: "com.example:my-driver:1.0.0".into(),
repositories: vec![]
};
let drivers = install_jdbc_driver_from_maven(&plugins_root, req, env).await?;
This stores the artifact as a Maven bundle in the plugins directory, maintaining version metadata for future updates.
Upload via the Web UI
The web front-end exposes driver operations through HTTP endpoints defined in crates/dbx-web/src/routes/jdbc.rs. When you upload a JAR through the UI, the backend invokes the same Rust functions, with Tauri command wrappers in src-tauri/src/commands/plugins.rs bridging the desktop UI to the core logic.
Reference the Driver in a DBX Connection
Once installed, configure your DBX connection to use the custom driver. In the ConnectionConfig, you have two options for driver discovery:
- Automatic discovery: Leave
jdbc_driver_classempty and rely on the standardServiceLoadermechanism. - Explicit class name: Set
jdbc_driver_classto the fully-qualified class name (e.g.,"com.example.MyDriver").
The connection handling code in src-tauri/src/commands/connection.rs passes the specified class name and the list of driver JAR paths to the external driver pool (state.external_driver_pool("jdbc")) when establishing connections.
Example connection configuration:
{
"name": "MyDB",
"type": "Jdbc",
"connection_string": "jdbc:mydb://localhost:1234/schema",
"jdbc_driver_class": "com.example.MyDriver",
"jdbc_driver_paths": ["/path/to/dbx/plugins/jdbc/drivers/my-driver.jar"]
}
Verify the Driver Works
Test your installation using either the DBX CLI or the web interface:
- List installed drivers: Use
GET /jdbc/driversvia the web API or the CLI to verify your driver appears in the catalog. - Create a test connection: Define a connection using your custom driver and attempt to connect to a test database. DBX will load the JAR, instantiate the driver class, and surface any errors through the same result types used for built-in drivers.
Command-line installation from Maven:
dbx-cli plugins install-jdbc-driver --coordinate com.example:my-driver:1.2.3
Package as a JDBC Plugin
For distribution scenarios where you need to ship multiple drivers together with metadata, create a formal JDBC plugin:
- Bundle your JARs under a plugin directory structure (
plugins_root/jdbc). - Create a
manifest.jsondescribing the plugin version, protocol version, and bundled drivers. - Install using
install_jdbc_pluginor the corresponding web endpoint.
The plugin installer validates the manifest against SUPPORTED_PLUGIN_PROTOCOL_VERSION (defined in crates/dbx-core/src/jdbc.rs) to ensure compatibility with the current DBX runtime.
Summary
- DBX loads JDBC drivers dynamically from the
jdbcdirectory under the plugins root, using functions incrates/dbx-core/src/jdbc.rsfor management. - Three installation methods are available: import local JARs with
import_jdbc_drivers, install from Maven coordinates withinstall_jdbc_driver_from_maven, or upload via the web UI. - Driver discovery can be automatic via
ServiceLoaderor explicit via thejdbc_driver_classfield in connection configurations. - Plugin packaging allows bundling multiple drivers with version metadata for enterprise distribution, validated against
SUPPORTED_PLUGIN_PROTOCOL_VERSION.
Frequently Asked Questions
How does DBX discover JDBC driver classes?
DBX uses the standard Java ServiceLoader mechanism when jdbc_driver_class is left empty in the connection configuration. Alternatively, you can specify the fully-qualified class name explicitly, and DBX will attempt to instantiate that class from the provided JAR paths.
Can I install JDBC drivers without restarting DBX?
Yes. DBX loads drivers at runtime from the plugins directory. When you import a JAR using import_jdbc_drivers or the web UI, the driver becomes available immediately for new connections without requiring an application restart.
What is the difference between a local bundle and a Maven bundle?
A local bundle is created when you import JAR files directly from the filesystem, grouping them for management purposes. A Maven bundle is created when installing from coordinates, maintaining the artifact's version metadata and allowing DBX to track updates from the repository.
Where does DBX store imported JDBC driver JARs?
Imported JARs are stored in <plugins_root>/jdbc/drivers. The unique_target_path function in crates/dbx-core/src/jdbc.rs ensures unique filenames to prevent collisions when multiple drivers or versions are present.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →