In this section we start by defining a runtime environment. An OSGi runtime environment consists of a classpath, a framework, and a number of configuration properties that properly setup the framework. In contrast with the application server model, the runtime is unique for the application. In this section we show how to create an executable JAR that contains all the dependencies.
Running a framework requires assembling the application. Assembly consists of selecting an appropriate set of bundles and defining the framework’s context.
This requires to select the initial requirements of a runtime and then let bnd resolve this into a set of run bundles. Once we have got this set of run bundles we can export it into an executable JAR or other format.
Make sure you are in the top directory:
$ cd ~/workspaces/osgi.enroute.examples.eval
In the osgi.enroute.examples.eval
directory we create the pom.xml
file in a new
bndrun
directory.
osgi.enroute.examples.eval $ mkdir bndrun
osgi.enroute.examples.eval $ cd bndrun
bndrun $ vi pom.xml
// add the following file
<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>
<parent>
<groupId>org.osgi</groupId>
<artifactId>osgi.enroute.examples.eval</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>osgi.enroute.examples.eval.bndrun</artifactId>
<packaging>jar</packaging>
We will define the OSGi runtime environment in a bndrun
file. This file contains
the myriad of details that is needed to define an OSGi runtime. Details like the
class path, the set of bundles, system properties, framework configuration, etc. We
will use the bnd-export-maven-plugin
. This plugin will take a bndrun file as input
and then generate an executable JAR. This is a JAR that contains all its dependencies.
<build>
<plugins>
<plugin>
We’re using the 3.4.0-SNAPSHOT revision because this tutorial needed a newer feature that missed 3.3
<groupId>biz.aQute.bnd</groupId>
<artifactId>bnd-export-maven-plugin</artifactId>
<version>3.4.0-SNAPSHOT</version>
We need to configure the plugin.
<configuration>
<resolve>true</resolve>
<bndruns>
Here we specify one or more bndrun files. We’ll discuss the format of this file later.
<bndrun>osgi.enroute.examples.eval.bndrun</bndrun>
</bndruns>
<targetDir>.</targetDir>
</configuration>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
We need to add our provider as a runtime dependency:
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.enroute.examples.eval.simple.provider</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
We also need a distro. So far we’ve been compiling against API only with the OSGi enRoute base API. However, we now need to add implementations. Implementations can come from different sources. For example IBM websphere, Karaf, Knopflerfish, Apache Felix, etc. However, the OSGi enRoute project has created a distro that consists of many different open source projects to demonstrate the interoperability of OSGi.
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.enroute.pom.distro</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</project>
We must also add bndrun as module in the parent pom.xml, e.g. after the existing api and simple.provider modules.
The osgi.enroute.examples.eval.bndrun
bndrun file contains a specification of an
OSGi runtime. An OSGi runtime needs quite a bit of information and we collect that
all in this file.
bndrun $ vi osgi.enroute.examples.eval.bndrun
// add the following file
The -standalone
instruction is there to indicate that this does not run in bndtools
but as a stand-alone definition.
-standalone:
We need access to all the dependencies of this project. The bndrun file supports this with the Bnd Pom Repository. We then need to define the list of snapshot URLs and release URLs.
-plugin.examples.eval = \
aQute.bnd.repository.maven.pom.provider.BndPomRepository; \
snapshotUrls=https://oss.sonatype.org/content/repositories/osgi/; \
releaseUrls=https://repo1.maven.org/maven2/; \
pom=${.}/pom.xml; \
name=examples.eval; \
location=${.}/target/cached.xml
In the -runrequires
section we list OSGi requirements that we want our runtime
to have. In the initial case we only need the provider to run. The syntax for
the -runrequires
is the syntax for an OSGi requirement, as used in the
OSGi Require-Capability header. Each clause consists of a namespace and a
filter. The namespace defines a number of properties and the filter is an assertion
on these properties. In this case we use the identity namespace to require a specific
bundle, the provider bundle. The property name is osgi.identity
following the
convention for namespaces and the Bundle Symbolic Name is osgi.enroute.examples.eval.simple.provider
.
-runrequires: \
osgi.identity; \
filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)'
The -runfw
specifies the framework we want to use.
-runfw: org.eclipse.osgi;version='[3.10.100.v20150529-1857,3.10.100.v20150529-1857]'
We can control the logging information during launching. Let’s keep this off for now:
-runtrace: false
In the example we use Equinox and equinox has a number of habits that need to be unlearned. For example, it has a built-in shell but it is better to define the used shell using standard OSGi techniques. These settings will not be further explained here.
#
# OSGi enRoute setting. These settings
# fixup some of the issues around equinox
# defaults.
#
-runee: JavaSE-1.8
-resolve.effective: resolve, active
-runproperties.eqnx: \
osgi.console.enable.builtin=false, \
osgi.console=, \
org.osgi.service.http.port=8080
-runpath.eqnx: osgi.enroute.equinox.log.adapter
-runrequires.eqnx: \
osgi.identity;filter:='(osgi.identity=org.apache.felix.log)'
-runsystempackages.eqnx: javax.script
-runsystemcapabilities.dflt: ${native_capability}
The definition so far cannot be run. We need to resolve the bndrun file. Resolving
will take the -runrequires
and the repository and calculate a closure of bundles.
This closure then is the list of -runbundles
that we need in our runtime.
We can resolve the requirements from Maven and get the list of bundles by running a mvn install
in this project. This will attempt to resolve the initial requirements and calculate the
list of bundles. If the list differs from the -runbundles
setting then the install will
fail but it will give the list of calculated bundles:
bndrun $ mvn install
...
-runbundles: \
org.apache.felix.configadmin; version='[1.8.8,1.8.9)',\
org.apache.felix.log; version='[1.0.1,1.0.2)',\
org.apache.felix.scr; version='[2.0.2,2.0.3)',\
org.eclipse.equinox.metatype; version='[1.4.100,1.4.101)',\
org.osgi.service.metatype; version='[1.3.0,1.3.1)',\
osgi.enroute.examples.eval.simple.provider; version='[1.0.0,1.0.1)'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
...
[INFO] ------------------------------------------------------------------------
You can now copy this list and paste it into the osgi.enroute.examples.eval.bndrun
file at the end. Make sure there is only one (1) -runbundles
instruction in the bndrun file.
NOTE: You can add
If we now run maven again we succeed and a JAR file is created in the project directory.
bndrun $ vi osgi.enroute.examples.eval.bndrun
// add/replace the -runbundles
bndrun $ mvn install
...
bndrun $ ls
osgi.enroute.examples.eval.bndrun pom.xml target
osgi.enroute.examples.eval.jar src
We can now run the application as follows:
bndrun $ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
bndrun $ java -jar osgi.enroute.examples.eval.jar
The output is a little embarrassing …
Though rather disappointing, it does make sense since we’ve not created any bundle that does something that is visual to us. So the lack of output is understandable.
You can use Control-C to quit the application.
Since we do not see any output it would be nice to know if the launching was ok.
We can set the -runtrace
instruction to true
in the osgi.enroute.examples.eval.bndrun
file to see the launching progress:
-runtrace: true
If we build and run the application, we see the following:
bndrun $ vi osgi.enroute.examples.eval.bndrun
// set -runtrace: true
bndrun $ mvn install
...
bndrun $ java -jar osgi.enroute.examples.eval.jar
# properties {launch.name=bndrun, osgi.console=, launch.noreferences=false, ...
...
Id State Modified Location
0 ACTIV <> System Bundle
1 ACTIV <> jar/org.apache.felix.configadmin-1.8.8.jar
2 ACTIV <> jar/org.apache.felix.log-1.0.1.jar
3 ACTIV <> jar/org.apache.felix.scr-2.0.2.jar
4 ACTIV <> jar/org.eclipse.equinox.metatype-1.4.100.v20150408-1437.jar
5 ACTIV <> jar/org.osgi.service.metatype-1.3.0.jar
6 ACTIV <> jar/osgi.enroute.examples.eval.provider-1.0.0-SNAPSHOT.jar
# framework=org.eclipse.osgi.launch.Equinox@7c0e2abd
# registered launcher with arguments for syncing
# will wait for a registered Runnable
The output is quite extensive. If you have problems during the launch it is a great help and including this information with a bug report is highly appreciated.
What we’re missing is a shell to see the inner bowels of our runtime. The most
popular shell in OSGi is the Gogo shell. We can add this shell by adding it as
an initial run requirement in the osgi.enroute.examples.eval.bndrun
file:
-runrequires: \
osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)',\
osgi.identity;filter:='(osgi.identity=osgi.enroute.gogo.shell.provider)'
You probably also want to set -runtrace
to false
to minimize the output. We
will now get a shell; as long as the shell works we can assume the launch was
ok.
We now need to resolve the bndrun file. We run mvn install
which will fail
because the new list of bundles does not match the current list of bundles. We
then copy the -runbundles
into the osgi.enroute.examples.eval.bndrun
file by
replacing the existing list. (Make sure you do not get more than 1 -runbundles
instruction in the file.)
bndrun $ vi osgi.enroute.examples.eval.bndrun
// add the -runrequires for Gogo
bndrun $ mvn install
....
-runbundles: \
org.apache.felix.configadmin; version='[1.8.8,1.8.9)',\
org.apache.felix.gogo.runtime; version='[0.16.2,0.16.3)',\
org.apache.felix.log; version='[1.0.1,1.0.2)',\
org.apache.felix.scr; version='[2.0.2,2.0.3)',\
org.eclipse.equinox.metatype; version='[1.4.100,1.4.101)',\
org.osgi.service.metatype; version='[1.3.0,1.3.1)',\
osgi.enroute.examples.eval.provider; version='[1.0.0,1.0.1)',\
osgi.enroute.gogo.shell.provider; version='[2.0.0,2.0.1)'
....
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
bndrun $ vi osgi.enroute.examples.eval.bndrun
// copy the -runbundles from the output of mvn into the file
// replacing the existing -runbundles
bndrun $ mvn install
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
bndrun $ java -jar osgi.enroute.examples.eval.jar
____ _
___ _ __ | _ \ ___ _ _| |_ ___
/ _ \ '_ \| |_) / _ \| | | | __/ _ \
| __/ | | | _ < (_) | |_| | |_ __/
\___|_| |_|_| \_\___/ \__,_|\__\___|
https://v2archive.enroute.osgi.org
G!
Gogo has many commands. You can find an introduction at the Gogo App Note.
For example:
G! bundles
0|Active | 0|org.eclipse.osgi (3.10.100.v20150529-1857)
1|Active | 1|org.apache.felix.configadmin (1.8.8)
2|Active | 1|org.apache.felix.gogo.runtime (0.16.2)
3|Active | 1|org.apache.felix.log (1.0.1)
4|Active | 1|org.apache.felix.scr (2.0.2)
5|Active | 1|org.eclipse.equinox.metatype (1.4.100.v20150408-1437)
6|Active | 1|org.osgi.service.metatype (1.3.0.201505202024)
7|Active | 1|osgi.enroute.examples.eval.provider (1.0.0.201610030911)
8|Active | 1|osgi.enroute.gogo.shell.provider (2.0.0.201608121439-SNAPSHOT)
G!
What we’re running is the base core primitive simple Gogo shell. This means it can run
the commands that are on the Bundle Context (that is bundles
command is mapped
to BundleContext.getBundles()
) but there are now user friendly commands. A number
of such commands are implemented in the org.apache.felix.gogo.command
bundle. So we
could add this bundle to the -runrequires
instruction:
-runrequires: \
osgi.identity;filter:='(osgi.identity=osgi.enroute.examples.eval.simple.provider)',\
osgi.identity;filter:='(osgi.identity=osgi.enroute.gogo.shell.provider)',\
osgi.identity;filter:='(osgi.identity=org.apache.felix.gogo.command)'
So now you can resolve again and then we can run help
in the Gogo shell:
bndrun $ vi osgi.enroute.examples.eval.bndrun
// replace the -runrequires
bndrun $ mvn install
...
-runbundles: ...
...
bndrun $ vi osgi.enroute.examples.eval.bndrun
// replace -runbundles
bndrun $ java -jar osgi.enroute.examples.eval.jar
____ _
___ _ __ | _ \ ___ _ _| |_ ___
/ _ \ '_ \| |_) / _ \| | | | __/ _ \
| __/ | | | _ < (_) | |_| | |_ __/
\___|_| |_|_| \_\___/ \__,_|\__\___|
https://v2archive.enroute.osgi.org
G! help
felix:bundlelevel
felix:cd
felix:frameworklevel
felix:headers
...
scr:config
scr:disable
scr:enable
scr:info
scr:list
G!
In this section we’ve created a bndrun file to create an OSGi runtime. We then
learned how to add requirements to the file and resolve it so we get the -runbundles
.
We then learned how to add these -runbundles
to the bndrun file so they can
be exported into an executable jar.
We then executed this JAR and added a Gogo shell.