# Plugins

# Plugin Market

# Plugin Functions

  • DBAPI plugins are divided into 5 categories: Data Transformation Plugin, Cache Plugin, Alert Plugin, Global Data Transformation Plugin, and Parameter Processing Plugin
  • Plugins are JAR packages that need to be placed in DBAPI's extlib directory or lib directory. Restart DBAPI to use them.

# Cache Plugin

  • Caches executor results. For example, for SQL executors, cache the results of query-type SQL to avoid frequent database queries and reduce database pressure.
  • Cache logic is written by users, who can cache to Redis/MongoDB/Elasticsearch, etc.
  • When data cannot be found in the cache, the executor is executed, and the results are cached.
  • For SQL executors containing multiple SQL statements, the cache plugin caches the encapsulated overall result of multiple SQL executions (if a single SQL is configured with a transformation plugin, the result will be transformed first) as a whole

# Alert Plugin

  • When an API encounters internal errors, the alert plugin can send error notifications, such as emails or SMS
  • Alert logic is written by users

# Data Transformation Plugin

  • Sometimes SQL cannot obtain the desired data format in one go. If using code to process and transform data is more convenient, the data transformation plugin should be used. Users write the code for data transformation logic.
  • For example, transforming user phone numbers and bank card numbers in SQL query results for desensitization.
  • For SQL executors, if an executor contains multiple SQL statements, each SQL corresponds to a data transformation plugin configuration. Data transformation plugins always transform the result of a single SQL query

# Global Data Transformation Plugin

  • The default API return data format is {success:true,msg:xxx,data:xxx}
  • In some cases, the response data format needs to be transformed. For example, the frontend low-code framework AMIS requires the interface return data to carry a status field. In this case, the Global Data Transformation Plugin can be used to transform the entire API return data format

Note the difference between data transformation plugins and global data transformation plugins. Data transformation plugins transform the executor execution results (such as transforming the results of SQL executors executing query SQL), while global data transformation plugins transform the entire API execution results.

# Parameter Processing Plugin

  • Processes request parameters with user-defined logic
  • For example, converting all request parameter values to uppercase
  • For example, APIs receiving encrypted parameters, users define logic to decrypt parameter values
  • For example, during pagination queries, users write logic to add an offset parameter whose value equals (pageNo-1)*pageSize

Note: Parameter processing plugins are supported starting from Personal Edition 4.0.16 and Enterprise Edition 4.1.10

# Plugin Development Process

# Preparation

  • Plugins are written in Java. Prepare a Java (8+) development environment, create a Maven project, and include dbapi-plugin in the pom:
<dependency>
    <groupId>com.gitee.freakchicken.dbapi</groupId>
    <artifactId>dbapi-plugin</artifactId>
    <version>4.0.16</version>
    <scope>provided</scope>
</dependency>

# Plugin Development

# Cache Plugin Development

  • Create a new Java class implementing com.gitee.freakchicken.dbapi.plugin.CachePlugin
import com.gitee.freakchicken.dbapi.common.ApiConfig;
import com.gitee.freakchicken.dbapi.plugin.CachePlugin;

import java.util.Map;

public class Cdemo extends CachePlugin {

    /**
     * Plugin name, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getName() {
        return null;
    }

    /**
     * Plugin function description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getDescription() {
        return null;
    }

    /**
     * Plugin parameter description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getParamDescription() {
        return null;
    }

    /**
     * Plugin initialization method, executed when instantiating the plugin, only executed once,
     * usually used to create connection pools
     */
    @Override
    public void init() {

    }

    /**
     * Cache setting
     *
     * @param config           API configuration
     * @param requestParams    Request parameters
     * @param data             Data to be cached
     * @param localPluginParam Local parameters of the plugin
     */
    public void set(ApiConfig config, Map<String, Object> requestParams, Object data, String localPluginParam){

    }

    /**
     * Clear all cache, triggered when API is modified, deleted, or taken offline
     *
     * @param config           API configuration
     * @param localPluginParam Local parameters of the plugin
     */
    public void clean(ApiConfig config, String localPluginParam){

    }

