Launching an OSGi app on the command line

I am a total beginner on this topic, but here is what I have found so far. Please correct me, advise me etc. in the comments.

A colleague has written a program based on OSGi, which is a framework for obfuscating everything “modular” software, which I think means loading code at runtime, even if it requires a different classloader, and even if it depends on other things which also need loading at runtime. I may be wrong though.

Anyway, all I want to do is run it (on windows only, for now).

OSGi is quite closely linked to the Eclipse development environment – Eclipse uses OSGi to manage its plugins, which are an infinitely complex web of incompatible interdependencies.

My colleague showed me how to set up their Eclipse environment, and how to run the program from within Eclipse using an OSGi launch configuration. I also managed to build the JAR files of the program itself.

What I wanted to do was run it outside Eclipse, on the command line (and eventually in an Ant build).

I found it almost impossible to understand anything others have written about OSGi, but somehow I muddled my way through to being able to do it.

Here’s how I managed it.

Find out the dependencies

If you have an Eclipse launch configuration that successfully runs your program inside Eclipse, you can find out all the OSGi bundles (which are JAR files containing extra config) that it needs. Go to the Run menu and click Run Configurations. Find the relevant run configuration, which will be inside the OSGi Framework tree item on the left. Click on it, and choose the Bundles tab. The tree view will show you all the bundles needed to run this program. If you check “Only show selected” you can see only the ones you need.

If you want a text version of this list, look for a file here:

WORKSPACE/.metadata/.plugins/org.eclipse.pde.core/LAUNCHERNAME/org.eclipse.simpleconfigurator/bundles.info

where WORKSPACE is the location of your Eclipse workspace, and LAUNCHERNAME is the name of the run configuration you found in the tree view in the Run Configurations page.

The bundles.info file contains a comma-separated list of bundle name (which is a reversed-url type name, like a package name – don’t confuse it with a package name though), some version information, and the path to the actual JAR file that is this bundle.

We will also need the Equinox OSGi bundles, including the SimpleConfigurator (oh, the irony). I am using these versions – yours might be different:

