The Maven Cookbook

1.9. Transforming a Maven Repository into an OSGi Bundle Repository

1.9. Transforming a Maven Repository into an OSGi Bundle Repository

In the previous recipe, you published an OSGi bundle to a Maven repository, and you relied on the Pax plugin to read and write the repository.xml file. While this approximates an OBR repository, you'd like Nexus to take care of generating the OBR metadata from the repository contents, and you don't want to rely on individual builds to lock, read, parse, alter, write, and unlock a shared OBR metadata file. Instead of relying on the Pax plugin, this recipe shows you how to configure an OBR repository in Nexus Professional.

1.9.1. Task

You need to expose OSGi bundles in a Maven repository using the OBR repository format.

1.9.2. Action

Use Nexus Professional, and create a virtual OBR repository which will scan a Maven repository for OSGi bundle artifacts and generate the OBR XML metadata in response to a change in the Maven repository. Building upon the example from the previous recipe, create a Virtual OBR repository named Snapshots OBR which uses the Snapshots repository as a source. To do this:

  1. Load the Nexus interface in a web browser by opening the URL http://localhost:8081/nexus.

  2. Login as an administrative user using the default credentials of admin/admin123 (if you haven't already changed the default password).

  3. Click on Repositories in the left navigation menu.

  4. Click on the Add.. button above the list of Nexus repositories and groups.

  5. Select "Virtual Repository" from the resulting dropdown.

  6. In the New Virtual Repository window, supply the following values as shown in Figure 1.7, “Creating a New Virtual OBR Repository”:

    1. Repository ID: snapshots-obr

    2. Repository Name: Snapshots OBR

    3. Provider: OBR

    4. Source Nexus Repository ID: snapshots

    5. Synchronize on Startup: False

  7. Click the Save button to create the new Virtual repository.

Creating a New Virtual OBR Repository

Figure 1.7. Creating a New Virtual OBR Repository


1.9.3. Detail

To verify that our new Virtual OBR repository is generating the the appropriate XML based on the contents of the Maven repository, click on Repositories in the left navigation menu, and then select "Snapshots OBR" from the list of repositories. If you look at the Browse tab for this repository and drill into the .meta/ directory, you can then right-click on the obr.xml file and select Download from the context menu. This should load the repository XML in a browser, and the contents of this XML file should resemble the XML file in Example 1.7, “Metadata for the Snapshots OBR Virtual Repository”. The URL for this new repository XML should be http://localhost:8081/nexus/content/repositories/snapshots-obr/.meta/obr.xml.

Example 1.7. Metadata for the Snapshots OBR Virtual Repository

<repository name='Snapshots OBR' lastmodified='1247630990695'>
<resource id='org.sonatype.mcookbook/1.0.0.SNAPSHOT' presentationname='org.sonatype.mcookbook' 
          symbolicname='org.sonatype.mcookbook' 
          uri='../org/sonatype/mcookbook/osgi-project/org.sonatype.mcookbook/1.0-SNAPSHOT/\
               org.sonatype.mcookbook-1.0-20090715.030813-1.jar' version='1.0.0.SNAPSHOT'>
  <description>
    Generated using Pax-Construct
  </description>
  <size>
    5345
  </size>
  <capability name='bundle'>
    <p n='manifestversion' v='2'/>

    <p n='presentationname' v='org.sonatype.mcookbook'/>
    <p n='symbolicname' v='org.sonatype.mcookbook'/>
    <p n='version' t='version' v='1.0.0.SNAPSHOT'/>
  </capability>
  <capability name='package'>
    <p n='package' v='org.sonatype.mcookbook'/>
    <p n='version' t='version' v='1.0.0.SNAPSHOT'/>
  </capability>
  <require extend='false' filter='(&amp;(package=org.osgi.framework)(version&gt;=0.0.0))' multiple='false' 
           name='package' optional='false'>

    Import package org.osgi.framework
  </require>
  <require extend='false' filter='(&amp;(package=org.sonatype.mcookbook)(version&gt;=1.0.0.SNAPSHOT))' 
           multiple='false' name='package' optional='false'>
    Import package org.sonatype.mcookbook ;version=1.0.0.SNAPSHOT
  </require>
</resource>
<resource id='org.sonatype.mcookbook/1.0.0.SNAPSHOT' presentationname='org.sonatype.mcookbook' 
          symbolicname='org.sonatype.mcookbook' 
          uri='../org/sonatype/mcookbook/osgi-project/org.sonatype.mcookbook/1.0-SNAPSHOT/\
               org.sonatype.mcookbook-1.0-20090715.030835-2.jar' version='1.0.0.SNAPSHOT'>
  <description>
    Generated using Pax-Construct
  </description>
  <size>

    5346
  </size>
  <capability name='bundle'>
    <p n='manifestversion' v='2'/>
    <p n='presentationname' v='org.sonatype.mcookbook'/>
    <p n='symbolicname' v='org.sonatype.mcookbook'/>
    <p n='version' t='version' v='1.0.0.SNAPSHOT'/>
  </capability>
  <capability name='package'>

    <p n='package' v='org.sonatype.mcookbook'/>
    <p n='version' t='version' v='1.0.0.SNAPSHOT'/>
  </capability>
  <require extend='false' filter='(&amp;(package=org.osgi.framework)(version&gt;=0.0.0))' multiple='false' 
           name='package' optional='false'>
    Import package org.osgi.framework
  </require>
  <require extend='false' filter='(&amp;(package=org.sonatype.mcookbook)(version&gt;=1.0.0.SNAPSHOT))' 
           multiple='false' name='package' optional='false'>
    Import package org.sonatype.mcookbook ;version=1.0.0.SNAPSHOT
  </require>
</resource>

</repository>

If you want to test how easy it would be to install this component directly from this new Nexus virtual OBR directory. If you've already installed Felix, from the previous recipe, delete the felix-1.8.0 directory and recreate the entire environment to take note of any changes in the behavior of Felix when using the new Snapshots OBR virtual repository:

  1. Download Apache Felix from http://www.apache.org/dist/felix/felix-1.8.0.tar.gz.

  2. Unpack the Felix distribution on your local workstation.

  3. Change directory to the Felix directory.

  4. Start Apache Felix with java -jar ./bin/felix.jar

  5. Add the Snapshots repository as an OBR repository by copying the URL to the repository.xml and passing it to the obr command: obr add-url http://localhost:8081/nexus/content/repositories/snapshots-obr/.meta/obr.xml

  6. List the contents of the OBR repository.

  7. Deploy the org.sonatype.mcookbook bundle.

  8. List the installed bundles.

These commands are captured in the following screen listing:

~/programs $ wget http://www.apache.org/dist/felix/felix-1.8.0.tar.gz
--2009-07-14 22:46:19--  http://www.apache.org/dist/felix/felix-1.8.0.tar.gz
Resolving www.apache.org... 140.211.11.130
Connecting to www.apache.org|140.211.11.130|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 901620 (880K) [application/x-gzip]
Saving to: `felix-1.8.0.tar.gz'
2009-07-14 22:46:20 (924 KB/s) - `felix-1.8.0.tar.gz' saved [901620/901620]

~/programs $ tar xvzf felix-1.8.0.tar.gz 
felix-1.8.0/
felix-1.8.0/bin/
felix-1.8.0/bin/felix.jar
...
felix-1.8.0/NOTICE
~/programs $ cd felix-1.8.0
~/programs/felix-1.8.0 $ java -jar ./bin/felix.jar 

Welcome to Felix.
=================

-> obr add-url http://localhost:8081/nexus/content/repositories/snapshots-obr/.meta/obr.xml
-> obr list
org.sonatype.mcookbook (1.0.0.SNAPSHOT, ...)
-> obr deploy org.sonatype.mcookbook
Target resource(s):
-------------------
   org.sonatype.mcookbook (1.0.0.SNAPSHOT)

Deploying...done.
-> ps 
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (1.8.0)
[   1] [Active     ] [    1] Apache Felix Shell Service (1.2.0)
[   2] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)
[   3] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)
[   4] [Installed  ] [    1] org.sonatype.mcookbook (1.0.0.SNAPSHOT)
-> start 4
STARTING org.sonatype.mcookbook
REGISTER org.sonatype.mcookbook.ExampleService
-> 

Aside from the output of the obr list command, this process was exactly the same as the previous recipe. The main difference between this recipe and the previous recipe is that we do not rely on the Pax Plugin to generate the repository XML file that makes the repository an OBR repository. Instead, we rely upon the OBR integration of Nexus Professional. Every time the underlying source repository (in this case the hosted snapshots repository) is changed, Nexus Professional will regenerate the OBR XML in this virtual OBR repository. Using this virtual repository, you can simply deploy your project's OSGi and non-OSGi artifacts to the same Maven repository and then you can expose OSGi bundles to systems such as Felix using Nexus Professional's support for virtual OBR repositories.

If you are using Nexus Professional's OBR support and exposing a Maven repository as an OBR repository using a virtual repository, there is no need for you to pass the -DremoteOBR option to mvn deploy as we did in the previous recipe.