In the Introduction to OSGi document we've learned the basics about OSGi and have learned lots of expressions and terms in the context of OSGi.
Now it's time to leave the theoretical lesson and go for a practical hands-on workshop.
In this exercise, we will
1. create a bundle
2. export the bundle and install it
3. do some operations on the OSGi console
Why are we doing this exercise?
- We learn how we can write a bundle which could be then deployed into an OSGi-based application server
- We learn how we can communicate with the OSGi Framework
- We learn how the lifecycle and version management works in OSGi
In your Eclipse, open the Java-Perspective (Window -> Open Perspective -> Java)
Open the New Project wizard via File -> New -> Project -> Plugin Development -> Plug-In Project
Press Next
Enter the project name, e.g. MySampleBundle, and choose “targeted to run with: an OSGi framework: standard”
This means that this bundle can run on any OSGi environment.
Press Next, enter the details as desired and enable the generation of the Activator class
Example:
ID | com.my.company.mysamplebundle |
Version | 1.0.0 |
Name | MySampleBundle |
Vendor | me |
Activator | com.my.company.mysamplebundle.Activator |
Explanation:
ID | this will be the unique identifier for the bundle that we create. Typically a fully qualified name. Will be the name of the jar file in the plugins folder |
Version | Together with the ID, the version uniquely defines the bundle. You may have several same bundles in different versions in your OSGi container |
Name | the human readable display name of the bundle |
Vendor | the company, if any. Can be empty |
Activator | The activator is a Java class that is invoked by the OSGi Framework and allows that the bundle can access info from the framework. Not mandatory. |
Press Next, de-select the template-creation and press Finish.
Result:
A Java-Project with the generated Activator-class
Furthermore, the project contains a MANIFEST.MF file in the META-INF folder
The manifest
Right after project generation, the manifest file is opened in the so-called Plugin Manifest Editor.
The information gathered by the wizard is already present.
Background
For our exercise, we don’t need to change anything here, but you may test the editor by doing the following:
Open the tab “Dependencies”.
You’ll see that the generator has already added a dependency to a package.
You can now press “Add” in the “Required Plug-ins” section,
type e.g. “equinox” in the filter field,
select e.g. the “…common” Plug-in and
press OK.
The result is a dependency to a Plug-in.
You know that there are 2 possibilities of defining dependencies:
on Plug-in level and on package-level (2nd one is recommended)
Now you may select the added plug-in and press “Properties”.
In the popup you can see that:
You can define this dependency as optional (the code of your plug-in has to support that)
You can reexport this dependency (such that other plugins, which depend on you, can enjoy of this lib)
You can define the version(s) of this dependency.
You know that the dependency management is very sophisticated
Close this dialog and open the tab “Runtime”
In the section “Exported Packages” click on “Add…”
The dialog offers the one package that exists in our example.
Select it and click OK.
Now this package is exported and can be used by plugins which depend on us.
The right section “Package Visibility” has become enabled.
You can choose if the selected exported package is visible for all plugins which depend on us,
or you can choose to only export the package for plug-ins which you select.
You've learned that the visibility management is very sophisticated.
Don’t forget to open the tab “MANIFEST.MF”, where you can see how the configurations which you’ve done are written into the manifest file
Open the Activator-class with double-click in the Project Explorer View.
You can see that this class has been generated as subclass of BundleActivator, which is part of the package org.osgi.framework, which has been added as dependency by the generator.
There are 2 relevant methods which have been overwritten, the start and stop methods.
These methods are invoked by the OSGi Framework, whenever this current bundle is started or stopped.
The generator has created code which stores the object BundleContext.
This makes sense, because this object allows access to the Framework, which provides access to bundles and services.
We’ll now add some lines to the generated code, which will allow us to see how OSGi works.
Add the following line to the start() method:
System.out.println("==> Hello World. Greetings from: " + bundleContext.getBundle().getSymbolicName() + " - " + bundleContext.getBundle().getVersion());
Add the following line to the stop() method:
System.out.println("==> Goodbye World.");
Running the created bundle:
Eclipse nicely supports running any current development right from the active Eclipse instance (using the appropriate launch configuration, which also exists for OSGi).
But in order to gain a little bit more insight into the OSGi-World, let’s do the following:
Export our example bundle to the local file system, just like it would be done for productive usage (almost…)
Then install the bundle into our running Eclipse. Our running Eclipse will then take the role of a standard OSGi environment.
In the Eclipse Project Explorer View, select your bundle-project, open the context menu and press “Export”
Select Plug-in Development -> Deployable plug-ins and fragments
Press Next
Select your bundle and choose “install into host. Repository:”
Enter the path to an empty directory.
Press Finish.
The wizard will do the following:
- Compile bundle and create a jar file.
- Create a repository at the specified location
- Invoke p2 in order to install the bundle in the currently running Eclipse instance (the OSGi host mentioned in the wizard)
Eclipse asks to restart, since its installation has been modified.
Background:
In the meantime, you may have look at the file system, to see what has been generated:
A plugins folder containing the exported bundle.
The artifacts.jar file which contains the artifacts.xml, which contains information about the generated (default) repository and the exported bundle.
The content.jar file which contains the content.xml, which contains information about the generated metadata repository and the exported installable unit.
Note: in the export step above, we’ve exported the bundle standalone. It would have been an appropriate alternative to create a feature, add the bundle to it, and export the feature.
Now check the plugins folder of your Eclipse installation: Our bundle has been copied from the repository to the plugins folder.
Now check the bundles.info file: it contains an entry for our bundle.
Now check the folder configuration\org.eclipse.osgi\bundles: here, a new folder has been created for our bundle. The name is a number, which we’ll recognize later.
So we see that our bundle has been really installed.
In the meantime, Eclipse has finished starting.
Check the configured software sites: Eclipse main menu -> Window -> Preferences -> Install/Update -> Available Software Sites
Select that entry in the tree and the right pane shows a new entry called “Exported Repository” which points to our location
You could now add more plugins and installable units to this repository and use it for sharing it with colleagues, etc
Now let’s have a look at Eclipse as OSGi runtime.
Open the Console View.
(In case you don’t see it, open it via Eclipse main menu -> Window -> Show View -> General -> Console)
Open the OSGi Console via drop down of the view:
In the OSGi console, we can play around with the OSGi commands.
Type ss
ss
The result is a long list of all installed plugins
Type lb mysampl
lb mysampl
The result is the matching bundle, which is our sample bundle.
The result prints the ID of the bundle, which is not the BundleSymbolicName, but the ID, under which it is recognized by the OSGi registry
You’ll see that this ID is the same like the number of the name of the created folder in the “bundles”-directory.
Type b <bundleID>
b <bundleID>
The result is the detailed information about the bundle.
The status of the bundle is RESOLVED. It hasn’t been automatically started.
P2 supports automated start via so-called start levels.
Anyways, let’s start it manually
Type start <bundleID>
start <bundleID>
In general, there’s no result for that command.
But since we’ve modified the start() method in our bundle, we see the System.out printed to the OSGi Console.
Check the status of the bundle.
Type b <bundleID>
b <bundleID>
The status is now ACTIVE.
Type stop <bundleID>
stop <bundleID>
Now our System.out is printed to the console:
Now you can check the status again. It is back to resolved.
Type ss –s RESOLVED
ss –s RESOLVED
The result is a list of all bundles in status RESOLVED
Type uninstall <bundleID>
uninstall <bundleID>
As a result, our bundle is uninstalled. You can verify it by typing lb mysampl and it won’t find the bundle
Check your file system:
the folder bundles\<bundleID> has been removed
The bundle jar in the plugins folder has not been removed
So, the uninstall procedure works on the metadata. This light-weight mechanism allows e.g. to switch between versions and to go back to older version if desired, etc.
Now we install the bundle again, this time using the command line.
Type: install file:C:/temp/plugins/com.my.company.mysamplebundle_1.0.0.jar
install file:C:/temp/plugins/com.my.company.mysamplebundle_1.0.0.jar
Note that the path has to be adapted to your export location.
Afterwards start the bundle as described above and check that it becomes active.
We go back to our bundle-development and we develop the second version of our bundle.
In the Activator-class, we modify the start() and stop() methods:
The start() method:
System.out.println("Hello, I'm back and I'm new: " + bundleContext.getBundle().getSymbolicName() + " - " + bundleContext.getBundle().getVersion());
The stop() method:
System.out.println("See you later...");
In the MANIFEST.MF file, we increase the version to e.g. 1.0.1
Bundle-Version: 1.0.1
Then we export the bundle, as described above, to the same location, i.e. into the same repository.
Restart Eclipse.
Check the plugins folder:
there are 2 jar files with same name, but different version
Open the OSGi console
Type lb mysampl
lb mysampl
As result, you can see the new bundle in the new version.
The export-and-install-into-host action in Eclipse has automatically replaced the old-version-bundle with the new-version-bundle
But the replacement has took place on metadata-level, the jar file in the Bundle Pool (plugins folder) hasn’t been removed.
Anyway, no problem, we install the old-version-bundle manually.
Type: install file:C:/temp/plugins/com.my.company.mysamplebundle_1.0.0.jar
install file:C:/temp/plugins/com.my.company.mysamplebundle_1.0.0.jar
Now again type lb mysampl
lb mysampl
As result, you’ll get both bundles
Now you can go ahead and start both bundles
Now again type lb mysampl
lb mysampl
As result, you’ll get both bundles in status ACTIVE.
That’s all for our first exercise.
Homework for you would be:
Create 2 more, different bundles.
The first one has a dependency to mysamplebundle_1.0.0
The second one has a dependency to mysamplebundle_1.0.1
Export them and play around with them.
Start them, stop them.
Stop both mysamplebundle bundles, then start the first new bundle.
Etc
The second exercise can be found here: Getting started with GWPA: OSGi Introduction Exercise 2
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
26 | |
25 | |
21 | |
12 | |
9 | |
8 | |
8 | |
8 | |
8 | |
8 |