Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

This article describes the process of converting a Java library delivered as JAR files to Eclipse plug-ins (OSGi bundles) and p2 update sites.

1. JAR files without OSGi meta-data

If a JAR file does not contain the OSGi meta-data in the META-INF/MANIFEST.MF file, it cannot be directly consumed by other Eclipse plug-ins.

If you want to use such standard Java libraries in other Eclipse plug-ins you have to convert them also into a plug-in. After the conversion the resulting JAR file can still be used in a non OSGi runtime, e.g., a Java webserver. The Java runtime ignores the additional OSGi meta-data.

Eclipse provides a wizard to convert a JAR file with OSGi meta-data to a plug-in. The usage of this wizard is demonstrated in Creating a plug-in project for your jar.

If you repackage a JAR into a plug-in it is wise to check if the license allows this. You should also try to contact the author of the software and ask if he can integrate the OSGi meta-data directly in his library.

2. Orbit receipts

The Orbit project hosts the Orbit receipts project which allows to convert JARs from Maven to OSGi bundles. Clone the Git repo from the following URL Orbit Git repos (https://git.eclipse.org/r/orbit/orbit-recipes). Afterwards see the README.md for how to use it. Also see https://github.com/eclipse/ebr for a description of the Eclipse Bundle Recipes project.

3. Integrating external jars / third party libraries

The following gives an example how to convert a standard Java JAR to an Eclipse plug-in via the user interface.

3.1. Creating a plug-in project for your jar

Create a new plug-in project by selecting File ▸ New ▸ Project ▸ Plug-in Development ▸ Plug-in from Existing JAR Archives.

externaljars20

Add the JAR files you want to have in this new plug-in. Press next.

externaljars25

Enter a name and a version for your new plug-in. Uncheck the Unzip the JAR archive into the project flag. Unchecking this flag prevents that the class files are extracted from the JAR file which is not necessary to use them.

Afterwards press the Finish button in the wizard.

externaljars30

You have created a new plug-in for the selected JAR files. Open the MANIFEST.MF file and validate that all required packages are exported on the Runtime tab. All the packages from your JAR files should be included in the exported packages. Otherwise OSGi prevents other plug-ins from accessing them.

3.2. Using the new plug-in project

In the plug-in project which should access the library, open the MANIFEST.MF file and select the Dependencies tab. Add the new plug-in as dependency.

externaljars40

4. Convert JAR files to OSGi bundles with Gradle

The Gradle build system can also be used to convert JARs to OSGi bundles. Therefore the usage of the bnd-platform Gradle plug-in is necessary.

It can be added to a build.gradle file like this:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.standardout:bnd-platform:1.5.0'
    }
}

apply plugin: 'org.standardout.bnd-platform'

This plug-in adds a platform closure, which can be used to configure an update site and the bundles, which should be part of the update site.

A complete example to create a p2 update site for retrofit 2.1.0 with a retrofit Gson converter could look like this:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.standardout:bnd-platform:1.5.0'
    }
}

apply plugin: 'org.standardout.bnd-platform'

repositories {
    jcenter()
}

platform {

    // Add proper path to your eclipse installation (necessary for building a p2 updatesite)
    eclipseHome = new File('/home/simon/eclipse/eclipse-baseline')

    // configure proper names for the p2 update site
    categoryId = 'retrofit'
    categoryName = 'retrofit'

    featureId = 'retrofit'
    featureName = 'retrofit osgi'
    featureVersion = '2.1.0'
    featureProvider = 'Simon Scholz'

    defaultQualifier = ''
    useBndHashQualifiers = false
    useFeatureHashQualifiers = false
    defaultQualifierMap.prefix = ''

    // Convert the retrofit artifact to OSGi, make android.os optional
    bundle('com.squareup.retrofit2:retrofit:2.1.0'){
        bnd {
            optionalImport 'android.os'
            optionalImport 'android.net'
        }
    }

    // Convert the retrofit gson converter artifact to OSGi
    bundle('com.squareup.retrofit2:converter-gson:2.1.0')

    // You can add other converters similar to the gson converter above...
}

It is highly recommended to specify a proper path to an existing Eclipse installation by using the eclipseHome in the platform closure, because without it the bnd-platform plug-in will download an Eclipse SDK in order to be able to create a p2 update site.

In order to create bundles/plug-ins from the listed dependencies the bundles tasks is supposed to be used. If the creation of a p2 update site is desired the updateSite or the updateSiteZip tasks can be used.

