# How to Build a Custom JDBC Database Driver for DBX

> Learn to build a custom JDBC database driver for DBX. Explore loading JDBC drivers as runtime plug-ins using local JARs Maven or bundled plugins.

- Repository: [skyler/dbx](https://github.com/t8y2/dbx)
- Tags: how-to-guide
- Published: 2026-07-10

---

**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`](https://github.com/t8y2/dbx/blob/main/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`](https://github.com/t8y2/dbx/blob/main/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:

```java
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:

```bash
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`](https://github.com/t8y2/dbx/blob/main/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:

```rust
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`](https://github.com/t8y2/dbx/blob/main/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`:

```rust
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`](https://github.com/t8y2/dbx/blob/main/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`](https://github.com/t8y2/dbx/blob/main/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_class` empty and rely on the standard `ServiceLoader` mechanism.
- **Explicit class name**: Set `jdbc_driver_class` to the fully-qualified class name (e.g., `"com.example.MyDriver"`).

The connection handling code in [`src-tauri/src/commands/connection.rs`](https://github.com/t8y2/dbx/blob/main/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:

```json
{
  "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:

1. **List installed drivers**: Use `GET /jdbc/drivers` via the web API or the CLI to verify your driver appears in the catalog.
2. **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:

```bash
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:

1. Bundle your JARs under a plugin directory structure (`plugins_root/jdbc`).
2. Create a [`manifest.json`](https://github.com/t8y2/dbx/blob/main/manifest.json) describing the plugin version, protocol version, and bundled drivers.
3. Install using `install_jdbc_plugin` or the corresponding web endpoint.

The plugin installer validates the manifest against `SUPPORTED_PLUGIN_PROTOCOL_VERSION` (defined in [`crates/dbx-core/src/jdbc.rs`](https://github.com/t8y2/dbx/blob/main/crates/dbx-core/src/jdbc.rs)) to ensure compatibility with the current DBX runtime.

## Summary

- **DBX loads JDBC drivers dynamically** from the `jdbc` directory under the plugins root, using functions in [`crates/dbx-core/src/jdbc.rs`](https://github.com/t8y2/dbx/blob/main/crates/dbx-core/src/jdbc.rs) for management.
- **Three installation methods** are available: import local JARs with `import_jdbc_drivers`, install from Maven coordinates with `install_jdbc_driver_from_maven`, or upload via the web UI.
- **Driver discovery** can be automatic via `ServiceLoader` or explicit via the `jdbc_driver_class` field 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`](https://github.com/t8y2/dbx/blob/main/crates/dbx-core/src/jdbc.rs) ensures unique filenames to prevent collisions when multiple drivers or versions are present.