org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222/*
org.eclipse.equinox.app_1.3.1.R36x_v20100803.jar
org.eclipse.equinox.common_3.6.0.v20100503.jar
org.eclipse.equinox.concurrent_1.0.100.v20100503.jar
org.eclipse.equinox.ds_1.2.1.R36x_v20100803.jar
org.eclipse.equinox.event_1.2.0.v20100503.jar
org.eclipse.equinox.frameworkadmin.equinox_1.0.200.v20100505.jar
org.eclipse.equinox.frameworkadmin_2.0.0.v20100503.jar
org.eclipse.equinox.http.jetty_2.0.0.v20100503.jar
org.eclipse.equinox.http.registry_1.1.1.R36x_v20101103.jar
org.eclipse.equinox.http.servlet_1.1.0.v20100503.jar
org.eclipse.equinox.launcher_1.1.1.R36x_v20101122_1400.jar
org.eclipse.equinox.p2.artifact.repository_1.1.1.R36x_v20100901.jar
org.eclipse.equinox.p2.console_1.0.200.v20100601.jar
org.eclipse.equinox.p2.core_2.0.3.R36x_v20110111.jar
org.eclipse.equinox.p2.director.app_1.0.202.R36x_v20110608.jar
org.eclipse.equinox.p2.directorywatcher_1.0.203.R36x_v20101220.jar
org.eclipse.equinox.p2.director_2.0.4.R36x_v20120223.jar
org.eclipse.equinox.p2.engine_2.0.1.R36x_v20110201.jar
org.eclipse.equinox.p2.extensionlocation_1.2.0.v20100518.jar
org.eclipse.equinox.p2.garbagecollector_1.0.100.v20100503.jar
org.eclipse.equinox.p2.jarprocessor_1.0.200.v20100503a.jar
org.eclipse.equinox.p2.metadata.repository_1.1.1.R36x_v20110302.jar
org.eclipse.equinox.p2.metadata_2.0.1.R36x_v20101202.jar
org.eclipse.equinox.p2.operations_2.0.0.v20100510.jar
org.eclipse.equinox.p2.publisher_1.1.2.v20100824-2220.jar
org.eclipse.equinox.p2.ql_2.0.0.v20100503a.jar
org.eclipse.equinox.p2.reconciler.dropins_1.1.3.R36x_v20111213.jar
org.eclipse.equinox.p2.repository.tools_2.0.1.R36x_v20100823.jar
org.eclipse.equinox.p2.repository_2.0.2.R36x_v20110111-1500.jar
org.eclipse.equinox.p2.touchpoint.eclipse_2.0.4.R36x_v20110908.jar
org.eclipse.equinox.p2.touchpoint.natives_1.0.201.R36x_v20110111.jar
org.eclipse.equinox.p2.ui.sdk.scheduler_1.0.0.v20100507-1815.jar
org.eclipse.equinox.p2.ui.sdk_1.0.100.v20100513.jar
org.eclipse.equinox.p2.ui_2.0.0.v20100518.jar
org.eclipse.equinox.p2.updatechecker_1.1.101.R36x_v20100823.jar
org.eclipse.equinox.p2.updatesite_1.0.201.R36x_v20100823.jar
org.eclipse.equinox.preferences_3.3.1.R36x_v20110302.jar
org.eclipse.equinox.registry_3.5.0.v20100503.jar
org.eclipse.equinox.security.ui_1.0.200.v20100503.jar
org.eclipse.equinox.security.win32.x86_1.0.200.v20100503.jar
org.eclipse.equinox.security_1.0.200.v20100503.jar
org.eclipse.equinox.simpleconfigurator.manipulator_2.0.0.v20100503.jar
org.eclipse.equinox.simpleconfigurator_1.0.200.v20100503.jar
org.eclipse.equinox.util_1.0.200.v20100503.jar
org.eclipse.osgi.services_3.2.100.v20100503.jar
org.eclipse.osgi.util_3.2.100.v20100503.jar
org.eclipse.osgi_3.6.50.R36x_v20120315-1500.jar

(I have no idea whether you need all of these – sorry.)

Make a fake environment

Imagine you have a program that consists of 2 JARs itself, called my_program_main_1.0.jar and my_program_lib_1.1.jar, 2 dependency bundles called com.dep1_3.6v20091112.jar and org.dep2_1.0.jar and a directory containing a dependency bundle called org.foo.dep3_1.4.

Create a directory that will contain your program and its dependencies. Structure it like this:

main_dir/
    my_program/
        my_program_main_1.0.jar
        my_program_lib_1.1.jar
    osgi_install_area/
        plugins/
            com.dep1_3.6v20091112.jar
            org.dep2_1.0.jar
            org.foo.dep3_1.4/
                ... more stuff in here ...
            org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222/
                ... more stuff in here ...
            org.eclipse.equinox.app_1.3.1.R36x_v20100803.jar
            ... lots more here ...
    configuration/
        config.ini
    bundles.info

Copy your program’s JARs into the my_program directory (feel free to give it a different name!).

Copy the Equinox bundles and the other dependencies into the plugins directory. You can find them in the directory listed in the bundles.info file you found in the previous section. The Equinox bundles should be alongside the others (hopefully).

The contents of bundles.info should be something like this:

#version=1
MyProgramMain,1.0,file:../my_program/my_program_main_1.0.jar,4,true
MyProgramLib,1.1,file:../my_program/my_program_lib_1.1.jar,4,true
com.dep1,3.6v20091112,file:./plugins/com.dep1_3.6v20091112.jar,4,true
org.dep2,1.0,file:./plugins/org.dep2_1.0.jar,4,true
org.foo.dep3,1.4,file:./plugins/org.foo.dep3_1.4/,4,true
org.eclipse.equinox.launcher.win32.win32.x86,1.1.2.R36x_v20101222,file:./plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.2.R36x_v20101222/,4,true
org.eclipse.equinox.app,1.3.1.R36x_v20100803,org.eclipse.equinox.app_1.3.1.R36x_v20100803.jar,4,true
... Plus similar lines for all the equinox and OSGi bundles you need ...

Make sure that the version number after the first comma exactly matches the version number encoded in the JAR filename.

The contents of config.ini should be something like this:

osgi.bundles=reference\:file\:C\:/absolute/path/to/main_dir/osgi_install_area/plugins/org.eclipse.equinox.simpleconfigurator_1.0.200.v20100503.jar@1\:start
org.eclipse.update.reconcile=false
osgi.bundles.defaultStartLevel=4
osgi.install.area=file\:C\:/absolute/path/to/main_dir/osgi_install_area
osgi.framework=file\:C\:/absolute/path/to/main_dir/osgi_install_area/plugins/org.eclipse.osgi_3.6.50.R36x_v20120315-1500.jar
org.eclipse.equinox.simpleconfigurator.configUrl=file\:/C\:/absolute/path/to/main_dir/bundles.info
osgi.configuration.cascaded=false

Note that these paths have to be absolute. I plan to write a small ant script to create the config.ini file when needed.

Run the program

Now, to run your program, it’s a simple matter of getting into the right directory:

cd "C:\absolute\path\to\main_dir"

and typing this simple command:

java -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dfile.encoding=Cp1252 -classpath "osgi_install_area\plugins\org.eclipse.equinox.launcher_1.1.1.R36x_v20101122_1400.jar" org.eclipse.equinox.launcher.Main -configuration "file:configuration/" -os win32 -ws win32 -arch x86 -nl en_GB -console ACTUAL_ARGS_TO_PROGRAM

Where ACTUAL_ARGS_TO_PROGRAM is where you type the actual command-line arguments (if any) you want to pass to your program.

Disclaimer

I have no idea what most of this means, and I’ve probably told you a lot of things that are wrong. Please, people who know about this stuff, correct me and I’ll update this post.

This worked for me, but I feel like I must be doing something wrong – can it really be this difficult?

4 thoughts on “Launching an OSGi app on the command line”

  1. You can run an OSGi framework with just “java -jar org.eclipse.osgi_.jar”.

    The problems you have encountered seem related to the vast number of bundles you have added to the framework. You admit yourself that you don’t know what they do, so why are you bothering with them?

  2. Hi Neil, thanks for the information. The bundles were needed by the code I was running, which I didn’t write. The main problem I was having was constructing a directory structure containing all the right stuff in order to be able to run the program, rather than the actual command line needed to run it (although that was a challenge too). I’d appreciate any tips on how to “build” something running inside Eclipse into a “executable” project (i.e. a file or set of files that can be run using the command you gave or a similar one).

  3. Hi there, simple question (hooping you still read this old post)

    Where is the point where you tell which application framwork must run? i suppose is main class in you MyProgramMain.jar ..where ACTUAL_ARGS_TO_PROGRAM goes.

    Becaouse in you command line there is not reference to you MyProgramMain, in bundles.info line with MyProgramMain.jar seems similar to others line and in config.ini i don’t see anything can help.

    I try to replicate but nothing invoke my main class.

  4. Hi Teu, I don’t think OSGi uses Main classes or methods but to be honest I found it totally confusing and am very glad I never have to touch it again. Good luck, and sorry I can’t help!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.