When running a build all dependencies and all its transitive dependencies will be downloaded automatically and can be found in the plugins folder.

The whole sample code including a sample RCP application using retrofit can be found here: https://github.com/SimonScholz/retrofit-osgi

For more details and advanced settings (like combining/merging plug-ins with split packages) see https://github.com/stempler/bnd-platform/.

5. Exercise - Convert JAR files to OSGi bundles with Gradle

5.1. Target

In this exercise a p2 update site for the retrofit library, including its' Gson converter, will be created.

Retrofit is a library for making REST calls fairly easy, including the serialization etc.

5.2. Installing Gradle

For this exercise the Gradle build tool is required.

How to install Gradle can be found here: Gradle tutorial

5.3. The build.gradle file

Create a folder called retrofit-osgi on your maschine. In this folder a build.gradle file has to be created.

mkdir retrofit-osgi
touch build.gradle

Alternatively a new general project in the Eclipse workspace called retrofit-osgi could be created, which contains a build.gradle file.

The build.gradle file should have the following contents:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.standardout:bnd-platform:1.5.0'
    }
}

apply plugin: 'org.standardout.bnd-platform'

repositories {
    jcenter()
}

platform {

    // Add proper path to your eclipse installation (necessary for building a p2 updatesite)
    eclipseHome = new File('/home/simon/eclipse/eclipse-baseline')

    // configure proper names for the p2 update site
    categoryId = 'retrofit'
    categoryName = 'retrofit'

    featureId = 'retrofit'
    featureName = 'retrofit osgi'
    featureVersion = '2.1.0'
    featureProvider = 'Simon Scholz'

    defaultQualifier = ''
    useBndHashQualifiers = false
    useFeatureHashQualifiers = false
    defaultQualifierMap.prefix = ''

    // Convert the retrofit artifact to OSGi, make android.os optional
    bundle('com.squareup.retrofit2:retrofit:2.1.0'){
        bnd {
            optionalImport 'android.os'
            optionalImport 'android.net'
        }
    }

    // Convert the retrofit gson converter artifact to OSGi
    bundle('com.squareup.retrofit2:converter-gson:2.1.0')

    // You can add other converters similar to the gson converter above...
}

Go to the retrofit-osgi folder and run the updateSite task.

cd retrofit-osgi

gradle clean uS
update site task terminal

5.4. Validate

Try to use the update site in your running Eclipse IDE, but do not install it.

install retrofit osgi

The whole solution for this exercise plus a sample RCP application using the retrofit library can be found here: https://github.com/SimonScholz/retrofit-osgi

6. Convert JAR files to OSGi bundles with the p2-maven-plugin

The p2-maven-plugin can be used to generate OSGi bundles out of JARs and to create a p2 update site, which contains the converted OSGi JARs.

With the following build file slf4j-log4j12 in version 1.7.10 and all of its dependencies are be converted to OSGi bundles. Also, a p2 update site is created.

<project>
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.vogella.maven.osgi</groupId>
 <artifactId>com.vogella.maven.osgi.convert</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>pom</packaging>

 <build>
  <plugins>
   <plugin>
    <groupId>org.reficio</groupId>
    <artifactId>p2-maven-plugin</artifactId>
    <version>1.1.2-SNAPSHOT</version>
    <executions>
     <execution>
      <id>default-cli</id>
      <configuration>
       <artifacts>
        <!-- specify your depencies here -->
        <!-- groupId:artifactId:version -->
        <artifact>
         <id>org.slf4j:slf4j-log4j12:1.7.10</id>
        </artifact>
       </artifacts>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>

 <pluginRepositories>
  <pluginRepository>
   <id>reficio</id>
   <url>http://repo.reficio.org/maven/</url>
  </pluginRepository>
 </pluginRepositories>

</project>

By using the mvn clean p2:site goal the following directory structure is created.

p2 maven plugin

Here you can see that also log4j_1.2.17 and slf4j.api_1.7.10 are converted. They can be used via the generated update site.

p2 maven plugin updatesite

In this case the p2 repository targets the file system. But of curse you can also embed the conversion into a deployment build.

