fe-extension-spi Developer Integration Guide
This guide is for plugin authors and business module integrators. It answers three practical questions:
- What fe-extension-spi is responsible for.
- When to use SPI only, and when to combine SPI with Loader.
- How to implement a plugin package that Doris FE can discover and execute.
fe-extension-spi provides contracts only. It does not provide runtime loading.
Core contracts in this module:
- Plugin: plugin instance lifecycle.
- PluginFactory: plugin factory contract.
- PluginContext: runtime configuration carrier.
- PluginException: common runtime exception type.
Capabilities intentionally excluded from this module:
- Directory scanning.
- Jar discovery and resolution.
- Classloader creation and close.
- Load failure aggregation and staging.
- Loaded plugin runtime registry.
Those runtime capabilities belong to fe-extension-loader.
2.1 When SPI Only Is Enough
Use fe-extension-spi directly if:
- Your module already has a custom loading pipeline.
- Your module already has a classloader framework.
- You only need compile-time contracts for plugin implementers.
2.2 When To Use SPI + Loader
Use SPI + Loader if:
- You want directory-driven loading by pluginRoots.
- You want unified child-first classloading behavior.
- You want standardized load failure stages (scan, resolve, discover, etc.).
- You want to reduce duplicated loading code in each business module.
Responsibilities:
- initialize(context): initialize plugin instance.
- close(): release plugin resources.
Recommendations:
- Keep initialize minimal and deterministic.
- Make close idempotent.
- Do not open external connections in static initializers.
Responsibilities:
- name(): return stable logical plugin name.
- create(): create a plugin instance.
- create(context): optional context-aware create path (defaults to create()).
Recommendations:
- Keep name() stable across environments.
- Keep create() lightweight and side-effect-free.
- Let business modules decide instance caching policy.
Responsibilities:
- Carry runtime config (Map<String, String>).
- Provide input for plugin initialization.
Recommendations:
- Use stable key prefixes (for example: ldap.*, auth.*).
- Validate required keys and apply defaults in plugin code.
Responsibilities:
- Represent common plugin runtime failures.
Recommendations:
- Include useful context in message: plugin name, stage, and key config item.
- Keep original cause to preserve root-cause traceability.
4. Minimal Integration Steps
4.1 Implement Plugin Class
public final class DemoPlugin implements Plugin {
@Override
public void initialize(PluginContext context) {
// init
}
@Override
public void close() {
// cleanup
}
}
4.2 Implement Factory Class
public final class DemoPluginFactory implements PluginFactory {
@Override
public String name() {
return "demo";
}
@Override
public Plugin create() {
return new DemoPlugin();
}
}
4.3 Add ServiceLoader Declaration
File path:
META-INF/services/org.apache.doris.extension.spi.PluginFactory
File content:
com.example.demo.DemoPluginFactory
Your plugin jar should include:
- Factory implementation class.
- Plugin implementation class.
- META-INF/services/... service declaration file.
5. Constraints for Plugin Authors
- name() must not be empty and should be globally distinguishable.
- Fail fast during invalid initialization to avoid partial state.
- Release thread pools and connection pools in close().
- Avoid global mutable state inside plugin logic.
6. Common Errors And Troubleshooting
6.1 Factory Not Discovered
Check in this order:
- Is META-INF/services/... file present?
- Is provider class name fully qualified and correctly spelled?
- Is the factory class included in final jar?
6.2 Plugin Creation Failure
Check in this order:
- Does factory create() depend on uninitialized resources?
- Are required PluginContext entries missing?
- Are plugin dependency jars complete?
6.3 Resource Leak After Runtime
Check in this order:
- Does close() actually release pools and handles?
- Is business code holding strong references to old plugin instances?
- In external loading mode, is classloader close strategy applied?
7. Relationship With Loader
Recommended composition:
- Define plugin contracts in fe-extension-spi.
- Perform directory-driven loading in fe-extension-loader.
- Do factory registration, instance caching, and routing in business modules.
Detailed Loader integration guide:
../fe-extension-loader/README.md
- Chinese developer guide: README_CN.md
- Loader module runtime guide: ../fe-extension-loader/README.md
- Unified runtime design (CN): ../fe-authentication/EXTENSION_LOADER_UNIFIED_DESIGN_CN.md