This section explains how to set up a Maven project for an API/provider bundle, where the API packages and implementation packages are kept in separate Maven projects, but then combined into a single bundle at build-time.
You can demonstrate an API/provider build-time combination bundle by modifying the
Maven configuration of the hello-paris-impl bundle. By exploiting the
Bnd utility's provide:=true clause, you can modify the instructions for
the Maven bundle plug-in, so that the
org.fusesource.example.hello.paris API package gets included in the
hello-paris-impl bundle at build time.
Whenever a bundle plays the role of provider with respect to a particular API
package, you must indicate this explicitly by attaching the
provide:=true clause to the API package, either in an import
instruction or in an export instruction (otherwise, by default, the bundle plug-in
would assume that the bundle is a consumer of the API package).
In particular, for an API/provider build-time combination bundle, you must
export the org.fusesource.example.hello.paris
API package and attach the provide:=true clause, as follows:
<instructions>
...
<Export-Package>
...
${project.groupId}.hello.paris*;provide:=true;version=${project.version},
</Export-Package>
...
</instructions>Exporting a package with the provide:=true clause has a very
important side effect: if the code for the exported package is not in the
current Maven project, the Maven bundle plug-in adds the package code to the
bundle at build time.
Code from the following Maven projects is included in the
hello-paris-impl bundle:
hello-paris-implContains the private package,
org.fusesource.example.hello.paris.impl. Build this bundle to create the API/provider build-time combination bundle,hello-paris-impl.hello-parisContains the public API package,
org.fusesource.example.hello.paris. This project is a prerequisite forhello-paris-impland must be built (usingmvn install) before thehello-paris-implproject. You do not deploy thehello-parisbundle directly into the OSGi container, however.
The following import and export rules apply to the hello-paris-impl
bundle, when it is configured as an API/provider build-time combination:
Exporting own packages—no own packages to export, because the
hello-paris-implMaven project contains only private implementation packages.Exporting dependent packages—export the public API package,
org.fusesource.example.hello.paris, with theprovide:=trueclause, which causes the API code to be included in thehello-paris-implbundle at build time.Importing own packages—import the public API package,
org.fusesource.example.hello.paris.Importing dependent packages—any external package dependencies must be imported.
To include the API from the hello-paris bundle in the
hello-paris-impl bundle, add the
org.fusesource.example.hello.paris package to the
Export-Package instruction with the provide:=true
clause attached, as shown in Example 2.3. Compare this with the
regular API/provider case, Example 2.2, which
takes the same approach of exporting the API package with the
provide:=true clause. The semantics, however, are a bit different,
because the current example pulls in the API package from a separate Maven
project.
Example 2.3. Plug-In Settings for Build-Time Combination
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Import-Package>*</Import-Package>
<Export-Package>
!${project.groupId}*.impl*,
!${project.groupId}*.internal*,
${project.groupId}.hello.paris*;provide:=true;version=${project.version},
</Export-Package>
</instructions>In the preceding example, the included
org.fusesource.example.hello.paris API package is given the
same version as the hello-paris-impl Maven
project, by adding the version=${project.version} clause to the export
instruction. In practice, however, you might not always want to assign versions in
this way. You might prefer to assign distinct versions to the
API package (from the hello-paris Maven project) and the implementation
package (from the hello-paris-impl Maven project).
The alternative approach you can take is to store version information at
package granularity in a packageinfo file (see
Export versions at package granularity for details). The
Maven bundle plug-in automatically scans your source code, looking for
packageinfo files and extracting the version information from them.
In this case, you must omit the version clause from the export instruction, as
follows:
<Export-Package>
!${project.groupId}*.impl*,
!${project.groupId}*.internal*,
<!-- hello.paris version stored in packageinfo -->
${project.groupId}.hello.paris*;provide:=true,
</Export-Package>When you build the bundle using Maven, the Maven bundle plug-in automatically
generates the following MANIFEST.MF file:
Manifest-Version: 1.0 Import-Package: org.fusesource.example.hello.paris;version="[1.0,1.1)" ,org.fusesource.example.time;version="[1.0,2)",org.osgi.service.bluep rint;version="[1.0.0,2.0.0)" Export-Package: org.fusesource.example.hello.paris;uses:="org.fusesour ce.example.time";version="1.0" Built-By: FBOLTON Tool: Bnd-1.15.0 Bundle-Name: hello-paris-impl Created-By: Apache Maven Bundle Plugin Export-Service: org.fusesource.example.hello.paris.HelloParis Build-Jdk: 1.6.0_24 Bundle-Version: 1.0.0 Bnd-LastModified: 1302098214984 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.fusesource.example.hello-paris-impl
The Import-Package header imports both the public API package,
org.fusesource.example.hello.paris, and the external package
dependencies—for example, org.fusesource.example.time.
The Export-Package header exports the public API package,
org.fusesource.example.hello.paris, while the uses
clause declares a transitive dependency on the
org.fusesource.example.time package.
The Export-Service header advertises the OSGi service as a
HelloParis instance.