    /**
     * Query cache
     *
     * @param config           API configuration
     * @param requestParams    Request parameters
     * @param localPluginParam Local parameters of the plugin
     * @return
     */
    public Object get(ApiConfig config, Map<String, Object> requestParams, String localPluginParam){
        return null;
    }
}
  • The init method is the plugin initialization method, executed only once, generally used to initialize connection pools, such as initializing Redis connection pools

  • The get method retrieves data from the cache. The first parameter is the API configuration, and the second parameter is the request parameters

  • The set method sets the cache. After the executor executes, the set method is called. The first parameter is the API configuration, the second parameter is the request parameters, and the third parameter is the executor execution result. If a data transformation plugin is configured, it's the transformed result

  • The clean method clears the cache. When an API is modified, taken offline, or deleted, the clean method is executed

# Data Transformation Plugin Development

  • Create a new Java class implementing com.gitee.freakchicken.dbapi.plugin.TransformPlugin
import com.alibaba.fastjson.JSONObject;
import com.gitee.freakchicken.dbapi.common.ApiConfig;
import com.gitee.freakchicken.dbapi.plugin.TransformPlugin;

import java.util.List;

public class Tdemo extends TransformPlugin {

    /**
     * Plugin name, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getName() {
        return null;
    }

    /**
     * Plugin function description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getDescription() {
        return null;
    }

    /**
     * Plugin parameter description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getParamDescription() {
        return null;
    }

    /**
     * Plugin initialization method, executed when instantiating the plugin, only executed once
     */
    public void init() {
    }

    /**
     * Data transformation logic
     *
     * @param data             Result data returned after executor execution
     * @param localPluginParam Local parameters of the plugin
     * @return
     */
    public Object transform(Object data, String localPluginParam) {
        return null;
    }
}
  • Data transformation logic is written in the transform method

  • The first parameter is the executor execution result. For SQL executors, it's the SQL execution result of type List<JSONObject>. The data can be cast to List<JSONObject> type

  • The second parameter is the plugin local parameters

# Global Data Transformation Plugin Development

  • Create a new Java class implementing com.gitee.freakchicken.dbapi.plugin.GlobalTransformPlugin
import com.alibaba.fastjson.JSONObject;
import com.gitee.freakchicken.dbapi.common.ResponseDto;
import com.gitee.freakchicken.dbapi.plugin.GlobalTransformPlugin;

public class AmisGlobalTransformPlugin extends GlobalTransformPlugin {

    /**
     * Plugin name, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getName() {
        return null;
    }

    /**
     * Plugin function description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getDescription() {
        return null;
    }

    /**
     * Plugin parameter description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getParamDescription() {
        return null;
    }

    /**
     * Plugin initialization method, executed when instantiating the plugin, only executed once
     */
    public void init() {
    }

    /**
     * Data transformation logic
     *
     * @param data             API return data
     * @param localPluginParam Local parameters of the global transformation plugin
     * @return
     */
    public Object transform(ResponseDto data, String localPluginParam) {
        return null;
    }
}
  • Data transformation logic is written in the transform method. The first parameter is the API execution return result, and the second parameter is the plugin local parameters

# Alert Plugin Development

  • Create a new Java class implementing com.gitee.freakchicken.dbapi.plugin.AlarmPlugin
import com.gitee.freakchicken.dbapi.common.ApiConfig;
import com.gitee.freakchicken.dbapi.plugin.AlarmPlugin;

import javax.servlet.http.HttpServletRequest;

public class EmailAlarmPlugin extends AlarmPlugin {

    /**
     * Plugin name, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getName() {
        return null;
    }

    /**
     * Plugin function description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getDescription() {
        return null;
    }

    /**
     * Plugin parameter description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getParamDescription() {
        return null;
    }

    /**
     * Plugin initialization method, executed when instantiating the plugin, only executed once
     */
    @Override
    public void init() {

    }

    /**
     * Alert logic
     * 
     * @param e                Exception
     * @param config           API metadata
     * @param request          Request
     * @param localPluginParam Local parameters of the alert plugin
     */
    public void alarm(Exception e, ApiConfig config, HttpServletRequest request, String localPluginParam) {

    }
}

# Parameter Processing Plugin Development

  • Create a new Java class implementing com.gitee.freakchicken.dbapi.plugin.ParamProcessPlugin
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gitee.freakchicken.dbapi.common.ApiConfig;

import java.util.Map;

public class PaginationPlugin extends ParamProcessPlugin {
    /**
     * Plugin name, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getName() {
        return null;
    }

    /**
     * Plugin function description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getDescription() {
        return null;
    }

    /**
     * Plugin parameter description, displayed on the page to prompt users
     *
     * @return
     */
    @Override
    public String getParamDescription() {
        return null;
    }

