A Target Platform based on Apache Felix

This article deals with the creation of a target platform based on Apache Felix.
Apache Felix is a runtime platform for OSGi. And a target platform is the set of bundles your OSGi projects will be compiled against. This notion of target platform is part of the Plugin Development Environment (PDE), the Eclipse tooling for OSGi.

Roughly, this article explains how to setup your Eclipse environment to make sure your OSGi plugins will be deployable on a Felix-based install.

Set it up manually

The first solution is to define the target plaftorm manually, with local files. It is the fastest solution.

  • Download http://felix.apache.org/ and unzip it somewhere on your local disk.
  • Start your Eclipse and go in Window > Preferences. Select Plug-in Development > Target Platform.
  • Click Add… and start with an empty target (nothing). Click Next.
  • In the locations tab, click Add…, select Directory, click Next and select the bin directory of your Felix install.
  • Repeat this last step and add the Felix bundle directory to your target platform.

Click OK and activate this target platform in the Eclipse preferences.
That’s it, you have your target platform.

All of this is good… except that it only works with the PDE.
If you want to build your OSGi projects with Tycho (*), this target platform will not be usable. Indeed, Tycho only supports p2 repositories referenced with an URL. Local artifacts can only be referenced by an URL. Which is great when you work alone, but not when you need to share your work. Or when you need continuous integration somewhere else than on your laptop.

(*) As a reminder, Tycho is a plug-in for Maven 3 that allows to build Eclipse plug-ins, and more generally, OSGi bundles. Its main focus is to search bundle dependencies from the manifests rather than from the POM files. Unlike the maven-bundle-plugin, Tycho prefers a manifest-first approach. The bundle search can be performed in Maven and p2 repositories.

Build a Felix target platform for Tycho

To create a Felix based platform that works with Tycho, we need to create a p2 repository that embeds Felix plus all our dependencies. Once we have it, all we will have to do will be to publish it on a web server. Thus, our target platform will reference a remote p2 repository and it will work with both PDE and Tycho.

First, we need to create a feature (as defined by Eclipse).
This will be our root feature. Create a Feature project in Eclipse (File > New… > Plug-in Development > Feature Project). Once it is done, we will add a POM file. This POM will be used by Tycho. And it will rely on a specific feature: Tycho can search dependencies in both p2 repositories, and in Maven repositories. But you cannot mix manifest and POM dependencies. Either all your dependencies are in the manifest, or they are all in the POM. No mix. And this choice is maintained during all the Maven life cycle (the reactor). I will get back to this later. The only thing you need to focus on right now, is to add the OSGi dependencies in the POM.xml. And we will later indicate to Tycho that it must consider POM files.

Here is a sample POM you can reuse.

<project
		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" 
		xmlns="http://maven.apache.org/POM/4.0.0" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>net.vzurczak.sample.platform</groupId>
		<artifactId>apps-target</artifactId>
		<version>1.0.0-SNAPSHOT</version>
		<relativePath>../pom.xml</relativePath>
	</parent>
	
	<groupId>net.vzurczak.sample.platform</groupId>
	<artifactId>net.vzurczak.sample.platform.feature</artifactId> 
	<version>1.0.0-SNAPSHOT</version>
	<name>Platform Root Feature</name>
	<packaging>eclipse-feature</packaging>
	
	<dependencies>
		<dependency>
			<groupId>org.apache.felix</groupId>
			<artifactId>org.apache.felix.http.jetty</artifactId>
			<version>2.2.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.felix</groupId>
			<artifactId>org.apache.felix.configadmin</artifactId>
			<version>1.6.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.felix</groupId>
			<artifactId>org.apache.felix.main</artifactId>
			<version>4.0.3</version>
		</dependency>
		
		<!-- Add all the other bundles you want to be in your target platform -->
	</dependencies>
</project>

Update the feature.xml file in consequence: 1 POM dependency = 1 plugin.

<?xml version="1.0" encoding="UTF-8"?>
<feature
      id="net.vzurczak.sample.platform.feature"
      label="Platform Feature"
      version="1.0.0.qualifier"
      provider-name="VZ">

   <description url="http://www.example.com/description">
      [Enter Feature Description here.]
   </description>

   <copyright url="http://www.example.com/copyright">
      [Enter Copyright Description here.]
   </copyright>

   <license url="http://www.example.com/license">
      [Enter License Description here.]
   </license>

   <plugin
         id="org.apache.felix.configadmin"
         download-size="0"
         install-size="0"
         version="0.0.0"
         unpack="false"/>

   <plugin
         id="org.apache.felix.http.jetty"
         download-size="0"
         install-size="0"
         version="0.0.0"
         unpack="false"/>

   <plugin
         id="org.apache.felix.main"
         download-size="0"
         install-size="0"
         version="0.0.0"
         unpack="false"/>

</feature>

So far, so good. Nothing unusual.
Now, we are going to create a project for the p2 repository.

Create an empty Eclipse project.
Then, create a category definition (File > New… > Plug-in Development > Category Definition). Save it in the project you created before. Open this new file, add a category and insert the feature you created previously. Your file should look like…

<?xml version="1.0" encoding="UTF-8"?>
<site>
   <feature url="features/net.vzurczak.sample.platform.feature_1.0.0.qualifier.jar" id="net.vzurczak.sample.platform.feature" version="1.0.0.qualifier">
      <category name="My Felix Platform"/>
   </feature>
   <category-def name="My Felix Platform" label="My Felix Platform">
      <description>
         A p2 repository with the required bundles to develop and compile against Felix.
      </description>
   </category-def>
