Feature Aggregation

May 8, 2026 · View on GitHub

When creating aggregates, extensions are merged into the resulting aggregate feature. There are default rules for aggregating extension content, which essentially is appending all the extension content of a given type. However custom merge plugins can also be provided. After the merge a postprocessor is always run which can perform additional operations based on the extension content. Note that both the aggregate task of the slingfeature-maven-plugin as well as the launcher perform merge operations on all the feature models these are provided with.

Resolving artifact clashes

When two features contribute artifacts (typically bundles) with the same Maven groupId:artifactId at different versions, the aggregator requires an explicit override rule. Rules are added via BuilderContext.addArtifactsOverride(...) and use a fake ArtifactId whose version field carries the rule:

RuleOutcome
HIGHESTPick the artifact with the highest version (OSGi version order)
LATESTPick the last contributed artifact
FIRSTPick the first contributed artifact
ALLKeep all candidates
<x.y.z>Pick the artifact whose version equals the literal value

The groupId and artifactId of the override are matched against the clashing artifacts; * matches anything. A typical wildcard rule is *:*:HIGHEST.

Resolving Bundle-SymbolicName collisions

The Maven-coordinate clash mechanism above is blind to OSGi identity. Two bundles can have different groupId:artifactId but the same Bundle-SymbolicName — typically when one source synthesises Maven coordinates from the OSGi manifest because the JAR has no embedded Maven metadata (META-INF/maven/.../pom.properties). The aggregator lets both through; the OSGi runtime then refuses to install duplicates with Bundle symbolic name and version are not unique.

Set BuilderContext.setOsgiBsnCollisionDetection(true) to detect this. After the standard GAV merge, every assembled bundle's manifest is read via the configured ArtifactProvider, bundles are grouped by BSN (parameters such as ;singleton:=true are stripped), and any group of two or more is resolved through the same wildcard *:*:<rule> overrides described above. If detection is enabled and a colliding group has no matching override, assembly fails — symmetric with the existing Artifact override rule required error for unresolved Maven-GAV clashes.

ArtifactProvider must be configured for detection to do anything. Bundles whose manifest cannot be read are passed through untouched.