    /**
     * Plugin initialization method, executed when instantiating the plugin, only executed once
     */
    @Override
    public void init() {

    }

    /**
     * Parameter processing
     *
     * @param requestParam     Request parameters
     * @param apiConfig        API metadata
     * @param localPluginParam Local parameters of the parameter processing plugin
     */
    @Override
    public void process(Map<String, Object> requestParam, ApiConfig apiConfig, String localPluginParam) {
        
    }
}
  • Parameter processing logic is written in the process method
  • requestParam is the request parameters, apiConfig is the API metadata, and localPluginParam is the plugin local parameters

# Plugin Registration

  • DBAPI plugins use Java's SPI mechanism for registration. The following operations are required:
  1. Create a new folder META-INF in the resources directory, then create a services folder under META-INF

  2. Create a file com.gitee.freakchicken.dbapi.plugin.CachePlugin in the META-INF/services directory and fill in the Java class name of the cache plugin you just wrote in this file

  3. Create a file com.gitee.freakchicken.dbapi.plugin.TransformPlugin in the META-INF/services directory and fill in the Java class name of the data transformation plugin you just wrote in this file

  4. Create a file com.gitee.freakchicken.dbapi.plugin.GlobalTransformPlugin in the META-INF/services directory and fill in the Java class name of the global data transformation plugin you just wrote in this file

  5. Create a file com.gitee.freakchicken.dbapi.plugin.AlarmPlugin in the META-INF/services directory and fill in the Java class name of the alert plugin you just wrote in this file

  6. Create a file com.gitee.freakchicken.dbapi.plugin.ParamProcessPlugin in the META-INF/services directory and fill in the Java class name of the parameter processing plugin you just wrote in this file

# Plugin Instructions

# Global Parameters

  • The purpose of designing plugin global parameters is to facilitate the use of a plugin in different environments
  • Plugin global parameters are each plugin's own parameters, unrelated to APIs, such as the Redis IP and port information needed by cache plugins. Configured in the file conf/plugin.properties.
  • Global parameters are mainly for facilitating environment switching. For example, test and production environments need to connect to different Redis addresses. Configuring Redis address information in the configuration file is very convenient.
  • If users want to add global plugin configurations, they can directly add configurations in the conf/plugin.properties file, for example:
RedisCachePlugin.ip=127.0.0.1
RedisCachePlugin.port=6379
RedisCachePlugin.db=0
RedisCachePlugin.password=
  • Method to get plugin global parameter values:
import com.gitee.freakchicken.dbapi.plugin.PluginConf;
String ip = PluginConf.getKey("RedisCachePlugin.ip")

# Local Parameters

  • The purpose of designing plugin local parameters is to allow a plugin to be flexibly reused by multiple APIs

  • Plugin local parameters are parameters specified separately for each API, with parameter values configured on the page (when creating or editing APIs).

  • For example, for Redis cache plugins, different APIs need to set different cache times. When each API calls the same cache plugin, different time parameters can be passed in. Another example is field encryption plugins, where different APIs need to encrypt different fields. When each API calls the same field encryption plugin, different field name parameters can be passed in. This allows one plugin to be flexibly reused by multiple APIs.

  • Method to get plugin local parameter values:

// Plugin local parameters are already passed to the corresponding plugin method, with the parameter name being localPluginParam
// For example, the alarm method of the alert plugin, the last parameter is the local plugin parameter
    public void alarm(Exception e, ApiConfig config, HttpServletRequest request, String localPluginParam) {

    }

# Plugin Log Printing

  • If you want to print logs within the plugin, it's recommended to directly call the parent class's logger
super.logger.debug("set data to cache");

# Plugin Description

  • All plugins must implement the getName, getDescription, and getParamDescription methods. Their purpose is to prompt users about the plugin's function and the format of plugin local parameters on the page

# Plugin Usage

  • After users develop plugins, please package them. Copy the generated JAR package and the plugin's dependent JAR packages to DBAPI's extlib or lib directory (we recommend placing them in the extlib directory for unified management). Then restart the DBAPI service (for cluster mode, each node needs to copy the JAR packages and restart the cluster) to use the plugins.
  • If plugins use global parameters, corresponding configurations need to be added to the conf/plugin.properties file and restarted to take effect (for cluster mode, each node needs to add corresponding configurations and restart to take effect)

# Complete Plugin Development Example

Example demo (opens new window)