Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

Overview

For many years the Apache Felix maven-bundle-plugin was the standard plugin used for building OSGi bundle projects in Maven. However, this has changed since the bnd project (which is also used as library inside maven-bundle-plugin) introduced their own Maven plugin, the bnd-maven-plugin. This plugin quickly catched up with most features that maven-bundle-plugin provides, and is always released immediately together with new bnd versions. Thus it is recommended to switch maven projects to the bnd-maven-plugin (also there is no urgent need to do this for stable projects).

This article describes the required steps. It is mainly focused on projects inheriting from the wcm.io AEM Global Parent POM, which contains all basic configuration suitable for Maven bundle projects using either maven-bundle-plugin or bnd-maven-plugin.

Migration Steps

Step 1: Update aem-global-parent

Update to aem-global-parent 1.4.0 or later - this version contains the base configuration of the bnd-maven-plugin.

Step 2: Update packaging

Unlike the maven-bundle-plugin the bnd-maven-plugin does no longer use the “bundle” packaging type - change the packaging type to “jar”.

Step 3: Replace Maven Plugins

Replace the Maven Bundle Plugin

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
</plugin>

with:

<plugin>
  <groupId>biz.aQute.bnd</groupId>
  <artifactId>bnd-maven-plugin</artifactId>
</plugin>
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
    </archive>
  </configuration>
</plugin>

The presence of the maven-bundle-plugin was optional if you had not the need to customize anything. If your Maven project is a bundle project you have to add the bnd-maven-plugin.

The maven-jar-plugin customization is only required due to this unresolved issue: MJAR-193. It cannot be defined in the parent POM as this would break the build of non-bundle Maven projects.

If you want to activate the Semantic Versioning check for the exported API of your bundles, additionally enable the bnd-baseline-maven-plugin. This is usually only required if your bundle contains reusable code that is used by other bundles/projects, not for “normal” AEM project bundles.

<plugin>
  <groupId>biz.aQute.bnd</groupId>
  <artifactId>bnd-baseline-maven-plugin</artifactId>
</plugin>

Step 4: Migrate Bundle Header Instructions

If you have defined custom bundle header instructions using the <instructions> configuration configuration option of the maven-bundle-plugin, you have to migrate them to the different syntax of the bnd-maven-plugin.

Example from maven-bundle-plugin:

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
    <instructions>
      <Sling-Initial-Content>
        SLING-INF/app-root;overwrite:=true;ignoreImportProviders:=xml;path:=/apps/wcm-io/wcm/commons
      </Sling-Initial-Content>
      <Sling-Model-Packages>
        io.wcm.wcm.commons
      </Sling-Model-Packages>
      <Sling-Namespaces>wcmio=http://wcm.io/ns</Sling-Namespaces>
      
      <Import-Package>
        <!-- For build compatibility with Java 11 -->
        javax.annotation;version="[0.0,2)",
        *
      </Import-Package>

    </instructions>
  </configuration>
</plugin>

Translates with bnd-maven-plugin to:

<plugin>
  <groupId>biz.aQute.bnd</groupId>
  <artifactId>bnd-maven-plugin</artifactId>
  <configuration>
    <bnd>
      Sling-Initial-Content: SLING-INF/app-root;overwrite:=true;ignoreImportProviders:=xml;path:=/apps/wcm-io/wcm/commons
      Sling-Model-Packages: io.wcm.wcm.commons
      Sling-Namespaces: wcmio=http://wcm.io/ns
      
      Import-Package: \
        <!-- For build compatibility with Java 11 -->\
        javax.annotation;version="[0.0,2)",\
        *
    </bnd>
  </configuration>
</plugin>

Notes for this translation:

  • We recommend to keep the Instructions in the pom.xml instead of using a separate bnd.bnd file. Defining it in the POM allows to inherit (and merge) settings via POM parent hierarchies, and allows to add XML comments (event inside a line split over multiple lines).

  • The <bnd> configuration option does not support nested sub elements. Instead, it’s just a text file using the notation <Instruction>: <Value>.

  • You can split a long line into multiple lines by putting \ on the end of each line (also on lines with XML comments!).

  • See the bnd documentation for a full index of bnd instructions.

  • It’s usually not required to put <![CDATA[…]]> around your bnd instructions. You might have to escape characters special to XML then, though.

Step 5: Verify Package Exports

The maven-bundle-plugin has a default behavior that always export all packages of the project that do not include “impl” or “internal” somewhere in the package name. This is no longer the case for the bnd-maven-plugin! The bnd-maven-plugin exports only packages that contain a package-info.java with an OSGi @Export annotation or an OSGi @Version annotation (the latter is a special configuration defined in aem-global-parent). This is a useful default setting for shared libraries that should export only those packages really required.

For “normal” AEM application bundles it may be too cumbersome to export each package explicit (especially as all packages containing Sling Models have to be exported to be accessible from HTL scripts). Also it would complicate the migration of existing projects relying on the old behavior. For those projects you can add this bnd instruction to your project’s POM file - example:

<!-- Export all non-internal packages by default -->
Export-Package: !*.impl.*,!*.internal.*,\
    io.wcm.samples.*

Replace io.wcm.samples.* with the topmost package from your project.

Optional Steps

Embedding JARs/Classes in the bundle

The bnd-maven-plugin has no direct counterpart for the Embed-Dependency feature of the maven-bundle-plugin which is used to included 3rdparty JARs into the bundle (inline or as JAR file).

To inline a dependency you can use the -conditionalpackage instruction.

If you want to include a dependency as JAR file you can copy it using maven-dependency-plugin and include it using Include-Resource and Bundle-ClassPath instruction, see example.

Legacy Felix SCR Annotations

The bnd-maven-plugin configured in aem-global-parent does no longer support the deprecated Felix SCR Annotations by default. It is recommended to update your project to make use of the standard OSGI annotations instead. If this is not possible you can add support for them for the bnd-maven-plugin:

Add this dependencies to the bnd-maven-plugin:

<dependency>
  <groupId>org.apache.felix</groupId>
  <artifactId>org.apache.felix.scr.bnd</artifactId>
  <version>1.9.4</version>
</dependency>
<dependency>
  <groupId>org.apache.felix</groupId>
  <artifactId>org.apache.felix.scr.annotations</artifactId>
  <version>1.12.0</version>
</dependency>

And add this bnd Instruction to activate the Felix SCR bnd plugin:

<!-- Support parsing of Felix SCR annotations through the felix.scr.bnd plugin -->
-plugin.felixscrannotations: org.apache.felix.scrplugin.bnd.SCRDescriptorBndPlugin;destdir=target/classes
  • No labels