The native bnd Workspace and Maven

NOTE: If you are looking information about the bnd-maven-plugin or bnd-export-maven-plugin this is the wrong article. Have a look here and here to find examples and the documentation of the plugins.

Preamble

This article will describe the following things:

  • The difference between the aQute.bnd.repository.maven.provider.MavenBndRepository and the aQute.bnd.repository.maven.pom.provider.BndPomRepository
  • How to deploy a BOM (Bill of Materials) aka. pom index file with bnd.
  • How to provide additional information to bnd to create decent pom files for your bundles

The different Repositories

Where maven only supports maven repositories or PDE only P2Update sites as a Repository type, bnd supports a lot more and makes it easy to grab dependencies from whatever source you desire.

A list of currently supported types are:

  • Maven Bnd Repository Plugin
  • Bnd Pom Repository
  • aQute.bnd.repository.p2.provider.P2Repository
  • aQute.bnd.repository.osgi.OSGiRepository
  • aQute.bnd.repository.osgi.LocalIndexedRepo
  • aQute.bnd.repository.fileset.FileSetRepository

What is the difference between MavenBndRepository and BndPomRepository

Both types can work with release or snapshot maven repositories. The two main differences are that the MavenBndRepository can be used as a release repository and that it does not look into transitive dependencies.

Examples:

-plugin.gecko: \
    aQute.bnd.repository.maven.provider.MavenBndRepository;\
        releaseUrl=https://devel.data-in-motion.biz/nexus/repository/maven-releases/;\
        snapshotUrl=https://devel.data-in-motion.biz/nexus/repository/maven-snapshots/;\
        index=${.}/dim_nexus.maven;\
        name='DIM Nexus'

-plugin.geckoemf:\
    aQute.bnd.repository.maven.pom.provider.BndPomRepository;\
        name="Gecko EMF";\
        releaseUrls="https://devel.data-in-motion.biz/nexus/repository/dim-release/,https://repo.maven.apache.org/maven2/";\
        snapshotUrls=https://devel.data-in-motion.biz/nexus/repository/dim-snapshot/;\
        revision="org.gecko.emf:org.gecko.emf.osgi.index:1.0.1, org.gecko.emf.mongo:org.gecko.mongo.osgi.index:1.0.2"

The maven Repository is accompanied by a index file that contains a list of GAV Coordinates. An Example looks like this:

org.gecko.emf:org.gecko.emf.osgi.api:3.3.1
org.gecko.emf:org.gecko.emf.osgi.component:2.2.12

This gives you fine grained control overthe dependencies available in your workspace. Besides the jar, it can also reference e.g. source jars or javadoc jars as well.

# will make the source jar part of the repository. The Version is in this case a Variable, that is maintained elsewhere
org.apache.lucene:lucene-analyzers-common:jar:sources:${lucene-version}

The BndPomRepository in comparison can have multiple repositories to resolve its required dependencies. It will resolve the revisions given to it and add them to your repository. It will also look at the pom files and download all the Artifacts marked as compile dependencies (not sure about the runtime dependencies).

Note: With this can become like maven and download half the Internet before you can get started.

What dependencies you need can be told in 3 ways:

  1. revision: It takes a comma separated List of revisions.
  2. pom: A comma separated list of URIs to pom files.
  3. query: A Solr query for repository that supports such.

Only one of the options can be used. For more details look at the Bnd Pom Repository documentation.

How to enable the creation of a pom.xml in a workspace/bundle

If you use the -pom instruction with e.g. true as value bndwill create a pom.xml and pom.properties in META-INF/<groupId>/<artifactId>.

If your you use SNAPSHOT versions like 1.0.0-SNAPSHOTyou can give bndan instruction to replace the snapshot e.g. for releases. Examples can be:

# simply removes the snapshot and leaves 1.0.0
-snapshot:

# replace it with a timesatmp
- snapshot: ${tstamp}

OSGi and maven have one main difference in their versions. bndproduces proper OSGi Versions. Meaning that 1.0.0-SNAPSHOT will become 1.0.0.SNAPSHOT. Maven however requires the - for a proper SNAPSHOT. Thus the Version needs to be masked in the pom for a proper SNAPSHOT build. This can be done by this snippet:

-pom: version=${versionmask;===s;${@version}}

For details more details on the versionmask macro look here.

How to deploy a BOM or Index pom.xml with bnd, without invoking maven?

If you have activated pom generation, a BOM (Bill of Materials) or index pom.xml is simple, because basically ever project produces its own BOM. bnd takes all dependencies in the -buildpath instruction and tries to create maven dependencies for it. The dependencies will have the scope complie. Note that all referenced dependencies need a generated pom.properties in it, because bnd calculates the GAV from them.

To have a pure BOM build and late release, create an empty project and add the following to your bnd.bnd:

# always use a Version, to make sure you get the right dependecy
# version=project for multi bundle projects will not work
-buildpath:\
    my.fancy.bundle.1;version=latest,\
    my.external.dependency;version=1.2

# can also be done globally in your cnf/build.bnd
-pom: version=${versionmask;===s;${@version}}

# Nothing to compile here
-resourceonly: true

# if you have baselining active, it will remind you to change the version
Bundle-Version:1.0.0.SNAPSHOT   

Chose your Maven Bnd Repository Plugin of choice as release repo and you should be set.

Usually BOMs are of the packaging type pom. In our case the they are real jars, but maven and bnd can read them non the less.

A dependency is missing in my pom.xml generated by bnd, what can I do?

  1. Make sure the dependency you reference has a pom.properties in the proper location.
  2. Make sure that bnd uses the right version. If you add something to your ``-buildpath` without version, bnd will use the first dependency it finds, that might not be the one you desire.
  3. In case the dependency has no proper pom.properties included, you can overwrite/append dependencies with the following:
# use it like this and it will only put the named dependencies in your pom
-maven-depdendencies:\
my.self.choosen.namespace;\
    groupId=my.group;\
    articatId=artifact.id;\
    version=1.2.3,\
my.self.choosen.namespace2;\
    groupId=my.group;\
    articatId=artifact.id.2;\
    version=1.2.5

# using a namespace, this will be added to the autogenerated dependencies
-maven-depdendencies.mydeps:\
my.self.choosen.namespace;\
    groupId=my.group;\
    articatId=artifact.id;\
    version=1.2.3,\
my.self.choosen.namespace2;\
    groupId=my.group;\
    articatId=artifact.id.2;\
    version=1.2.5

by Ilenia Salvadori, Mark Hoffmann, Jürgen Albert