ADR-00010: Evolving from Package-based Plugins to Quarkus Extensions
Approval Status
Section titled “Approval Status”Status flow: Proposed → Accepted → Reviewed → Approved (or Rejected), or Not Required. A superseded ADR keeps its file; only its status changes to Superseded by NNNNN.
| Governance body | Status | Last update |
|---|---|---|
| CTN Project Team | Proposed | 2026-06-08 |
| CTN Technical Advisory Board | Pending | — |
| CTN Steering Committee | Not Required | — |
| BDI Conformance Team | Proposed | — |
| BDI Framework Team | Pending | — |
Context and Problem Statement
Section titled “Context and Problem Statement”ADR-00009 established a three-layered package structure (org.bdinetwork, org.bdinetwork.marketplace, and nl.ctn) within a single repository to facilitate rapid development while maintaining logical separation.
As the BDI ecosystem grows, we anticipate the need to deliver these layers as independent JAR files that can be “plugged in” to a core distribution. We need a roadmap to move from compile-time package separation to build-time or deployment-time artifact composition without re-architecting the application logic.
Considered Options
Section titled “Considered Options”Option 1: Package-based SPI (Status Quo)
Section titled “Option 1: Package-based SPI (Status Quo)”- Description: All layers reside in the same Maven module but use distinct package roots.
- Mechanism: Standard Jakarta CDI injection with
@Alternativeand@Priority. - Pros: Zero infrastructure overhead, fast refactoring, easy debugging.
- Cons: Harder to distribute individual plugins without the core source.
Option 2: Multi-module Artifacts (Intermediate)
Section titled “Option 2: Multi-module Artifacts (Intermediate)”- Description: Move
org.bdinetwork.bdi.spito a standalonebdi-spiMaven module. - Mechanism: Marketplace and CTN implementations move to their own modules/repositories.
- Pros: Enables independent versioning and distribution.
- Cons: Increased overhead in CI/CD and dependency management.
Option 3: Quarkus Extensions (Target)
Section titled “Option 3: Quarkus Extensions (Target)”- Description: Implementation modules are wrapped as Quarkus Extensions.
- Mechanism: Use Quarkus build-time scanning to optimize plugin discovery and native compilation.
- Pros: Optimized for GraalVM, best integration with Quarkus ecosystem, supports “drop-in” JARs via classpath scanning.
- Cons: Requires specialized Quarkus extension development knowledge.
Decision Outcome
Section titled “Decision Outcome”Chosen option: A phased approach starting with Option 1, transitioning to Option 2 for distribution, and targeting Option 3 for final optimization.
Rationale
Section titled “Rationale”- Continuity: The CDI-based SPI pattern implemented in Phase 1 is the foundation for Quarkus Extensions. Moving to Phase 2 or 3 will not require changes to the
AssociationProviderinterface or its consumers. - Simplicity: Starting with a single repo avoids the “dependency hell” of managing multiple versions of SPIs while the API is still volatile.
- Native Support: Quarkus Extensions are the only way to ensure that “drop-in” logic is properly optimized and compiled when targeting GraalVM Native Images.
Consequences
Section titled “Consequences”- Positive:
- Clear migration path from “monolith” to “plugin-host” architecture.
- Decouples implementation speed of CTN from the BDI Core stabilization.
- Negative:
- Future transition to extensions requires understanding of the Quarkus Extension API (deployment vs. runtime modules).
- Neutral:
- Developers must ensure every implementation JAR contains a
META-INF/beans.xmlto be discoverable by the CDI container.
- Developers must ensure every implementation JAR contains a
Implementation Plan
Section titled “Implementation Plan”- Phase 1 (Current): Maintain the package-based SPI using CDI
@Alternativeand@Prioritywithin theasr-servicemodule.
Example Code (Phase 1)
Section titled “Example Code (Phase 1)”The following example shows how the AssociationProvider SPI is implemented across different layers using CDI.
1. SPI Interface (org.bdinetwork.asr.spi)
public interface AssociationProvider { String getLegalName(); String getFriendlyName();}2. Default Implementation (org.bdinetwork.marketplace.asr)
@ApplicationScopedpublic class ExampleMarketplaceAssociationProvider implements AssociationProvider { @Override public String getLegalName() { return "Example Legal Name"; }
@Override public String getFriendlyName() { return "example plugin name"; }}3. CTN-Specific Override (nl.ctn.asr)
@ApplicationScoped@Alternative@Priority(1)public class CtnAssociationProvider implements AssociationProvider { @Override public String getLegalName() { return "CTN i.o."; }
@Override public String getFriendlyName() { return "Connected Trade Network"; }}4. Consuming the SPI
@Path("/hello")public class GreetingResource { @Inject AssociationProvider associationProvider;
@GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "Hello from ASR Service. Association: " + associationProvider.getFriendlyName(); }}- Phase 2: Extract the SPI interfaces and implementations into separate Maven modules when independent distribution becomes a requirement.
- Phase 3: Convert the modules into Quarkus Extensions to leverage build-time optimizations and official plugin support.
Compliance and Validation
Section titled “Compliance and Validation”- Security review completed
- Performance impact assessed
- Integration impact evaluated
- Documentation updated
- Stakeholder approval obtained
Related Documents
Section titled “Related Documents”In samenwerking met




