Chapter 3. Building an OSGi Bundle
Abstract
This chapter describes how to build an OSGi bundle using Maven. For building bundles, the Maven bundle plug-in plays a key role, because it enables you to automate the generation of OSGi bundle headers (which would otherwise be a tedious task). Maven archetypes, which generate a complete sample project, can also provide a starting point for your bundle projects.
3.1. Generating a Bundle Project Copy linkLink copied to clipboard!
3.1.1. Generating bundle projects with Maven archetypes Copy linkLink copied to clipboard!
To help you get started quickly, you can invoke a Maven archetype to generate the initial outline of a Maven project (a Maven archetype is analogous to a project wizard). The following Maven archetypes can generate projects for building OSGi bundles:
3.1.2. Apache CXF karaf-soap-archetype archetype Copy linkLink copied to clipboard!
The Apache CXF karaf-soap-archetype archetype creates a project for building a service from Java. To generate a Maven project with the coordinates, GroupId:ArtifactId:Version, enter the following command:
mvn archetype:generate \
-DarchetypeGroupId=io.fabric8.archetypes \
-DarchetypeArtifactId=karaf-soap-archetype \
-DarchetypeVersion={fabricVersion} \
-DgroupId=GroupId \
-DartifactId=ArtifactId \
-Dversion=Version \
-Dfabric8-profile=ProfileName
The backslash character, \, indicates line continuation on Linux and UNIX operating systems. On Windows platforms, you must omit the backslash character and put all of the arguments on a single line.
3.1.3. Apache Camel archetype Copy linkLink copied to clipboard!
The Apache Camel OSGi archetype creates a project for building a route that can be deployed into the OSGi container. To generate a Maven project with the coordinates, GroupId:ArtifactId:Version, enter the following command:
mvn archetype:generate \
-DarchetypeGroupId=org.apache.camel.archetypes \
-DarchetypeArtifactId=camel-archetype-blueprint \
-DarchetypeVersion=2.21.0.fuse-000055-redhat-2 \
-DgroupId=GroupId \
-DartifactId=ArtifactId \
-Dversion=Version
3.1.4. Building the bundle Copy linkLink copied to clipboard!
By default, the preceding archetypes create a project in a new directory, whose names is the same as the specified artifact ID, ArtifactId. To build the bundle defined by the new project, open a command prompt, go to the project directory (that is, the directory containing the pom.xml file), and enter the following Maven command:
mvn install
The effect of this command is to compile all of the Java source files, to generate a bundle JAR under the ArtifactId/target directory, and then to install the generated JAR in the local Maven repository.
3.2. Modifying an Existing Maven Project Copy linkLink copied to clipboard!
3.2.1. Overview Copy linkLink copied to clipboard!
If you already have a Maven project and you want to modify it so that it generates an OSGi bundle, perform the following steps:
3.2.2. Change the package type to bundle Copy linkLink copied to clipboard!
Configure Maven to generate an OSGi bundle by changing the package type to bundle in your project’s pom.xml file. Change the contents of the packaging element to bundle, as shown in the following example:
<project ... >
...
<packaging>bundle</packaging>
...
</project>
The effect of this setting is to select the Maven bundle plug-in, maven-bundle-plugin, to perform packaging for this project. This setting on its own, however, has no effect until you explicitly add the bundle plug-in to your POM.
3.2.3. Add the bundle plug-in to your POM Copy linkLink copied to clipboard!
To add the Maven bundle plug-in, copy and paste the following sample plugin element into the project/build/plugins section of your project’s pom.xml file:
<project ... >
...
<build>
<defaultGoal>install</defaultGoal>
<plugins>
...
<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>2.3.7</version> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName> <Import-Package></Import-Package>
</instructions>
</configuration>
</plugin>*
</plugins>
</build>
...
</project>
Where the bundle plug-in is configured by the settings in the instructions element.
3.2.4. Customize the bundle plug-in Copy linkLink copied to clipboard!
For some specific recommendations on configuring the bundle plug-in for Apache CXF, see Section 3.3, “Packaging a Web Service in a Bundle”.
For an in-depth discussion of bundle plug-in configuration, in the context of the OSGi framework and versioning policy, see olink:OsgiDependencies/OsgiDependencies.
3.2.5. Customize the JDK compiler version Copy linkLink copied to clipboard!
It is almost always necessary to specify the JDK version in your POM file. If your code uses any modern features of the Java language—such as generics, static imports, and so on—and you have not customized the JDK version in the POM, Maven will fail to compile your source code. It is not sufficient to set the JAVA_HOME and the PATH environment variables to the correct values for your JDK, you must also modify the POM file.
To configure your POM file, so that it accepts the Java language features introduced in JDK 1.7, add the following maven-compiler-plugin plug-in settings to your POM (if they are not already present):
<project ... >
...
<build>
<defaultGoal>install</defaultGoal>
<plugins>
...
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin>
</plugins>
</build>
...
</project>
3.3. Packaging a Web Service in a Bundle Copy linkLink copied to clipboard!
3.3.1. Overview Copy linkLink copied to clipboard!
This section explains how to modify an existing Maven project for a Apache CXF application, so that the project generates an OSGi bundle suitable for deployment in the Red Hat JBoss Fuse OSGi container. To convert the Maven project, you need to modify the project’s POM file and the project’s Blueprint file(s) (located in META-INF/spring).
3.3.2. Modifying the POM file to generate a bundle Copy linkLink copied to clipboard!
To configure a Maven POM file to generate a bundle, there are essentially two changes you need to make: change the POM’s package type to bundle; and add the Maven bundle plug-in to your POM. For details, see Section 3.1, “Generating a Bundle Project”.
3.3.3. Mandatory import packages Copy linkLink copied to clipboard!
In order for your application to use the Apache CXF components, you need to import their packages into the application’s bundle. Because of the complex nature of the dependencies in Apache CXF, you cannot rely on the Maven bundle plug-in, or the bnd tool, to automatically determine the needed imports. You will need to explicitly declare them.
You need to import the following packages into your bundle:
javax.jws
javax.wsdl
javax.xml.bind
javax.xml.bind.annotation
javax.xml.namespace
javax.xml.ws
org.apache.cxf.bus
org.apache.cxf.bus.spring
org.apache.cxf.bus.resource
org.apache.cxf.configuration.spring
org.apache.cxf.resource
org.apache.cxf.jaxws
org.springframework.beans.factory.config
3.3.4. Sample Maven bundle plug-in instructions Copy linkLink copied to clipboard!
Example 3.1, “Configuration of Mandatory Import Packages” shows how to configure the Maven bundle plug-in in your POM to import the mandatory packages. The mandatory import packages appear as a comma-separated list inside the Import-Package element. Note the appearance of the wildcard, *, as the last element of the list. The wildcard ensures that the Java source files from the current bundle are scanned to discover what additional packages need to be imported.
Example 3.1. Configuration of Mandatory Import Packages
<project ... >
...
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
...
<Import-Package>
javax.jws,
javax.wsdl,
javax.xml.bind,
javax.xml.bind.annotation,
javax.xml.namespace,
javax.xml.ws,
org.apache.cxf.bus,
org.apache.cxf.bus.spring,
org.apache.cxf.bus.resource,
org.apache.cxf.configuration.spring,
org.apache.cxf.resource,
org.apache.cxf.jaxws,
org.springframework.beans.factory.config,
*
</Import-Package>
...
</instructions>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
3.3.5. Add a code generation plug-in Copy linkLink copied to clipboard!
A Web services project typically requires code to be generated. Apache CXF provides two Maven plug-ins for the JAX-WS front-end, which enable tyou to integrate the code generation step into your build. The choice of plug-in depends on whether you develop your service using the Java-first approach or the WSDL-first approach, as follows:
-
Java-first approach—use the
cxf-java2ws-pluginplug-in. -
WSDL-first approach—use the
cxf-codegen-pluginplug-in.
3.3.6. OSGi configuration properties Copy linkLink copied to clipboard!
The OSGi Configuration Admin service defines a mechanism for passing configuration settings to an OSGi bundle. You do not have to use this service for configuration, but it is typically the most convenient way of configuring bundle applications. Both Spring DM and Blueprint provide support for OSGi configuration, enabling you to substitute variables in a Blueprint file using values obtained from the OSGi Configuration Admin service.
For details of how to use OSGi configuration properties, see Chapter 4, Configuring the Bundle Plug-In and Section 8.6, “Add OSGi configurations to the feature”.