Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

under construction

Introduction

Explain:

  • What is a bundle? Give an example.
  • What is OSGi and how does it work?
    • Explain what an Activator is.
  • Provide references to tutorials developers new to the concept of bundles can read to get familiar with the topic.
  • Explain the concept of extension point.
  • Explain the advantages of bundles, plug-ins. (Ann can write this part after talking more with Michael and Lance.)

Developing IGB bundles

IGB bundles are OSGi compatible, so they must have an Activator, a class that extends org.osgi.framework.BundleActivator, and they must have a manifest.mf file that is found in the META-INF directory. These are compiled and jarred with all required classes, jars, and resources. The resulting jar is the bundle. This can then be uploaded to the bundle repository. At that point, any one can use the bundle with IGB. IGB uses the Apache Felix OSGi implementation, but this could change, so no Felix specific code should be used. In the Activator class, there is a start() and stop() method that are called when the bundle is activated / deactivated (not installed / uninstalled). This is where you want to put all the code to start and stop the bundle.

In the manifest.mf file, there are several headers that need to be specified - fill in parenthesis below:

Panel

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: (name of bundle)
Bundle-SymbolicName: (name of bundle)
Bundle-Version: (bundle version, you can use 1.0.0 to start)
Bundle-Activator: (activator class name, including package)
Bundle-ActivationPolicy: lazy
Bundle-Vendor: (your company)
Bundle-DocURL: (URL of bundle documentation)
Import-Package: (list all external packages required by the bundle)
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ClassPath: (put the class path within the bundle itself, e.g.: ., resources/, lib/xyz.jar)
Bundle-Description: (description of bundle)
Require-Bundle: (list all bundles required by this bundle)

Ann's note: the formatting below is weird. Did you copy and paste from an email message?

Ann's note: Please explain how the fields in the manifest map onto what user's see in the Plug-Ins tab.

