# How Chat2DB's SPI Plugin System Supports Over 35 Databases

> Discover how Chat2DB's SPI plugin system effortlessly supports over 35 databases. Learn how Java's ServiceLoader enables dynamic driver discovery through pluggable JARs without core code changes.

- Repository: [OtterMind/Chat2DB](https://github.com/OtterMind/Chat2DB)
- Tags: internals
- Published: 2026-07-26

---

**Chat2DB leverages Java's Service Provider Interface (SPI) mechanism to discover database drivers at runtime via ServiceLoader, enabling support for over 35 databases through pluggable JAR modules that require no changes to the core application code.**

The OtterMind/Chat2DB repository implements a highly extensible architecture that decouples database-specific logic from the core application through a unified plugin system. By defining a strict service contract in the `ai.chat2db.spi.IPlugin` interface, Chat2DB allows each database to ship its own implementation as an independent module, enabling horizontal scalability where adding support for a new database simply means dropping a JAR file into the classpath.

## The Core SPI Contract: IPlugin Interface

At the heart of the system lies the `IPlugin` interface located in [`chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/IPlugin.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/IPlugin.java). This interface defines the contract that every database plugin must fulfill, ensuring the core application can interact with any database through a consistent API.

Every plugin implementation must provide these essential methods:

- **`getDBConfig()`** – Returns a `DBConfig` object containing the database type, URL pattern, default port, and driver class name.
- **`getDbMetaData()`** – Supplies an `IDbMetaData` implementation that handles catalog, table, column, and routine discovery for the specific dialect.
- **`getDbManager()`** – Provides an `IDbManager` for connection lifecycle management and DDL execution.
- **`getSqlBuilder()`**, **`getValueProcessor()`**, **`getSQLIdentifierProcessor()`** – Expose dialect-specific SQL construction, value quoting, and identifier quoting strategies.
- **`getCommandExecutor()`**, **`getKeyOperations()`** – Define command execution patterns and primary key operations.

Optional extension hooks include `getSqlSyntaxPlugin()`, `getAccountManager()`, and `getRoutineManager()`, which allow plugins to inject custom syntax highlighting, cloud account handling, or stored procedure management capabilities.

## Runtime Discovery via ServiceLoader

The central class **`Chat2DBContext`** handles plugin discovery dynamically using Java's standard `ServiceLoader` mechanism. Located in [`chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/sql/Chat2DBContext.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/sql/Chat2DBContext.java), this class scans the classpath for service provider registrations at startup:

```java
ServiceLoader<IPlugin> loader = ServiceLoader.load(IPlugin.class);
for (IPlugin plugin : loader) {
    DBConfig cfg = plugin.getDBConfig();
    PLUGIN_MAP.put(cfg.getType(), plugin);
}

```

The `ServiceLoader` inspects all JAR files for a text file at `META-INF/services/ai.chat2db.spi.IPlugin`. Each plugin module contains exactly one such file listing the fully-qualified class name of its implementation. For example, the MySQL plugin registers itself by including the following line in its service file:

```

ai.chat2db.plugin.mysql.MySQLPlugin

```

This design allows the core application to aggregate dozens of drivers automatically. The repository ships with a `chat2db-community-plugins` directory containing ready-made modules for MySQL, PostgreSQL, Oracle, SQL Server, SQLite, ClickHouse, MongoDB, Redis, Hive, Snowflake, and others.

## Plugin Implementation Architecture

Each plugin module follows a consistent pattern that maximizes code reuse while allowing dialect-specific customization. The `chat2db-community-plugins` directory contains independent Maven modules where each database implementation extends default helpers or provides specialized subclasses.

The **`DefaultMetaService`** class in [`chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/DefaultMetaService.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/DefaultMetaService.java) provides generic metadata functionality that plugins can inherit. For example, the MySQL plugin implements `IPlugin` in [`MySQLPlugin.java`](https://github.com/OtterMind/Chat2DB/blob/main/MySQLPlugin.java) but delegates standard operations to `DefaultMetaService` while overriding specific behaviors through `MySQLMetaData` and `MySQLSqlBuilder` classes.

This layered approach means plugin authors only implement methods where their database diverges from standard JDBC behavior. Common operations like connection pooling or basic result set iteration require no custom code, as the core SPI provides sensible defaults.

## Adding a New Database: Implementation Guide

Creating support for a new database requires only three components: an implementation class, a service registration file, and a JAR deployment. Here is the complete workflow for registering a custom database called "mycustom".

First, implement the `IPlugin` interface:

```java
package ai.chat2db.plugin.mycustom;

import ai.chat2db.spi.*;

public class MyCustomPlugin implements IPlugin {
    @Override
    public DBConfig getDBConfig() {
        return new DBConfig("mycustom", "jdbc:mycustom://{host}:{port}/{db}");
    }

    @Override
    public IDbMetaData getDbMetaData() {
        return new MyCustomMetaData();
    }

    @Override
    public IDbManager getDbManager() {
        return new MyCustomDBManager();
    }
}

```

Next, create the service registration file at `src/main/resources/META-INF/services/ai.chat2db.spi.IPlugin` with the content:

```text
ai.chat2db.plugin.mycustom.MyCustomPlugin

```

Finally, compile the module into a JAR and place it in the `chat2db-community-plugins/` directory or add it to the application classpath. Upon restart, `Chat2DBContext` automatically detects the new plugin through `ServiceLoader`, making the database immediately selectable in the UI without modifying any core application code.

## Summary

- **Service Provider Interface architecture** enables Chat2DB to support over 35 databases through a standardized `IPlugin` contract defined in the SPI module.
- **Runtime discovery** occurs via Java's `ServiceLoader`, which scans `META-INF/services/ai.chat2db.spi.IPlugin` files across the classpath to register available drivers.
- **Horizontal scalability** allows new database support by simply adding plugin JARs to the `chat2db-community-plugins` directory, with no core code changes required.
- **Default implementations** in `DefaultMetaService` minimize boilerplate, requiring plugins to override only dialect-specific behaviors.
- **Unified access** means the UI, query engine, and export tools interact with all databases through the consistent `IPlugin` interface, regardless of underlying driver complexity.

## Frequently Asked Questions

### How does Chat2DB discover new plugins without modifying core code?

Chat2DB uses Java's standard `ServiceLoader` mechanism to scan the classpath for JARs containing `META-INF/services/ai.chat2db.spi.IPlugin` registration files. When the application starts, `Chat2DBContext` loads all implementations of the `IPlugin` interface found in these files and maps them to their respective `DBConfig` types, enabling zero-configuration plugin discovery at runtime.

### What is the minimum implementation required for a functional database plugin?

At minimum, a plugin must implement the `IPlugin` interface and provide concrete implementations for `getDBConfig()`, `getDbMetaData()`, and `getDbManager()`. These methods supply the connection configuration, metadata retrieval logic, and connection management required to interact with the database. Optional methods like `getSqlBuilder()` can inherit from `DefaultMetaService` if standard JDBC behavior suffices.

### Can multiple versions of the same database driver coexist in Chat2DB?

Yes, because each plugin is isolated in its own JAR with a unique implementation class, you can deploy multiple versions or variants of database drivers simultaneously. The `PLUGIN_MAP` in `Chat2DBContext` keys plugins by their `DBConfig` type string, allowing distinct entries for different versions or dialects of the same underlying database system.

### Where should custom enterprise plugins be deployed in production?

Place custom plugin JAR files in the `chat2db-community-plugins/` directory alongside the bundled open-source drivers, or include them in the application classpath through standard Java classpath configuration. Ensure the JAR contains the required `META-INF/services/ai.chat2db.spi.IPlugin` file so `ServiceLoader` can discover the implementation during the initialization phase in `Chat2DBContext`.