The maven-osgi-plugin is deprecated and has been replaced by a new plugin: maven-bundle-plugin
The OSGi plugin for Maven 2.0 is currently under development at the Apache Felix project, and this page documents the plugin's current state of functionality and will serve as a how-to guide for its use.
The main task this plugin aims to accomplish is the generation of OSGi-compliant bundle archives. To this end, the plugin provides an integraton with Maven 2's project object model (POM) with particular focus on manipulation of the bundle's manifest and the automated generation of some headers (e.g., Bundle-ClassPath, Import-Package, and Bundle-Activator).
Current Plugin Functionality
Standard Features
The plugin provides the user with two ways to manipulate the contents of a bundle's manifest:
- Path and filename of a manifest.mf file in which the contents will be merged with the default entries generated by Maven 2. Note that any manifest entry can be added to the bundle's manifest using this technique - java-standard, osgi-standard, or custom entries. The path name is relative to the root of the Maven 2 project, and is specified using the following POM notation:
Manifest Example 1
... <plugins> <plugin> <groupId>org.apache.felix.plugins</groupId> <artifactId>maven-osgi-plugin</artifactId> <extensions>true</extensions> <version>0.3.0</version> <configuration> <manifestFile>resources/manifest.mf</manifestFile> </configuration> </plugin> </plugins> ...
- Individual plugin configuration attributes for OSGi manifest entries. Currently, only a subset of the standard OSGi manifest entries are supported so far. The intention is to implement the full set of OSGi specified manifest entries. OSGi manifest entries currently supported as plugin configuration attributes include:
- Bundle-ManifestVersion
- Bundle-ClassPath (can only be automatically generated)
- Bundle-Activator (can be automatically generated if desired, otherwise will be verified if specified)
- Bundle-Name
- Bundle-Version
- Bundle-Description
- Bundle-Vendor
- Bundle-Date
- Bundle-UpdateLocation
- Bundle-SymbolicName
- Bundle-URL
- Bundle-DocURL
- Bundle-Source
- Bundle-Category
- Export-Service
- Import-Service
- Export-Package (will be verified if specified, cannot be automatically generated)
- Import-Package (will be verified if specified, otherwise automatically generated)
- DynamicImport-Package
- Metadata-Location
- Bundle-Copyright
- Bundle-NativeCode
- Bundle-ContactAddress
- Bundle-RequiredExecutionEnvironment
- Bundle-Localization
- Require-Bundle
- Fragment-Host
- Service-Component
These manifest entries are specified as plugin configuration attributes using the following POM notation:
... <plugins> <plugin> <groupId>org.apache.felix.plugins</groupId> <artifactId>maven-osgi-plugin</artifactId> <extensions>true</extensions> <version>0.3.0</version> <configuration> <osgiManifest> <bundleName>My OSGi Application</bundleName> <bundleDescription>An example bundle application</bundleDescription> <bundleActivator>org.safehaus.bundle.Activator</bundleActivator> <importPackage>org.osgi.service.log</importPackage> <bundleVendor>Safehaus</bundleVendor> </osgiManifest> </configuration> </plugin> </plugins> ...
Additionally, the following OSGi manifest entries are automatically populated by the plugin:
- Bundle-Version
- Bundle-Classpath
- Import-Package
- Bundle-Activator
To auto-generate the Bundle-Activator manifest entries, you must explicitly specify "auto-detect", such as:
... <configuration> <osgiManifest> <bundleName>My OSGi Application</bundleName> <bundleActivator>auto-detect</bundleActivator> </osgiManifest> </configuration> ...
If you specify a value for Import-Package or Bundle-Activator, then the specified values will be verified against what is computed and warnings may be issued if discrepencies are found. The Export-Package header is also similarly verified, even though it cannot be automatically generated. The detection of the Bundle-Activator is currently simplistic and will not correctly detect cases where there are more than one potential activator, the activator is a subclass of subclass of activator, or the activator is imported.
Note: It is possible to use both methods of manifest manipulation simultaneously.
The plugin uses the Maven2 <scope/> dependency attribute in order to analyze which dependent JARs need to be embedded in the generated OSGi bundle. Maven2 dependencies specified in the project's POM that have the scope of provided or test will not be embedded in the OSGi bundle archive. Maven 2 dependencies that have scope of compile or runtime will be embedded in the OSGi bundle archive. Maven 2 dependencies have a default scope of compile when not explicitly specified in the POM.
If the plugin determines that dependent JARs will be embedded in the generated OSGi bundle archive, then the Bundle-Classpath manifest entry will be automatically created and populated with the path/filename(s) of the bundled dependencies.
The plugin automatically creates and populates the Bundle-Version manifest entry based on the POM's artifact version attribute.
Advanced Features
The plugin calculates the Import-Package manifest header by examining the byte code of the classes in the bundle. In some situations, it generates imports for packages that are not strictly necessary, such as if the bundle does not access all of the code of an embedded library. In those situations it is possible to specify <ignorePackage> tag. In some cases, the plugin does not calculate the precise set of imports. For such situations, the plugin supports a <explicitImportPackage> tag, which specifies a set of imported packages to be added to the calculated set.
The plugin automatically embeds any JAR file dependencies with a scope of compile or runtime into the bundle and will add these JAR files to the Bundle-ClassPath header. In some situations it is better to inline or unroll the dependent JAR files to that their files are simply included in the resulting bundle JAR file; this makes it possible to put the bundle JAR file on the class path like a standard JAR file. The <inlinedArtifacts> tag is used for this purpose.
Both the <ignorePackage> and <inlinedArtifacts> tags are set in the <configuration> section of the plugin, while <explicitImportPackage> is specified in the <osgiManifest> section, such as:
<project> <modelVersion>4.0.0</modelVersion> <groupId>my-osgi-bundles</groupId> <artifactId>simple</artifactId> <packaging>osgi-bundle</packaging> <version>1.0</version> <name>Simple Bundle</name> <build> <plugins> <plugin> <groupId>org.apache.felix.plugins</groupId> <artifactId>maven-osgi-plugin</artifactId> <extensions>true</extensions> <version>0.3.0</version> <configuration> <inlinedArtifacts> <inlinedArtifact>kxml2</inlinedArtifact> </inlinedArtifacts> <ignorePackage>javax.xml.parsers,org.xml.sax</ingorePackage> <osgiManifest> <bundleActivator>com.my.company.Activator</bundleActivator> <bundleName>Simple Bundle</bundleName> <bundleDescription>simple bundle</bundleDescription> <bundleVendor>Me</bundleVendor> <explicitImportPackage>org.foo.bar</explicitImportPackage> </osgiManifest> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>kxml2</groupId> <artifactId>kmxl2</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.osgi.core</artifactId> <version>??What value should be used here??</version> <scope>provided</scope> </dependency> </dependencies> </project>
How-To
Get the Maven 2.0 Runtime
The first step in the process of using the Maven 2 OSGi plugin is downloading and installing the latest version of the Maven 2 runtime itself. The current latest release is Maven 2.0 and instuctions for getting started with Maven 2 can be found at http://maven.apache.org/maven2/index.html.
Getting the maven-osgi-plugin
The Maven 2 OSGi plugin development is being hosted at the Apache Felix project. The remainder of this How-To section discusses how to obtain and install the OSGi plugin, and some of things that you need to do in order to effectively use the plugin to construct OSGi-compliant bundle archives from your Maven 2 projects.
The following steps describe how to get the maven-osgi-plugin installed in your local Maven 2 repository:
- Using the SVN client of your choice, checkout the Maven 2 OSGi plugin project.
$ svn co [http://svn.apache.org/repos/asf/incubator/felix/trunk/tools/maven2/maven-osgi-plugin]
- Using Maven 2, build and install the maven-osgi-plugin by issuing the following Maven 2 command in the root directory of the project you checked out in Step 1.
$ mvn install
Adding the Safehaus Maven 2 Repository
If you have experience using Maven 1.0 or 2.0 to compile and build software artifacts, you probably understand that one of the goals of Maven to help developers with dependancy management. While this is certainly a strength that the Maven project model offers that a traditional Ant-based build system lacks, it does require that the developers of widely-distributed libraries publish their binary distributions to a centrally-managed Maven jar repository in adherence to some naming and grouping guidelines.
To date, none of the OSGi binaries have been published to a Maven jar repository either at the Maven 1.0 Repository or the Maven 2.0 Repository. Certainly, this will need to be addressed as the Apache Felix implementation moves forward. But, to begin using the maven-osgi-plugin today, you can use the published versions in the Safehaus Maven 2 Repository by adding the repository to your Maven 2 settings.xml. After these artifacts are published at iBiblio, this activity will no longer be required.
Add a custom Maven 2 repository by placing the following in your $HOME/.m2/settings.xml:
<settings> ... <profiles> <profile> <id>myprofile</id> <repositories> <repository> <id>safehaus-repository</id> <name>Safehaus Repository</name> <url>http://m2.safehaus.org</url> </repository> </repositories> </profile> </profiles> <activeProfiles> <activeProfile>myprofile</activeProfile> </activeProfiles> ... </settings>
Once this is configured, you may use the following dependencies for OSGi R3 or R4:
<groupId>org.osgi</groupId> <artifactId>org.osgi</artifactId> <version>3.0</version>
<groupId>org.apache.felix</groupId> <artifactId>org.osgi.core</artifactId> <version>??What value should be used here??</version>
<groupId>org.apache.felix</groupId> <artifactId>org.osgi.compendium</artifactId> <version>??What value should be used here??</version>
Using the maven-osgi-plugin
To use the maven-osgi-plugin, you first need to add the plugin and some appropriate plugin configuration to your project's POM. Below is an example of a simple OSGi bundle POM for Maven 2:
<project> <modelVersion>4.0.0</modelVersion> <groupId>my-osgi-bundles</groupId> <artifactId>simple</artifactId> <packaging>osgi-bundle</packaging> <version>1.0</version> <name>Simple Bundle</name> <build> <plugins> <plugin> <groupId>org.apache.felix.plugins</groupId> <artifactId>maven-osgi-plugin</artifactId> <extensions>true</extensions> <version>0.3.0</version> <configuration> <osgiManifest> <bundleActivator>com.my.company.Activator</bundleActivator> <bundleName>Simple Bundle</bundleName> <bundleDescription>simple bundle</bundleDescription> <bundleVendor>Me</bundleVendor> </osgiManifest> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.osgi.core</artifactId> <version>??What value should be used here??</version> <scope>provided</scope> </dependency> </dependencies> </project>
Three things to note: (1) the <packaging> specifier, (2) the plugin and configuration specification, and (3) the <scope> specifier on the dependency. The org.osgi-3.0.jar is a compile-time dependency, but the scope specifier indicates that our OSGi container will provide the dependency at runtime so there is no need to embed the dependent jar into the bundle archive.
Issuing Maven 2 Lifecycle Commands
'mvn package' will compile the project code and generate a bundle jar archive of the project (in this case named simple-1.0.jar). If this jar is in turn a dependency of another project, it can still be included in another Maven 2 POM as usual.
$ mvn package
'mvn install' will compile the project code, generate a bundle jar archive, and install the jar in your local Maven 2 repo.
$ mvn install
'mvn deploy' will compile the project code, generate a bundle jar archive, install the jar in your local Maven 2 repo, and deploy the jar to any remote Maven 2 repos you have configured.
$ mvn deploy