Wednesday, September 10, 2008

PDE and 3rdParty Bundles in OSGI Enterprise apps

If you're developing an OSGI based Enterprise Application you'll always reach a point where you have to integrate external libraries, bundles or whole projects. In many cases PDE tooling will be your friend.

You have to watch some rules to make life easier - for you and others using your bundles. I already talked about this in previous blog entries. Hopefully it will help you to avoid chaos in your OSGI environment.

1. JAR - Files as Bundles

As a good citizen of OSGI world there's the first rule: 

Rule 1: 
Always put dependent JAR Files in separate bundles and describe the dependencies in your Manifest file. 
Don't hide those JARs in your own bundle. 

Then its much easier to re-use bundles or to let your bundles play together with others.

PDE makes it very easy to create bundles (plug-ins) from JAR - Files: Select New - Plug-In Development - Plug-in from existing JAR - archives, choose the JAR File - and thats it :-). 
Attention - please use this comfortable function as last of your steps ! At first follow the next rule for good OSGI citizens:

Rule 2: 
If a Bundle for your dependent JAR File already exists in one of the Bundle Repositories - then choose this. 
Don't create your own bundles for existing ones.

How do you know, if there's already a bundle ? Here's my way to search bundles:

  1. Does the bundle exist in the SpringSource Enterprise Bundle Repository ? SpringSource is my first choose, because all bundles and dependencies are described there in detail. A great thanks to the SpringSource Team for this great work.
  2. Does the bundle exist in the Eclipse Orbit Repository ? You can find an overview here.
  3. To be sure also search for the bundle at OSGI (look at OBR Bundle Repository).
  4. Only if all search results are negative, I'm creating my own bundle with help of PDE as descibed above. If its a common JAR - File used in many projects, then I create an entry into SpringSource JIRA "wishing" to have this bundle there. Some time ago I was looking for bundles of Drools Rule Engine, but nothing exists in any of the repositories. So I put an entry into SpringSource JIRA. Some days later: „Mission completed“ - if you're now looking for it you'll find per ex.: Drools Rules Engine Core.

2. Using "foreign" Bundles

Great - with the help of the repositories of PDE - Tooling we got all the dependent bundles providing the needed functionality and APIs. Now we can integrate them into our own OSGI Project.

Analyzing other projects and bundles in many cases I found, that the easiest way was used: Need a bundle ? Put a dependency with Require-Bundle. And because its so fast and easy re-export it simply hitting „Re-Export this dependency“ in Manifest editor.

To get a clean OSGI architecture there's something more to think about ;-)

My next rule to watch follows. I know that there's some controverse discussion about required bundles vs. importing packages. But from my experiencies you should do this:

Rule 3: 
If possible use Import-Package to resolve your dependencies. 
Export only your "public" packages  - no internal. 
Use Require-Bundle only to resolve dependencies inside your own „universe“, not against common bundles. 
Always version Require-Bundle, Import-Package und Export-Package.

Require-Bundle always has a dependency to a bundle with a specific name. You cannot change an Eclipse Orbit Bundle (per ex. org.apache.commons.logging) with a SpringSource Bundle (com.springsource.org.apache.commons.logging) if you're using Require-Bundle - only using Import-Package

Import-Package isn't dependent from the name of the bundle, so its more flexible. Of course its more work to look at your packages and decide which you need to import or to export compared to a one-liner with Require-Bundle

One example: Eclipse Riena needs a special Hessian Bundle because of Eclipse Buddy Policy. If you have a bundle where Require-Bundle points to another Hessian bundle you cannot use the one Riena needs. If you're using Import-Package you can avoid much trouble.

I have some more rules I'm watching to work easier with PDE:

Rule 4: 
If a bundle itself contains packages inside the bundle and exports them, never put these packages also into the Manifest as imported packages.
This can cause PDE to detect cycles and then some functionalities of PDE tooling don't run as expected.

s.a. Bugzilla 246615, 246617 and 208011.

Rule 5: 
Before deploying of a bundle as plug-in be sure the Package-Uses are re-calculated. 
Wrong Package-Use entries for exported packages can stop PDE to export your Plug-In.

s.a. Bugzilla 246615.

Rule 6: 

Avoid nesting  JAR - Files - better use multiple bundles.

s.a. Bugzilla 157375 - esp. comment #31.

Workaround: If a dependency to a „foreign“ binary bundle with nested JAR Files is causing PDE Build - problems, most time it helps to load another plug-in exporting these classes into the workspace.
Attention: You need this plug-in only to build / compile your bundle not for Runtime or OSGI Launch Configurations, because Equinox has no problem using bundles with nested JAR Files.

If you watch these DOs & DON‘Ts, then I'm sure you have less trouble and chaos and also your bundles itself can easy be integrated into foreign OSGI projects.

3.Integration of whole ("foreign") OSGI Projekts 

Sorry, but the reality isn't so easy as described above building complex OSGI Enterprise applications. You have to live with other projects not following those rules.

As an example try to integrate the OSGI EJB3 container from EasyBeans. EasyBeans contains some different components, utilities, an agent and a core bundle.

Not watching  Rule 1 and Rule 2:
bundle org.ow2.easybeans.core contains uncount JAR Files (the core bundle has a size of 12 MB). Many of these JAR Files are already available as bundles in OSGI Repositories. This makes it very hard to work with the core bundle and to let your own architecture clean. The EasyBeans team knows about this, so hopefully in the future this will become better.

