Alex headshot

AlBlue’s Blog

Macs, Modularity and More

EclipseCon OSGi best practices

2006, conference, eclipse, eclipsecon, osgi

The penultimate talk I attended at EclipseCon was Jeff and BJ's Best Practices for Programming Eclipse and OSGi. The slides aren't available on the EclipseCon site yet (since they only finished them just before the presentation itself); but they will be up there later on. In the meantime; this is my notes from the presentation:

Eclipse 3.1/Equinox is now the reference implementation for the OSGi R4 platform. A lot of use cases from Eclipse 3.0 were actually incorporated into the OSGi platform. [It's clear that the OSGi is becoming increasingly important; you can even run it on a slug - Al]

Modularity in OSGi bundles is important. There's two ways of sharing classes and resources between bundles, and there's advantages and disadvantages to each.

Require-Bundle

Allows bundles to be defined with dependencies specifically on a named bundle. For example, org.eclipse.jface may depend directly on org.eclipse.swt.

Advantages
  • Can be used to bulk import groups of dependencies
  • Can be used for non-code dependencies (help, resources)
  • Convenient for grouping imports
  • Can be used to join 'split packages' (e.g. test fragments)
Disadvantages
  • Tight coupling between dependent bundles; may cause brittleness
  • Split packages - don't know which bundle contains which package (e.g. refactoring of org.eclipse.core.resources into 5 separate bundles)
  • Package shadowing from other bundles
  • May have unexpected signature changes
Observations
  • Can be used for complex scenarios
  • Simple place to start for legacy code
  • Consider tradeoff between simplicity and flexibility
Import-Package
Advantages
  • Loose coupling between implementation and interface
  • Arbitrary attributes allow sophisticated export matching (using LDAP-style filters)
  • No concept of whole packages
Disadvantages
  • More metadata to be created and maintained (one per package, not one per bundle)
  • Only useful for code dependencies
  • Can't be used for split packages
Observations
  • PDE can help management of import-packages
  • Versioning may cause problems

In terms of collaboration, there's several ways of doing this in Eclipse 3.2. There's the Extension Registry, which has been there since the start, but recently, the Service Registry, which can be used to maintain services throughout a system. The key difference is that the extension registry is declarative; and thus uses lazy loading to load implementation. It's also hooked with the life cycle of the bundle too; when the bundle is installed, the extension is registered, and when it's uninstalled, the extension is unregistered. The Service Registry on the other hand uses a publish/find/bind model, and is loosely coupled. That means the service can be started and stopped during runtime, and so isn't necessarily based on plugin lifecycle. However, given that it's API based, it means that services must be loaded eagerly, which obviously is less desirable in terms of startup time. Fortunately, there's a Declarative Service Registry, which adds a declarative definition of the service along with a simple wrapper that enables the service to be effectively started the first time it's called. It's somewhat similar to the Spring concept of XML configuation being used to dynamically switch service implementations.

There's no single answer as to which way you should implement services, since there's a decoupling of client and service anyway. There are issues depending on whether you want the client to be responsible for registering itself as a listener, or whether the server is responsible for querying all available listeners. They can also affect the order of starting services and whether the service or listener needs to be brought in eagerly or lazily. In any case, using services is a good way of decoupling client and server, and the services registry can be queried to find services that match a particular LDAP-style filter.

Extension registryServiceDeclarative service
  • Provide contact with extension point
  • Provide data-only payload
  • Lazily loaded and run
  • Lifecycle scoped to resolved state of bundles
  • Public contract
  • No data-only payload
  • Eager loading
  • Lifecycle scoped to started state of bundles
  • Public contract
  • No data-only payload
  • Lifecycle scoped to started state of bundles
  • Classloader not necessarily started with bundle; the activator doesn't need to run
  • Use when there's a tightly coupled relationship, such as contributing UI elements
  • Use when providing a service usable by any consumer (loosely coupled)
  • Use when substitutability of service providers and consumers is desired
  • As for services, but can be dynamic
  • Does not have the full power of service registry, such as starting upon receipt of an external event

end of presentation

One question from the audience asked if were possible to have two versions of the same plugin operating at once. The answer was yes, provided that they aren't singletons. A singleton bundle is used to prevent any other versions of a bundle being loaded in memory, which might be desirable for a bundle (like SWT) that needs access to a single system resource (such as a windowing system) or something that provides UI contributions (so that you wouldn't want two versions of the same menu item, for example).

It's clear that OSGi is going to be big. If you've not looked into it yet, look into the Equinox, which is the Eclipse OSGi engine. There's also other open source ones; Felix is the Apache implementation. There's also Harmony, which is a (pseudo) OSGi-aware Java VM that's using OSGi references to support a split of the normal rt.jar into separate Jars.

EclipseCon has certainly been busy this year. I've enjoyed every minute and I'm glad to have met all the people that I have done. Now, I just need several hours more sleep and get back to normal, and I may be able to start doing some of the many things that I've volunteered to help out with. Thanks for listening!