In the following sample the p2-maven-plugin is added to the package phase and the site goal is executed. Then the p2 updatesite is archived to one zip file, which is then uploaded to a repository manager.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.vogella.p2</groupId>
 <artifactId>com.vogella.p2</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>pom</packaging>

 <properties>
  <tycho.version>0.23.0</tycho.version>
 </properties>

 <distributionManagement>
  <repository>
   <id>deployment</id>
   <name>Internal Releases</name>
   <url>http://localhost:8081/nexus/content/repositories/releases/</url>
  </repository>
  <snapshotRepository>
   <id>deployment</id>
   <name>Internal Releases</name>
   <url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
  </snapshotRepository>
 </distributionManagement>

 <build>
  <plugins>
   <!-- create p2 updatesite with specified dependencies -->
   <plugin>
    <groupId>org.reficio</groupId>
    <artifactId>p2-maven-plugin</artifactId>
    <version>1.1.2-SNAPSHOT</version>
    <executions>
     <execution>
      <phase>package</phase>
      <id>default-cli</id>
      <goals>
       <goal>site</goal>
      </goals>
      <configuration>
       <artifacts>
        <!-- specify your depencies here -->
        <!-- groupId:artifactId:version -->
        <artifact>
         <id>org.slf4j:slf4j-log4j12:1.7.10</id>
        </artifact>
       </artifacts>
      </configuration>
     </execution>
    </executions>
   </plugin>
   <!-- Zip the P2 repository -->
   <plugin>
    <groupId>org.eclipse.tycho</groupId>
    <artifactId>tycho-p2-repository-plugin</artifactId>
    <version>${tycho.version}</version>
    <executions>
     <execution>
      <phase>package</phase>
      <goals>
       <goal>archive-repository</goal>
      </goals>
     </execution>
    </executions>
   </plugin>

   <!-- Attach zipped P2 repository to be installed and deployed in the Maven
    repository during the deploy phase. -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.8</version>
    <executions>
     <execution>
      <goals>
       <goal>attach-artifact</goal>
      </goals>
      <configuration>
       <artifacts>
        <artifact>
         <file>target/${project.artifactId}-${project.version}.zip</file>
         <type>zip</type>
        </artifact>
       </artifacts>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>

 <pluginRepositories>
  <pluginRepository>
   <id>reficio</id>
   <url>http://repo.reficio.org/maven/</url>
  </pluginRepository>
 </pluginRepositories>

</project>

If you are using an artifact manager like Nexus, you can mvn clean deploy and the zip file is deployed to it.

In order to use this p2 update site inside this zip file you can create a virtual repository on Nexus and use the Tycho/Nexus Unzip Plugin.

See Tycho/Nexus Unzip plugin for more information.

See http://projects.reficio.org/p2-maven-plugin for more information on the usage of the p2-maven-plugin.

7. Exercise - Convert JAR files to OSGi bundles with the p2-maven-plugin

7.1. Target

In this exercise a p2 update site for the RxJava 2.0 library will be created.

RxJava is a library for reactive programming in Java. See RxJava tutorial for more information on RxJava.

7.2. Creating a p2 maven project

Create a folder called p2-maven on your maschine. In this folder a pom.xml file has to be created.

mkdir p2-maven
touch pom.xml

Alternatively a new general project in the Eclipse workspace called p2-maven could be created, which contains a pom.xml file.

The pom.xml file should have the following contents:

<project>
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.vogella.maven.osgi</groupId>
 <artifactId>com.vogella.maven.osgi.convert</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>pom</packaging>

 <build>
  <plugins>
   <plugin>
    <groupId>org.reficio</groupId>
    <artifactId>p2-maven-plugin</artifactId>
    <version>1.1.2-SNAPSHOT</version>
    <executions>
     <execution>
      <id>default-cli</id>
      <configuration>
       <artifacts>
        <!-- specify your depencies here -->
        <!-- groupId:artifactId:version -->
        <artifact>
         <id>io.reactivex.rxjava2:rxjava:2.0.3</id>
        </artifact>
       </artifacts>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>

 <pluginRepositories>
  <pluginRepository>
   <id>reficio</id>
   <url>http://repo.reficio.org/maven/</url>
  </pluginRepository>
 </pluginRepositories>

</project>

Go to the p2-maven folder and run the p2:site goal.

cd p2-maven

maven clean p2:site

7.3. Validate

Try to use the update site in your running Eclipse IDE, but do not install it.

p2 maven plugin rxjava

8. About this website

Retrofit Gradle Conversion Example - https://github.com/SimonScholz/retrofit-osgi

9.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2017 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.