Making a component add-on OSGi-compatible
In order to use a component jar as an OSGi bundle, the manifest file needs to have additional headers. The headers describe the bundle and provide additional information. Some of the headers are as follows.
Bundle-SymbolicName is the only mandatory header. It specifies a unique identifier for the bundle, based on the reverse domain name convention. e.g.
com.vaadin.flow.component.button
Bundle-Name defines a human-readable name. e.g. vaadin-button-flow
Bundle-License specifies the license information of bundle. e.g. http://www.apache.org/licenses/LICENSE-2.0
Bundle-ManifestVersion indicates the OSGi specification to use for reading this bundle. The value 1 indicates OSGi release 3, and the value 2 indicates OSGi release 4 and later.
Bundle-Version specifies the version of this bundle which consists of up to four parts separated with dots.
Import-Package declares the imported packages for this bundle.
Export-Package contains a declaration of exported packages.
Require-Capability specifies that this bundle requires other bundles to provide a capability e.g. osgi.ee;filter:=”(&(osgi.ee=JavaSE)(version=1.8))”
After generating the MANIFEST.MF file, manually or using any tool, it should be added to the output jar file. This job can be done by configuring maven-jar-plugin
like this:
XML
<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>
Note | Static resources do not work in OSGi environment for now and it is required to unpack them in the application project. |
Tools
Although the headers can be added to MANIFEST.MF manually, it is recommended to use an automated tool to create them. Here two tools, both maven plugins, are briefly introduced.
Bnd maven plugin
This plugin generates required manifest entries based on specified instructions which are declared in either a file (with default name of bnd.bnd) or the plugin <configuration>
in the pom. The plugin also set default values to some headers derived from pom elements. For example, Bundle-SymbolicName
is set to artifactId
, and Bundle-Version
is deducted from artifact version. The following is an example of the usage of the plugin.
XML
<plugin>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bnd-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>bnd-process</goal>
</goals>
</execution>
</executions>
<configuration>
<bnd><![CDATA[
-exportcontents: org.example.api,org.example.types
-sources: true
Private-Package: org.example.internal.*
Bundle-Activator: org.foo.myproject.impl.Activator
]]>
</bnd>
</configuration>
</plugin>
In this example, the instructions are provided using <![CDATA[ ]]>
section in bnd
parameter. In addition to the instructions, that start with a minus sign (‘-‘), manifest headers (e.g. Private-Package
) can also be added here. For more information about instructions see Bnd Instruction Reference.
For more information about this plugin see bnd-maven-plugin documentation on GitHub.
Apache Felix Maven Bundle Plugin
This plugin is based on Bnd tool with this change that you can provide headers and instructions as nested tags in <configuration>
section. So, it may be a better choice when we want to have instructions in the pom
file. Although the values of the required entries in the manifest file can be set manually, this plugin generates reasonable default values for various headers. Here is an example on how to use the plugin.
XML
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<_exportcontents>org.example.api,org.example.types</_exportcontents>
<_sources>true</_sources>
<Private-Package>org.example.internal.*</Private-Package>
<Bundle-Activator>org.foo.myproject.impl.Activator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
With these instructions, the plugin generates for instance Bundle-Version
deducted from ${pom.version}
, Bundle-Name
set to ${pom.name}
and Bundle-SymbolicName
computed from groupId
and artifactId
. For more information see Apache Felix Maven Bundle Plugin documentation.