views:

725

answers:

5

OSGi has a problem with split packages, i.e. same package but hosted in multiple bundles.

Are there any edge cases that split packages might pose problems in plain java (without OSGi) ?

Just curious.

+3  A: 

For OSGi packages in different bundles are different, regardless of their name, because each bundle uses its own class loader. It is not a problem but a feature, to ensure encapsulation of bundles.

So in plain Java this is normally not a problem, until you start using some framework that uses class loaders. That is typically the case when components are loaded.

starblue
On further introspection, even web containers like Tomcat have different classloaders: catalina versus webapps'. So it might pose some problems.
ashitaka
Thanks, I edited accordinly.
starblue
+2  A: 

Splitting packages across jars probably isn't a great idea. I suggest making all packages within jars sealed (put "Sealed: true" in the main section of the manifest). Sealed packages can't be split between jars.

In the case of OSGi, classes with the same package name but a different class loader are treated as if they are in different packages.

Tom Hawtin - tackline
A: 

Are you asking because the package in question is yours, not third party code?

An easy example would be a web app with service and persistence layers as separate OSGi bundles. The persistence interfaces would have to be shared by both bundles.

If I've interpreted your question correctly, would the solution be to create a sealed JAR containing the shared interfaces and make it part of both bundles?

I don't mean to try and hijack the thread. I'm asking for clarification and some better insight from those who might have done more with OSGi to date than I have.

duffymo
Yes the packages belong to me. At the root, is the question of how to design the layout of the packages and have it be modular.
ashitaka
Then I'd say that common interfaces need to be packaged into separate JARs that can be part of both modules.
duffymo
+3  A: 

You'll get a nasty runtime error if you have classes in the same package and some are in a signed JAR while others are not.

Michael Borgwardt
+3  A: 

Where split packages come from

Split packages (in OSGi) occur when the manifest header Require-Bundle is used (as it is, I believe, in Eclipse's manifests). Require-Bundle names other bundles which are used to search for classes (if the package isn't Imported). The search happens before the bundles own classpath is searched. This allows the classes for a single package to be loaded from the exports of multiple bundles (probably distinct jars).

The OSGi spec (4.1) section 3.13 describes Require-Bundle and has a long list of (unexpected) consequences of using this header (ought this header be deprecated?), one section of which is devoted to split packages. Some of these consequences are bizarre (and rather OSGi-specific) but most are avoided if you understand one thing:

  • if a class (in a package) is provided by more than one bundle then you are in trouble.

If the package pieces are disjoint, then all should be well, except that you might not have the classes visible everywhere and package visibility members might appear to be private if viewed from a "wrong" part of a split package.

[Of course that's too simple—multiple versions of packages can be installed—but from the application's point of view at any one time all classes from a package should be sourced from a single module.]

What happens in 'standard Java'

In standard Java, without fancy class-loaders, you have a classpath, and the order of searching of jars (and directories) for classes to load is fixed and well-defined: what you get is what you get. (But then, we give up manageable modularity.)

Sure, you can have split packages—it's quite common in fact—and it is an indication of poor modularity. The symptoms can be obscure compile/build-time errors, but in the case of multiple class implementations (one over-rides the rest in a single class-path) it most often produces obscure run-time behaviour, owing to subtly-different semantics.

If you are lucky you end up looking at the wrong code—without realising it—and asking yourself "but how can that possibly be doing that?"
If you are unlucky you are looking at the right code and asking exactly the same thing—because something else was producing unexpected answers.

This is not entirely unlike the old database adage: "if you record the same piece of information in two places, pretty soon it won't be the same anymore". Our problem is that 'pretty soon' isn't normally soon enough.

Steve Powell
Steve, a very clear explanation. Because I divide up my code into many small maven artifacts, I now diligently assign a unique base package name to all artifacts.
ashitaka