Declarative Services in depth
Declarative Services (DS) is the default component model for modern OSGi.
Component lifecycle
SCR—the Service Component Runtime—reads component descriptions, waits for required references and configuration, creates the instance, injects references, calls activation, publishes services, and later deactivates it.
@Component(
service = Reconciler.class,
configurationPid = "com.acme.reconciler"
)
public final class DefaultReconciler implements Reconciler {
private Ledger ledger;
@Reference
void bindLedger(Ledger ledger) { this.ledger = ledger; }
@Activate
void activate(ReconcilerConfig config) { /* validate */ }
}Use constructor injection for mandatory unary references when your DS level and tooling support it. Use bind/unbind methods when dynamic replacement is a real requirement.
Cardinality
1..1 is one mandatory service; 0..1
optional; 1..n at least one; 0..n any number.
Multiple cardinality can inject a collection, map, tuple, or component
service objects depending on the field option.
Immediate and delayed
A delayed component activates on first service use, reducing startup work. Immediate components activate as soon as satisfied. Components without a service are normally immediate. Avoid making everything eager.
Configuration policy
OPTIONAL, REQUIRE, and IGNORE
decide whether configuration is necessary. Typed configuration
annotations turn string dictionaries into a checked contract. Validate
invariants during activation so invalid instances never publish.
Factory components
A factory configuration can create multiple independently configured component instances—for example one connector per charging-network tenant.
Tooling
bnd generates descriptors and requirements from DS annotations. At
runtime, inspect scr:list, scr:info, satisfied
references, component failure reasons, and configuration PIDs before
editing code.
Feynman check
A bundle can be ACTIVE while a DS component is unsatisfied. Explain this by separating bundle lifecycle from component prerequisites.