Skip to main content

Extension mechanisms

ApiGo provides extension capabilities at three levels: data source drivers (integrate new databases/storage), result processing plugins (transform returned data), and runtime configuration hooks (change behavior without touching code). This document explains how extension points are loaded and executed from a code-structure perspective. For usage instructions, see Data plugins and Data source management.

Data source driver SPI​

Loading​

Data source drivers are discovered through the Java ServiceLoader, with no need to modify core code:

Adding a driver takes three steps:

  1. Implement the DataSourceDriver interface (or extend DefaultDataSourceDriver).
  2. Write the fully qualified implementation class name into the module's META-INF/services/cn.apigo.core.spi.datasource.DataSourceDriver.
  3. Add the module to the dependencies of apigo-api and apigo-admin so that ServiceLoader discovers it on both sides.
Driver names must be unique

DataSourceManager registers drivers by getName() during initialization; a duplicate or empty name throws a 51003/51004 exception and blocks service startup. Type matching is always lowercased.

Interface responsibilities​

MethodPurpose
getName()Driver type identifier, corresponding to datasourceType in the data source configuration
isRelational()Whether the data source is relational; determines whether transactions and the JDBC connection pool are used
supportsTransaction() / supportsStatement() / supportsMetaData()Capability declarations; the execution engine chooses the execution path accordingly
test()Data source connectivity test
init() / destroy()Connection pool or client lifecycle
getMetaData()Database/table structure browsing (tables, fields, indexes)
getStatement()SQL/query statement execution

Two driver types​

  • JDBC driver: JdbcDataSourceDriver extends DefaultDataSourceDriver and uniformly handles connection pools, transactions, metadata, and StatementMapper. Relational databases such as MySQL, Oracle, and PostgreSQL share this implementation; differences come from the JDBC URL and driver package.
  • Native driver: MongoDB and Elasticsearch implement DataSourceDriver directly, declare isRelational=false, and manage clients and query statements themselves. Such data sources do not participate in SQL transactions, and their metadata capabilities are implemented per driver.

Connection pool isolation​

DataSourceManager maintains three mappings in-process:

MappingContent
pluginTypeDriver type → driver instance
pluginDataSourcePoolData source ID → native driver instance
DATA_SOURCE_POOL_JDBCData source ID → JDBC DataSource

When a data source switches driver type, resources of the old type are released to avoid connection pool leaks. Each admin instance maintains its own local connection pool; only the configuration snapshot in Redis is shared.

Result processing plugins​

Execution chain​

Plugins run after API execution completes and before the response is written; the input is the result data and the output is the transformed data. PluginExecutor works as follows:

  1. Parse the pluginConfig JSON on the API. Its structure is { "<pluginType>": { "enabled": true, ... } }.
  2. Match a handler by getType() among the PluginHandler beans registered in the Spring container.
  3. Keep only plugins with enabled=true and execute them in ascending getOrder().
  4. The output of each handler becomes the input of the next.

Built-in handlers​

TypeOrderResponsibility
fieldMapping5Field renaming / mapping
dataProcess10Filtering, sorting, masking, encryption, calculation
dictTransform11Dictionary value to text
fieldFormat12Date, amount, percentage, case, whitespace trimming
fieldReplace13Null / regex match replacement
dataMerge14Merge multiple fields into one field
dataAggregation15Group aggregation (sum, count, average, max, min)
treeTransform30List to tree
singleObject35Take a single record from a list
nestedStructure40Build multi-level nesting by path
Group aggregation is not exposed in the UI

dataAggregation is implemented and registered, but the current frontend plugin panel does not expose an entry for it. It still takes effect when configured through the API definition JSON; this is a backend capability the UI does not yet expose.

Fault tolerance semantics​

When plugin execution throws an exception, PluginExecutor logs the error and returns the original data, rather than failing the API call. This design ensures that "processing logic errors" do not escalate into "API unavailable", but it also means plugin configuration errors can only be found in logs and never appear in the response code.

Adding a handler​

  1. Implement PluginHandler, returning a unique getType() and a suitable getOrder().
  2. isEnabled() reads the enabled field from the configuration by default; it usually does not need to be overridden.
  3. Register it as a Spring bean in PluginConfiguration, or declare the bean in any @Configuration class.
  4. The frontend needs a corresponding configuration panel; otherwise the handler can only be used through the pluginConfig JSON in the API definition.

Handlers should be idempotent, free of external side effects, and assume the input may be a single object or a list.

Reports and data processing boundaries​

CapabilityExtension methodRequires code changes
Integrate a new databaseImplement DataSourceDriver + SPI registrationYes
Modify the returned field structureConfigure data pluginsNo
Adapt SQL dialect differencesJDBC driver or custom StatementMapperDepends
Add AI toolsDeclare @Tool methods in McpAdminToolAdapterYes
Adjust flow control/cache/alert behaviorConfiguration in the admin UINo
Replace the License signature algorithmImplement SignatureAlgorithmYes (vendor side)

Extension boundaries with the admin service​

The admin and execution services share the same apigo-core and apigo-plugin, therefore:

  • Data source drivers must be loadable on both sides. If a driver is added only to the execution service dependencies, the admin's connection test and metadata browsing will fail.
  • Result plugins only take effect in the execution path, but the admin also runs them when previewing an API, providing WYSIWYG behavior.
  • Changing plugin execution order affects every API that has the plugin enabled—this is a global behavior change that requires regression testing.