Not watching Rule 4 and Rule 5:
org.ow2.easybeans.core causes problems with PDE Dependency Analyzing: PDE reports cycles and wrong package-uses. If only using the easybeans.core bundle in runtime or OSGI launch configurations, all works perfect. 
Problems arrive if an own bundle has dependencies to org.ow2.easybeans.core: PDE cannot export the bundle as Deployable Plug-In, because cycles and wrong Package - Uses are reported. (s.a. Bugzilla 246615)

Workaround to export your bundle with PDE tooling:

At first load bundle org.ow2.easybeans.core as Source Project into your workspace.

  1. PDE reports incorrect Package-Uses of org.ow2.easybeans.core if you try to export your bundle as deployable plug-in. Open MANIFEST.MF of org.ow2.easybeans.core bundle from workspace, tab Runtime - Exported Packages re-caclulate Uses. Save MANIFEST.MF and try again to export your bundle.
  2. Now PDE detects the cycles. Again open MANIFEST.MF, tab Dependencies, Dependency Analysis „Find unused Dependencies“ and remove all selected. Save MANIFEST.MF and try to export again.

Now you can export your bundle :-)

Remark: PDE is happy with this manipulated easybeans.core bundle - but never try to use this in runtime or from OSGI launch configs ! 

Problems with bundle - filenames:

EasyBeans uses filenames like 
    easybeans-component-hsqldb-1.1.0-SNAPSHOT
Eclipse uses filenames like 
    easybeans-component-hsqldb_1.1.0-SNAPSHOT

Did you notice the difference ? Eclipse uses underlines (_) before the version (1.1.0) and EasyBeans uses minus (-).

I'm always replacing -1.1.0 by _1.1.0 after downloading from EasyBeans. This makes some things easier, per ex. in bundle.info of config.ini I can use the plug-in - name only. Without replacing I always have to enter the whole filename, which means I have to change the config.ini for all version-changes, because Equinox cannot find the version number with all these "-" (Bug JIRA).


Problems with Bundle - Symbolic Names:

PDE has a problem using "-" in Symbolic Names. (s.a. Blog A dash of legacy from Chris Aniszczyk). 

EasyBeans contains some Util Bundles, where the symbolic name contains "-" (per ex. org.ow2.bundles.ow2-util-event-api). If you load such bundles into your workspace, they are marked as error (Bundle symbolic name contains illegal characters.  Legal characters are A-Z a-z 0-9 . _). You have to change the symbolic name.

Result:

Hopefully my rules, solutions and workarounds will help others fighting with OSGI bundle - dependencies.
If you're noticing problems with logging, please read my blog entries about "Logging in OSGI Projects".

Follow - Up:
Some more blogs are work-in-process and will follow soon to demonstrate the use of EasyBeans 1.1.0, Eclipse Riena M4 and Equinox 3.4 in a small example project.

11 comments:

Frederic Conrotte said...

Many thanks for this blog entry ekke, it will help me getting my way to OSGi within the Eclipse OFMP project.

Especially the "dash bug" that's worth mentioning !

One question: SpringSource bundles heavily use the "Package-Uses" meta-tag, does it hurt current version of PDE in any way ?

I have seen any trouble so far

ekke said...

frederic,

all bundles I used from SpringSource till now had no problems with "Package-Uses", they were all correct.

ekke

Frederic Conrotte said...

Good news. I was a bit worried about this info from Orbit team:
http://wiki.eclipse.org/Orbit_Minutes_080129#.22Uses.22_Clause_in_Bundle_Manifests

"(...) These issues will not be solved for the Eclipse Platform 3.4 so it is not recommended that bundles in Orbit use the "uses" clause for this release."

ekke said...

hmmm...
till now I had no problems.
I also could repair the wrong Package-Uses of easybeans.core using Manifest editor
ekke

ekke said...

thanks to Florent Benoit from EasyBeans pointing me to https://bugs.eclipse.org/bugs/show_bug.cgi?id=197503.

the problem using "-" in symbolic names is fixed for 3.4.1 :-)

ekke

Simon Kelly said...

hi Ekke, thanks for your posts, they have been very helpful. Have you tried automating a build with EasyBeans bundles? I am having great difficulty, every easybeans bundle reports"[eclipse.buildScript] Unsatisfied import package ..."

I thought it may be related to nested jar's but having exploded all the bundles nothing has changed. Any ideas?

ekke said...

hi simon,

I haven't tried this yet (but its on the todo list).

perhaps the reason are cyclic dependencies - if you try to export bundles dependent on easybeans bundles PDE reports cyclic dependencies. there are some tricks with dummi bundles in the workspace, but I hope that the bugs with cyclic dependencies and nested jars will be fixed soon.
ekke

Unknown said...

Hi,

I really would like to be a good OSGi citizen (devloping Eclipse RCP), but there is something not too obvious for me: How do I resolve transitive dependencies? For example, I wanted to integrate JAXB in my application. There is a corresponding bundle at Springsource, but this bundle again has various dependencies.

There must be a practical solution to this problem, but I seem to just can't find it.

Maybe I should also add, that I startet RCP development (and thus migrating to eclipse) not too long ago.

Bye,
Ralph

ekke said...

ralph,

if you're inside eclipse world then updates using P2 updatesites can recognize bundles you need.

but if adding bundles from 3rd party you have to do the work :-(
springsource is great because it says you which other bundles are required.

ekke
btw: just moved my blog to ekkescorner@wordpress.com

tiger said...

Oh, that's sad. I was hoping, that I just didn't recognize the integration ...

Btw ... could it be, that I was sitting right behind you in Wayne Beatons talk at JAX09?

Bye,
Ralph

ekke said...

maybe.... (JAX09) - I visited many talks
ekke