Skip to content
Deze documentatie wordt actief uitgebreid — kom regelmatig terug.

ADR-00010: Evolving from Package-based Plugins to Quarkus Extensions

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 bodyStatusLast update
CTN Project TeamProposed2026-06-08
CTN Technical Advisory BoardPending
CTN Steering CommitteeNot Required
BDI Conformance TeamProposed
BDI Framework TeamPending

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.

  • Description: All layers reside in the same Maven module but use distinct package roots.
  • Mechanism: Standard Jakarta CDI injection with @Alternative and @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.spi to a standalone bdi-spi Maven 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.
  • 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.

Chosen option: A phased approach starting with Option 1, transitioning to Option 2 for distribution, and targeting Option 3 for final optimization.

  • 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 AssociationProvider interface 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.
  • 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.xml to be discoverable by the CDI container.
  1. Phase 1 (Current): Maintain the package-based SPI using CDI @Alternative and @Priority within the asr-service module.

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)

@ApplicationScoped
public 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();
}
}
  1. Phase 2: Extract the SPI interfaces and implementations into separate Maven modules when independent distribution becomes a requirement.
  2. Phase 3: Convert the modules into Quarkus Extensions to leverage build-time optimizations and official plugin support.
  • Security review completed
  • Performance impact assessed
  • Integration impact evaluated
  • Documentation updated
  • Stakeholder approval obtained

In samenwerking met

Connected Trade NetworkConclusionData in LogisticsContargoInland Terminals GroupVan Berkel