</site>

Add a POM file (the usual one for Tycho), except that you must put a dependency to your feature in the POM.

<project 
		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" 
		xmlns="http://maven.apache.org/POM/4.0.0" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
		
	<modelVersion>4.0.0</modelVersion> 
	<parent>
		<groupId>net.vzurczak.sample.platform</groupId>
		<artifactId>apps-target</artifactId>
		<version>1.0.0-SNAPSHOT</version>
		<relativePath>../pom.xml</relativePath>
	</parent>
	
	<groupId>net.vzurczak.sample.platform</groupId>
	<artifactId>net.vzurczak.sample.platform.repository</artifactId> 
	<name>Platform Repository</name>
	<version>1.0.0</version>
	<packaging>eclipse-repository</packaging>
	
	<dependencies>
		<dependency>
			<groupId>net.vzurczak.sample.platform</groupId>
			<artifactId>net.vzurczak.sample.platform.feature</artifactId> 
			<version>1.0.0-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>

For the moment, you have two Maven projects.
The glue between them will come from a parent POM. It will contain all the magic.

<project
		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" 
		xmlns="http://maven.apache.org/POM/4.0.0" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	
	<modelVersion>4.0.0</modelVersion> 
	<groupId>net.vzurczak.sample.platform</groupId>
	<artifactId>apps-target</artifactId>
	<name>Apps Target</name>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>pom</packaging>
	
	<modules>
		<module>net.vzurczak.sample.platform.feature</module>
		<module>net.vzurczak.sample.platform.repository</module>
	</modules>

	<properties>
		<tycho-version>0.16.0</tycho-version>
	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.eclipse.tycho</groupId>
				<artifactId>tycho-packaging-plugin</artifactId>
				<version>${tycho-version}</version>
			</plugin>

			<plugin>
				<groupId>org.eclipse.tycho</groupId>
				<artifactId>tycho-maven-plugin</artifactId>
				<version>${tycho-version}</version>
				<extensions>true</extensions>
			</plugin>

			<plugin>
				<groupId>org.eclipse.tycho</groupId>
				<artifactId>tycho-source-plugin</artifactId>
				<version>${tycho-version}</version>
				<executions>
					<execution>
						<id>attach-source</id>
						<phase>process-classes</phase>
						<goals>
							<goal>plugin-source</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.eclipse.tycho</groupId>
				<artifactId>target-platform-configuration</artifactId>
				<version>${tycho-version}</version>
				<configuration>
					<resolver>p2</resolver>
					<ignoreTychoRepositories>true</ignoreTychoRepositories>
					<pomDependencies>consider</pomDependencies>
				</configuration>
			</plugin>
		</plugins>
	</build>
	
	<!-- If you need to specify repositories -->
	<!--
	<repositories>
		<repository>
			<id>osgi-jaxrs-connector-repo</id>
			<url>http://hstaudacher.github.com/osgi-jax-rs-connector/</url>
			<layout>p2</layout>
		</repository>
	</repositories>
	-->
</project>

The most important thing in this POM is that we force Tycho to consider POM dependencies. It means we will allow to search dependencies declared in the POM, not only in p2 repositories, but also in Maven repositories. As a parent POM, we list the child modules: the feature and the category definition, which will result in a p2 repository with all our Felix bundles. Such a project can be built continuously. The build infrastructure, Hudson, Jenkins, Bamboo, whatever… should then be configured to upload the build output on a web server. You can then create a target platform that points directly to this p2 repository.

I have shared the complete sample on GitHub.

This is how you can share with all your team a target platform that is based on Felix and which work with both the PDE and Tycho. In fact, this works with Felix but with any other bundle requirements. You can add extra bundles in the root feature, or add several features in your p2 repo.

One constraint, though, is that the p2 repo should be considered as a distinct “build”.
Remember what I said about the reactor. The reactor could be described as some kind of context in a Maven build. Considering POM dependencies with Tycho affects the whole reactor. It means that all the projects which are built in the same reactor will inherit this property. It cannot be changed by a child module. Building your p2 repository with your OSGi projects may result in “interferences”. Just avoid it. Two distinct things, two distinct builds.

Conclusion

You may think… Cool, I can now use Tycho with Felix.
The answer is yes… and no. Compilation will work. Debug too, thanks to the PDE. Tests will not.

Testing OSGi bundles with Tycho relies on a plug-in called Tycho-surefire-plugin. And unfortunately, this plug-in and p2 depend on Equinox bundles. Not packages. Bundles. Until these ties are removed, testing bundles on Felix will not be possible with Tycho. More information can be found about it on Eclipse’s wiki.

If you look at Eclipse sources, you will also see that there is a predefined target platform for Felix. But I did not understood in which way it was better that a tailored target platform.

So, how can you do about handling tests with Felix and Tycho? I did not find it myself.
Instead, I dropped Tycho and went back with the Maven bundle plugin for packaging, and I use PAX for testing. Too bad, I really like the way Tycho handles the build. POM files are so clean when using Equinox. I would have enjoyed to have the same thing with Felix…

Notice I also found a set of Eclipse plug-ins that configure your environement for Felix.
The project is called felix-eclipse and is available in open source at http://code.google.com/p/felix-eclipse. I mention it here because this can be a good addition to the PDE when developing for Felix.


About this entry