Wednesday, February 25, 2009

Installing and running plugins in Eclipse applications

A common question on the newsgroups is: "I copied new plug-ins into my RCP application but they are getting ignored, what's the problem?". The answer to this is really quite fundamental and is something I think every RCP developer should understand.

My answer here is about the Equinox runtime which is used in Eclipse and is the reference implementation of the OSGi spec.

Installing into the OSGi Runtime

Every plug-in (or bundle, I use the terms interchangeably), must be installed into the OSGi runtime before you can even think about it running. There are two main ways to install a bundle: programmatically through the BundleContext API, or declaratively through the osgi.bundles property in the config.ini file.

The osgi.bundles property is read at startup. It is a list of bundles that are automatically installed and optionally started once the framework is up and running. The format of each entry is
<URL | simple bundle location>[@ [<start-level>] [":start"]]

Starting your bundles

It is not enough to simply have your plug-in installed, it must also be started. When the OSGi framework starts up, it increments through the start levels starting bundles as it goes. A bundle won't be started until its start level is reached, and to get started it must be marked as such, or be marked as lazy start. A lazy start bundle will be started when something tries to load a class from that bundle (and once the start level has been reached for that bundle).

[Edit:] In most cases, marking a bundle as Lazy-Start is sufficient and one need not worry about starting bundles explicitly. See Neil's comment attached to this post.

The default start level for bundles is 4.

Managing installed bundles


There are 2 strategies here, one is to list all of your bundles on the osgi.bundles list, the other is to list only a few bundles that can bootstrap the rest of the application. I will call this kind of bootstrap bundle a "configurator".

If you list all your plug-ins on the osgi.bundles property, then it can be painful to maintain and add new plug-ins to your application. I won't try to make arguments for or against any particular way of managing your system, but it a large way it often comes back to the differences between the old update manager and the new p2 provisioning system.

Update Configurator


In Eclipse 3.3 and earlier, there was the update configurator (org.eclipse.update.configurator). It was installed on the osgi.bundles list and started at level 3. It would scan the plugins directory and automatically install everything it found there.

This is where the magic ability to just copy things into the plugins directory and have them work came from. However, update configurator is essentially forcing the found bundles into the framework with no regard to any conflicts or unresolved dependencies that may result.

Simple Configurator

In Eclipse 3.4, with the advent of p2, update configurator is replace with simple configurator (org.eclipse.equinox.simpleconfigurator). As the name suggests, it is quite simple: it installs everything it finds listed in its configuration file (specified by the org.eclipse.equinox.simpleconfigurator.configUrl property, usually bundles.info).

Editing the bundles.info file to add plug-ins to your product is not really any easier than editing the osgi.bundles list. The difference here is that p2 manages bundles.info for you. In fact, if your product is p2 enabled for updating and installing plug-ins, then any changes made manually are likely to be lost when p2 updates or installs new software.

Dropins

Whatever the other problems update has with respect to avoiding conflicts and ensuring that dependencies are satisfied, it is hard to ignore the simplicity of just copying new bundles into your install. p2 has support for dropins (provided by org.eclipse.equinox.p2.reconciler.dropins).

Like the update configurator, the dropins reconciler will automatically watch a directory and install things it finds there. However, unlike the update configurator, it will ensure that the bundles found will not conflict with others in the system and that all dependencies are satisfied.

7 comments:

Chris Aniszczyk (zx) said...

Thanks for the summary Andrew. This should be helpful for people who want to get a better understanding of how the various configurators work in Eclipse.

Neil Bartlett said...

Hi Andrew,

Thanks, this is a good summary. One small quibble:

"It is not enough to simply have your plug-in installed, it must also be started."

Actually, unless you are using something like OSGi services, it's not necessary for the bundle to be started. If your bundle declares extensions, they will become visible when the bundle is resolved.

The way it works is usually as follows: suppose your bundle contains a View declared via an extension into the org.eclipse.ui.views extension point. As soon as your bundle is resolved, the visual placeholders for your view will be displayed, i.e. it will be visible in the Show View menu and so on.

If the user shows an interest in the view by actually selecting it from the menu, at that point Eclipse loads the class that implements the content of the view. That classloading event triggers activation of your bundle if it is marked as lazy-start. However the activation in most Eclipse bundles is only used for basic initialisation, like turning on debug logging and starting the compatibility layer (for old pre-OSGi plug-ins).

Andrew Niefer said...

Yes Neil, perhaps I glossed over the Lazy-Start a little too quickly. Especially given that this mechanism is sufficient for the large majority of plug-ins and most don't need to worry about getting started in other ways.

Lately I've been working more with p2's use of services where we've had a few issues getting the services started.

Fushimisi said...

Nice summary, it was really useful for me.
One thing I would still like to find out: where is p2 reconciler reporting the problems it finds when scanning the dropins?
With update manager I had to watch the error log on startup and could collect the eventual missing dependencies, but p2 simply drives me crazy when it ignores my bundles without issuing a single error message.

Andrew Niefer said...

Fushimisi, I don't think the dropins is reporting anything right now, see bug 264924

Fushimisi said...

Thank you, Andrew. I voted for the "enhancement" and I can only hope that it gets promoted to a bug.

andig said...

Hi Andrew, Neil,

thanks for your post and comments. I've recently tried integrating Jetty as embedded http server in RCP applications- wthout using config.ini to ensure bundle start. I'm now stuck with reproducibly getting jetty started as well as making sure the http registry is also started in order for my declared servlet extensions to get processed.

Any thoughts on this?

Best regards,
Andreas