Common Plugins¶
Group the API and implementation of the framework plugin system.
Depend on plugin-api when authoring a plugin or extension point, and plugin-core in the host that loads and manages plugins. The aggregator itself does not supply a standalone runtime JAR.
| Maven artifact | Packaging | Source project |
|---|---|---|
org.fireflyframework:fireflyframework-plugins |
pom |
modules/plugins |
Part of Team-wide architecture.
Host and extension lifecycle¶
flowchart LR
Host[Host application] --> Manager[PluginManager]
Manager --> Load[Load and initialize]
Load --> Start[Start plugin]
Start --> Registry[ExtensionRegistry]
Registry --> Points[Host extension points]
Manager --> Stop[Stop and unload]
The API defines plugin metadata, lifecycle, and extension contracts. The core supplies the default manager, dependency resolver, and extension registry.
In the onboarding service¶
A host may expose an extension point for product-specific onboarding checks. Plugin authors use plugin-api; the host uses plugin-core to load classes and manage their lifecycle.
Choose a component¶
| Related component | Why it belongs nearby |
|---|---|
| Plugin API | Define plugins, extension points, extension registration, and lifecycle contracts without the host implementation. |
| Plugin Core | Load plugins, resolve dependencies, and manage extension registration in a host process. |
Add the component¶
Installation and version availability explains source builds and published releases.
This artifact has pom packaging and groups child projects. Select a concrete child JAR for the application classpath.
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>plugin-api</artifactId>
<version>26.10.20-SNAPSHOT</version>
</dependency>
Quick start¶
The Java examples in this section are API fragments for application code. Use the stated imports and supply the application-owned collaborators described alongside them.
1. Define an extension point (in the host)¶
import org.fireflyframework.plugin.annotation.ExtensionPoint;
@ExtensionPoint(id = "payment-processor", description = "Processes payments")
public interface PaymentProcessor {
PaymentResult process(PaymentRequest request);
}
2. Write a plugin that contributes an extension¶
A plugin is a class with a no-arg constructor that implements org.fireflyframework.plugin.api.Plugin. Its extensions are @Extension-annotated inner classes that implement an extension-point interface.
import org.fireflyframework.plugin.annotation.Extension;
import org.fireflyframework.plugin.annotation.Plugin;
import org.fireflyframework.plugin.api.PluginException;
import org.fireflyframework.plugin.model.PluginMetadata;
@Plugin(
id = "stripe-payments",
name = "Stripe Payments",
version = "1.0.0",
description = "Stripe payment processing",
author = "Acme Corp"
)
public class StripePlugin implements org.fireflyframework.plugin.api.Plugin {
@Override
public PluginMetadata getMetadata() {
return PluginMetadata.builder()
.id("stripe-payments")
.name("Stripe Payments")
.version("1.0.0")
.build();
}
@Override public void initialize() throws PluginException { /* set up clients */ }
@Override public void start() throws PluginException { /* begin work */ }
@Override public void stop() throws PluginException { /* pause work */ }
@Override public void destroy() throws PluginException { /* release resources */ }
@Extension(extensionPointId = "payment-processor", priority = 100)
public static class StripePaymentProcessor implements PaymentProcessor {
@Override
public PaymentResult process(PaymentRequest request) {
return /* call Stripe and map the result */ null;
}
}
}
3. Load, run, and use the extension (in the host)¶
import org.fireflyframework.plugin.api.ExtensionRegistry;
import org.fireflyframework.plugin.api.PluginManager;
import org.fireflyframework.plugin.core.DefaultPluginManager;
PluginManager manager = new DefaultPluginManager();
manager.initialize();
ExtensionRegistry registry = manager.getExtensionRegistry();
// Extension points must be registered before extensions can be added to them:
registry.registerExtensionPoint("payment-processor", PaymentProcessor.class);
// Loading a plugin also initializes it and auto-registers its @Extension classes:
manager.loadPlugin(StripePlugin.class);
manager.startPlugin("stripe-payments");
// Highest-priority extension for the point:
PaymentProcessor processor = registry.<PaymentProcessor>getExtension("payment-processor").orElseThrow();
PaymentResult result = processor.process(request);
// ...or fan out across all contributed extensions (ordered by priority, highest first):
for (PaymentProcessor p : registry.<PaymentProcessor>getExtensions("payment-processor")) {
// ...
}
manager.shutdown(); // stops, unloads, and destroys all plugins
Configuration and wiring¶
This POM has no runtime configuration namespace. Configure the selected child libraries in the application that uses them.
Build and test¶
Use Java 25. From the repository root, build this component with its required dependencies:
git clone https://github.com/fireflyframework/fireflyframework-jafly.git
cd fireflyframework-jafly
./mvnw -pl :fireflyframework-plugins,:plugin-api,:plugin-core -am verify
./mvnw -pl :fireflyframework-plugins,:plugin-api,:plugin-core -am install
verify runs the selected projects' tests. install makes the current build available in your local Maven repository.
This subproject has no authored src/test/java suite. Its Maven build still validates the configured compilation/generation and any reactor prerequisites. Use the consuming component tests to validate integration behavior.
Detailed reference¶
How It Works¶
- Loading.
loadPlugin(Class)instantiates the plugin via its no-arg constructor, reads itsPluginMetadata, records aPluginDescriptorin stateLOADED, callsinitialize()(moving it toINITIALIZED, orFAILEDon error), then registers its@Extensioninner classes. - Starting.
startPlugin(id)first resolves declared dependencies viaPluginDependencyResolverand starts any not-yet-started dependencies, then calls the plugin'sstart()(→STARTED). - Extension lookup. extensions are validated to implement their point, stored thread-safely, and returned ordered by descending priority.
getExtensionreturns the single highest-priority extension;getExtensionsreturns them all. - Shutdown.
unloadPlugin(id)stops a running plugin, unregisters its extensions, and callsdestroy().shutdown()does this for every loaded plugin.
Configuration¶
This module has no configuration properties. It contains no Spring Boot auto-configuration and no @ConfigurationProperties classes. You wire a PluginManager (typically DefaultPluginManager) yourself, as a plain object or as a Spring @Bean, and drive it through its API. Plugin metadata (ids, versions, dependencies, extension priorities) is declared in code via annotations or the PluginMetadata builder, not in application.yml.
Continue the application¶
Use the Plugin API guide for the next part of this integration. The runnable submission/query service is in Getting started.