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.jfacemay depend directly onorg.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.resourcesinto 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 registry | Service | Declarative service |
|---|---|---|
|
|
|
|
|
|
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!