Import-Package and Require-Bundle don't need to overlap, you can specify a requirement
in one or the other. To have a multi line header, start the continuation line after a blank in column 1.
Put a blank line at the end of the manifest.mf file - due to a bug in felix.
The igb, genometry and genoviz projects can by accessed as bundles.
If a class/method is needed from igb/genometry/genoviz, it must be public, and the package
must be exported in the manifest.mf Export-Package list. Ann's note: manifest.mf of what?
If you want to add a tab window (Ann's note: Do you mean panel or window, because they can be opened as new windows?) as a bundle, there is a helper abstract class, 
com.affymetrix.igb.window.service.WindowActivator, that you can extend.
If you need access to other bundles (like IGBService), you will not be sure when the
bundle is available. (Ann's note: Please explain more) For Services, like IGBService and WindowService, you can use a
ServiceTracker to be notified when the required service is available - see WindowActivator
for an example.

To create plug-ins using eclipse - a Quick-Start Guide

Eclipse (http://www.eclipse.org) makes it a lot easier to develop bundles. You can create a new project
as a plug in project, and it will give you wizards, etc. for development. see:

Table of Contents

Introduction

Plugins are software programs that can be dynamically added to existing programs to add / enhance functionality. They are also called Add-ons or Bundles (the OSGi term). In IGB, plug-ins are also called "Apps." You may have seen plugins in the software that you use, such as internet browsers, text/graphics editors, games, etc. Examples include Chrome extensions and countless Photoshop filters. Users can search for plugins and choose ones that address their needs. Users can add or remove plugins at will without having to re-install the base application. Plugins can also be updated dynamically when the author(s) make changes.

IGB uses OSGi to implement plug-able Apps 

OSGi is specification and framework for building modular applications in java. In addition to the framework specification, it also contains a specification for dynamically installing and running plug-ins. The OSGi term for a Plugin is Bundle. They mean the same thing.

An OSGi bundle is a nothing but a jar file with some OSGi-specific headers included in the its MANIFEST.MF file. The OSGi framework uses these headers to manage how the bundle interacts with other bundles within the same framework.  The OSGi framework also use the headers to manage transitions between lifecycle states for a bundle - installed, resolved, starting, active, stopping, and uninstalled.  

An OSGi bundle can (usually will) have a special java class called an Activator. This class must extend org.osgi.framework.BundleActivator, and implement the start() and stop() methods. The activator class is specified in the Bundle-Activator MANIFEST.MF header (see below). These methods are called when the bundle is started and stopped.

When a program is running with OSGi, the OSGi framework dynamically handles installing / uninstalling, activating (starting), deactivating (stopping), and upgrading bundles.

OSGi caches bundles, saving them to a directory called the "bundle cache" on the local hard disk, so that they don't need to be downloaded every time. So you can work offline after you have loaded IGB. IGB stores the App bundles alongside core IGB platform bundles in a folder called "bundles" in an IGB-specific directory called ".igb." The bundles directory contains subdirectories for specific IGB versions.   

There are several implementations of OSGi, including:

The implementations are (for the most part) interchangeable and are free. The implementations allow the user to run OSGi from a command line tool or to start it within a program.

IGB uses the Apache Felix implementation from within the com.affymetrix.igb.main.OSGiHandler class.

There are several tutorials for OSGi, including:

...

  • )

- check out IGB from httpsIGB uses OBR (http://genovizfelix.svnapache.sourceforge.netorg/svnroot/genoviz/trunk
  into a new project in eclipse
- make a new IGB_HOME environment variable to point to the IGB project (Ann's Note: What directory should it point to in the checked out code - maybe give an example?)
- open a command prompt in IGB_HOME, and do an "ant clean" and "ant jar"
- in eclipse, project explorer, right click the IGB project and select "refresh"
- in eclipse, project explorer, right click on open space, and select "Import..."
  Select "Plug-ins and Fragments" under "Plug-in Development", click the "Next >" button
     under "Import From", select "Directory:",
     under "Plug-ins and Fragments to Import" select "Select from all plug-ins and Fragments",
     under "Import As" select "Binary Projects"
     for "Directory:", click the "Browse..." button and select the IGB_HOME/ext, click the "OK" button
     click the "Next >" button
  under "Plug-ins and Fragments Found:", select affx_fusion, colt, freehep, image4j, jlfgr, picard, and sam
     click the "Add -->" button to add these all to "Plug-ins and Fragments to Import:", click the "Finish" button
- Do the following for the directories under IGB_HOME, genometryImpl, genoviz_sdk, igb, plugins/igb_service, plugins/window_service
   in eclipse, project explorer, right click on open space, and select "Import..."
   Select "Existing Projects into Workspace" under "General", click the "Next >" button
   click "Select root directory:" and click the "Browse..." button on the right
   select the project under IGB_HOME, and click "OK"
   click "Finish"

Ann's note: Please add a tutorial explaining how to develop a simple plug-in. Your graph plug-in is probably a good place to start. We need a very simple but cool example that relies on a stable part of the API so that the tutorial doesn't get out of date.)

Sample plug-in using eclipse

 In the Project Explorer - blank area, right-click
 New > Project ... > Plug-in Project > "Next >" button
 Project name: "HelloWorld" > "Next >" button
 Version: "1.0.0" check "Generate an activator ...",
   Activator "helloworld.Activator", Rich Client Application click "No",
   "Next >" button
 Uncheck "Create a plug-in using one of the templates", "Finish" button
 Under the new HelloWorld project, find the META-INF directory, and open
   the MANIFEST.MF file by double-clicking on it.
 Click on the "Dependencies" tab,
   in the "Required Plug-ins" box, 
   highlight org.eclipse.core.runtime, and click the "Remove" button on the right.
   next to the "Imported Packages" box, click the "Add..." button, int
   the "Package Selection" popup in the text box, enter "com.affymetrix.genoviz.util"
   and click the "OK" button. Do the same for "org.osgi.framework" (there may be
   a version number in parentheses after the name).
   Right click on the blank area at the top, next to "Dependencies" and
   a context menu comes up, click "Save".
 Open the Activator.java file under src/helloworld, add the import statement
   import com.affymetrix.genoviz.util.ErrorHandler;
   at the top, and add the line
   ErrorHandler.errorPanel("Hello World");
   at the end of the start() method, and
   ErrorHandler.errorPanel("Goodbye World");
   at the end of the stop method
   Save the file
 In the Project Explorer, Right click the HelloWorld project, > "Export ..."
   "Deployable plug-ins and fragments", "Next >" button,Under "Available Plug-ins and Fragments:", check only
   Hello World, "Directory:" use any directory you like. click the "Finish" button.
   The HelloWorld_1.0.0.jar file will be in the plugins directory under the directory the you specified. This is your bundle
   In the plugins directory, from the command line run
   java -cp IGB_HOME/igb_server/lib/bindex.jar -jar bindex.jar -n IGB -q -r repository.xml .
   where IGB_HOME is your IGB directory.
   Now, if you can access your plugins directory from a local web server, you can open up the Plug ins tab
   in IGB, and click on the "Repositories..." button on the lower right. Click the "Add..." button, and put the
   URL for your local plugin directory. Click the "Add Server" button, then close the Preferences popup. Now,
   uncheck and recheck the "Show Uninstalled" checkbox at the bottom of the Plug ins tab. You should nos
   see your Hello World plugin. If you install the plugin you will see an Error popup "Hello World". When you uninstall
   the plugin, you will see an Error popup "Goodbye World".

To create plug-ins using NetBeans - a Quick-Start Guide

Is this possible? Easy? site/apache-felix-osgi-bundle-repository.html) to find and load bundles from web servers (repositories). The web servers need to use OBR to create the repository.xml file listing all the available bundles. 

Users can add / remove bundle repositories by choosing File>Preferences , Plugin Repositories tab.

IGB uses OSGi Services to allow bundles to add new implementations of existing IGB elements. The new implementations will show up as soon as the bundle is started. Examples include IGB tabs and graph manipulation functions.

Extension Points

IGB has several "extension points" designed for Apps. These are interfaces or abstract classes that are implemented or extended by App classes. Usually the Activator for the App will register the App as a service in its start() method:

Code Block
bundleContext.registerService(<extension point>.class.getName(), 
                              <plugin implementation>, 
                              new Properties());

Some of the available extension points include:

  • com.affymetrix.genometryImpl.operator.Operator - operates on a selection of tracks from the GraphAdjuster tab or popup menu
  • com.affymetrix.genometryImpl.parsers.FileTypeHandler - process a file type (by the file extension)
  • com.affymetrix.igb.shared.TrackClickListener - called when the user clicks on the label portion of a track
  • com.affymetrix.igb.shared.GlyphProcessor - called when IGB creates a glyph
  • com.affymetrix.igb.shared.MapViewGlyphFactoryI - a new way to display a track
  • com.affymetrix.igb.search.mode.ISearchMode - a new search method option on the Search View tab
  • com.affymetrix.igb.osgi.service.IGBTabPanel - a tab in the JTabbedPane at the bottom and sides of IGB
  • com.affymetrix.genometryImpl.util.ServerTypeI - a server type
  • com.affymetrix.igb.osgi.service.IStopRoutine - a routine to be run when IGB terminates
  • com.affymetrix.igb.prefs.IPrefEditorComponent - a Preferences window to let users enter preferences

IGB-specific MANIFEST.MF requirements

To install an App into IGB, the MANIFEST.MF file needs to include the standard OSGi headers, which you should not have to manually add. You should use the BND tool to create these. Of these, two are specifically required by IGB to install and manage Apps. These are:

  • Bundle-SymbolicName - used by IGB to uniquely identify an App and its various versions, e.g., "super-simple-igb-app." Users typcally do not see this name; however, App Store uses this to form URLs to App-specific pages, e.g., https://apps.bioviz.org/apps/org.lorainelab.igb.protannot
  • Bundle-Version - used by IGB to distinguish different versions, called "releases", of the same App, e.g., "0.0.1." An App's version should always look like x.y.z, where x, y, and z are non-negative integers. It is important to not include suffix tags so that IGB can distinguish higher from lower versions of the same App. 

IGB also recognizes and uses two optional MANIFEST.MF headers. These are:

  • Bundle-Name - a user-facing, display name for an App, e.g., "Super Simple IGB App." This appears in App Manager and also on IGB App Store pages. 
  • Bundle-Description - base64-encoded markdown text describing the App. IGB App Manager and IGB App Store pages display the decoded, rendered Markdown to users. We provide a maven plugin (bundle-markdown-encoder) for developers to include this header in their bundle's MANIFEST.MF file.