ArcadeDB supports a plugin architecture that allows extending the server functionality through isolated plugins. Each plugin runs in its own class loader, enabling plugins to have different versions of dependencies without conflicts.
ArcadeDB includes the following built-in plugins:
- Gremlin - Apache TinkerPop Gremlin graph traversal language support
- PostgreSQL Wire Protocol - PostgreSQL protocol compatibility
- MongoDB Wire Protocol - MongoDB query language compatibility
- Redis Wire Protocol - Redis command compatibility
- gRPC - gRPC protocol support
The plugin system uses isolated class loaders with the following strategy:
- Server API Classes (
com.arcadedb.*) - Loaded from parent class loader (shared across all plugins) - Plugin Classes - Loaded from plugin's own JAR first (isolated)
- Other Classes - Fall back to parent class loader if not found in plugin JAR
This approach ensures:
- Plugins can use different versions of third-party libraries
- Server APIs are shared for consistency and communication
- Memory efficiency through shared core classes
- Discovers plugins from
lib/plugins/directory - Manages plugin lifecycle (start, stop)
- Coordinates plugin loading with server initialization
- Custom class loader that isolates plugin dependencies
- Parent-first delegation for server API classes
- Child-first delegation for plugin-specific classes
- Metadata container for each plugin
- Tracks plugin state and lifecycle
- Associates plugin with its class loader
- Discovery - Scan
lib/plugins/directory for JAR files - Class Loading - Create isolated class loader for each plugin JAR
- Service Discovery - Use Java ServiceLoader to find
ServerPluginimplementations - Configuration - Call
configure()with server instance and configuration - Starting - Call
startService()based on installation priority - Running - Plugin provides functionality
- Stopping - Call
stopService()in reverse order - Cleanup - Close class loaders and release resources
Plugins are started in phases based on their installation priority:
BEFORE_HTTP_ON- Before HTTP server starts (default)AFTER_HTTP_ON- After HTTP server startsAFTER_DATABASES_OPEN- After databases are loaded
package com.example.myplugin;
import com.arcadedb.ContextConfiguration;
import com.arcadedb.server.ArcadeDBServer;
import com.arcadedb.server.ServerPlugin;
public class MyPlugin implements ServerPlugin {
private ArcadeDBServer server;
private ContextConfiguration configuration;
@Override
public void configure(ArcadeDBServer arcadeDBServer, ContextConfiguration configuration) {
this.server = arcadeDBServer;
this.configuration = configuration;
// Initialize your plugin configuration
}
@Override
public void startService() {
// Start your plugin services
System.out.println("MyPlugin started!");
}
@Override
public void stopService() {
// Stop your plugin services and clean up resources
System.out.println("MyPlugin stopped!");
}
@Override
public INSTALLATION_PRIORITY getInstallationPriority() {
return INSTALLATION_PRIORITY.AFTER_HTTP_ON;
}
}Create file: src/main/resources/META-INF/services/com.arcadedb.server.ServerPlugin
Content:
com.example.myplugin.MyPlugin
mvn clean packageCopy the plugin JAR to the lib/plugins/ directory in your ArcadeDB installation:
cp target/myplugin-1.0.0.jar $ARCADEDB_HOME/lib/plugins/The plugin will be automatically discovered and loaded when ArcadeDB starts:
cd $ARCADEDB_HOME
bin/server.shCheck the logs for:
[INFO] Discovered plugin: myplugin from myplugin-1.0.0.jar
[INFO] - myplugin plugin started
Plugin POMs should include server dependencies with provided scope:
<dependency>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-server</artifactId>
<version>${arcadedb.version}</version>
<scope>provided</scope>
</dependency>Plugin-specific dependencies use normal compile scope and will be packaged with the plugin:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-library</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>The Maven assembly descriptor automatically places plugin JARs in lib/plugins/:
<dependencySet>
<outputDirectory>lib/plugins</outputDirectory>
<includes>
<include>com.arcadedb:arcadedb-gremlin</include>
<include>com.arcadedb:arcadedb-postgresw</include>
<include>com.arcadedb:arcadedb-mongodbw</include>
<include>com.arcadedb:arcadedb-redisw</include>
<include>com.arcadedb:arcadedb-grpcw</include>
</includes>
<useTransitiveDependencies>false</useTransitiveDependencies>
</dependencySet>Plugins have full access to the ArcadeDB server instance:
@Override
public void configure(ArcadeDBServer arcadeDBServer, ContextConfiguration configuration) {
this.server = arcadeDBServer;
// Access databases
ServerDatabase db = server.getDatabase("mydb");
// Access HTTP server for custom endpoints
HttpServer httpServer = server.getHttpServer();
// Access security
ServerSecurity security = server.getSecurity();
}The PluginManager automatically sets the thread context class loader during plugin operations:
- During
configure()- Set to plugin's class loader - During
startService()- Set to plugin's class loader - During
stopService()- Set to plugin's class loader
This ensures proper class loading for frameworks that use the thread context class loader.
Plugins can register custom HTTP endpoints:
@Override
public void registerAPI(HttpServer httpServer, PathHandler routes) {
routes.addExactPath("/api/myplugin", exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
exchange.getResponseSender().send("{\"status\":\"ok\"}");
});
}Check that:
- Plugin JAR is in
lib/plugins/directory META-INF/services/com.arcadedb.server.ServerPluginfile exists- Service file contains correct plugin class name
- Plugin class implements
ServerPlugininterface
If you see ClassNotFoundException for server classes:
- Ensure server dependencies use
providedscope - Check that class is in
com.arcadedb.*package
If you see ClassNotFoundException for plugin classes:
- Ensure dependency is included with
compilescope - Check that JAR contains the required class
If two plugins have conflicting dependencies:
- This is the main benefit of isolated class loaders
- Each plugin can use its own version
- Ensure server API classes match across all plugins
The new plugin system is backward compatible with the legacy configuration-based loading. Both systems can coexist:
arcadedb.server.plugins=gremlin:com.arcadedb.server.gremlin.GremlinServerPlugin- Place plugin JAR in
lib/plugins/ - Include
META-INF/servicesfile - No configuration needed
- Use Provided Scope - Server dependencies should always use
providedscope - Clean Shutdown - Implement proper cleanup in
stopService() - Thread Safety - Make plugin implementations thread-safe
- Logging - Use
LogManager.instance().log()for consistent logging - Error Handling - Handle exceptions gracefully, don't crash the server
- Resource Management - Close all resources in
stopService() - Configuration - Use
ContextConfigurationfor plugin settings
See the built-in plugins for complete examples:
gremlin/- Complex plugin with custom graph managerpostgresw/- Network protocol pluginmongodbw/- Query language compatibility pluginredisw/- Simple protocol plugingrpcw/- gRPC service plugin