Bundle selection extended - what if…

OSGi provides developers with plenty of configuration and selection mechanisms to adapt your application perfectly to a certain environment. One of these features is the usage of native code. Other than plain Java in OSGi you can simply define a header like the following:

Bundle-NativeCode: lib/superDuper.dll;
osname = WindowsNT;
processor = x86;
selection-filter="(net.mjahn.sample.windowing=win32)";
language = en;
language = de

Now doing this in a fragment is a very nice feature. If your environmental requirements are met, your fragment gets attached to the host and the correct library will be loaded by your OS. On the other hand, if you deploy that fragment on another machine with let’s say a Solaris OS, it simply won’t get resolved. The advantage is you can just create an assembly with all native libraries for the different OS versions and systems in different fragments. Depending on your environment, the container will figure out, which fragment to choose and attach to the host. Piece of cake, I would say.

Recently I was faced with a similar, but unfortunately more difficult problem. I wanted to provide two different bundles containing a distinct implementation of a specific API as fragments; depending on the OS it is running on. On first sight, it is the problem, I already discussed, but on a second view, I realized that it is actually plain Java. The API, I am providing in my fragments is OS dependent, but doesn’t contain native code. I thought, I could work around it, by providing something like a selection-filter or anything similar to the mechanisms of the Bundle-NativeCode header, but there isn’t. (If I am wrong here, please enlighten me, but I haven’t found anything in the 4.1 OSGi core specification!).

Of course, if you have the possibility, you can just implement your own mechanisms to do what OSGi does for native code, just with plain old Java code. Check the environment and load the correct libraries or even simpler, just only provide the correct fragment versions. This is all true; it definitely would work that way. The question, I am asking myself is more, shouldn’t this actually be an infrastructural concern? Shouldn’t the infrastructure be able to decide what is necessary and suits best? In my opinion, one of the big advantages of OSGi is the expressiveness of constraints. Everything is explicit, so from my point of view, it is logical to enable such declarative dependencies without native code as well.

One question remains: Where should this mechanism be added? Like with singleton bundles together with the “Bundle-SymbolicName”? I wouldn’t say so. I think the “Bundle-RequiredExecutionEnvironment” would be a perfect spot for that. A selection based on System properties is flexible, yet distinct enough, so the already introduced “selection-filter” could be applied here. The execution environment in general fits the scope of this property way better than any other, already defined in OSGi.

Well, unfortunately, I am not an OSGi member and the next spec will take a while to come, so I guess this is nothing to be expected any time soon, if at all ;-) Maybe I am wrong about all that, because I am missing something, but I actually haven’t found any evidence stating the opposite. Till then, I hope for the best - a more compatible (IT) world.

– Mirko

Share/Save/Bookmark

Half bundle, half jar - the nature of a fragment, a blessing or a curse?

When first diving into OSGi, you probably don’t notice fragments at all. After a while, once you become familiar with the concept and the main parts of the spec, you start looking into ways to accomplish things, which were fairly simple done in plain Java, but might be really painful in OSGi. By then the latest, you’ll find them in the spec and they are really tempting in so many ways. Before I elaborate on that, let me just summarize the main features of fragments in order to give everyone a chance to follow.

Fragments, like bundles are just simple jar files with additional manifest headers; actually they are almost the same as the bundle manifest headers. At first glance, bundles and fragments look alike. Both are jars by definition and specify additional manifest headers. The huge difference is that a Fragment is like virus. It needs to be attached to a host in order to function. During the attaching process of a fragment to a exactly specified host, the manifest files were logically merged if not conflicting and the dependencies are being resolved, if possible (if not possible, the fragment will just not be resolved and attached). After that, the resources in the fragments are loadable with the host ClassLoader, thus the Fragment does NEVER have its own ClassLoader (but its own ProtectionDomain if not an extension fragment, but we are not going there). Actually, there are quiet a few more things worth mentioning, but to understand what I am training to explain here, it should be fine. If something beyond that is needed, I am going to explain it as we go.

Now, that we know, what a Fragment is, what is it actually for where is the problem. Well, the purpose as described in the spec is pretty straight forward and logic. For customization of your bundle depending on the environment, often only very little, yet delicate changes are sometimes necessary. This can be a simple localization issue of your translations or the packaging of system dependant libraries like “dll”, “.so” or “.dmg” you are invoking in your bundle code. Depending on system properties like “os.name” or “lang” you can let the container decide, which bundles/fragments suit your environment - so far so good.

Now, where might be the problem with that? To motivate this, one has to keep in mind that one of the strengths of OSGi is its encapsulation model. Based on this declarative, strong and rigid component definition, OSGi became a very robust deployment format/ environment. A bundle or component is very expressive about its requirements and features, which makes it easy to handle them. Now, with Fragments attached to a host, the behavior of the host might change, without any changes of the version information within the bundle. The former strong formalism is now softened. Especially if you look into Software Product Lines, where you have thousands of bundles in many different versions, dynamically wired together, you can’t test every combination effectively; you have to be sure, that you can rely on a certain behavior, enforced by the component contract, which is in this case no longer possible.

Figure 1 - simple import Fragment attachedThe question is how a fragment potentially manages to violate the component contract. Concerning this question, there has been a discussion on the OSGi-Dev list this week. Just imagine you have a bundle X with three packages a, b and c. Fragment F defines one Import-Package: b. Another Bundle Z provides the package b as an export and has c internally available (see figure).

We further assume that bundle X defines in package a only a BundleActivater loading a class from package b. Now we have everything set, to begin our small example. Starting the bundle X (with the attached fragment F) will result in loading the BundleActivator. The activator then will try to load the class from package b. Depending on the OSGi class loading strategy, the class loader first looks into the import statements of the host, if there are no entries (like in our case), the fragment is queried for import statements. This time we’re successful and the ClassLoader is trying to obtain the class from another bundle. Here we have our problem. The behavior of X can be altered by providing another implementation of package b as an export of bundle Z in the container (it has to be a different bundle - import your exports in the fragment won’t work in that case). The problem here is not, that the package is replaced with an alternate implementation; this is pretty common in OSGi with the best practice of importing your exports. The crux here is that there is no statement of imports and the actual developer of the bundle might not have intended to replace the package at all.Figure 2 - Fragment replaces the a private package of a bundle

Of course this behavior has advantages as well. Consider you have a OSGi-efied bundle, which unfortunately isn’t converted perfectly, so you still have some Class.forName() calls in one minor package. The license however doesn’t allow you to touch the bundle at all, but now with the help of a fragment, you can inject your own code as described above. Not sure, if one really needs that, but you can.

Something else you can do with fragments is to emulate a global class space. I was actually working in on a project, where we had a pretty monolithic software in terms of the core DTOs. Although “Extensions” were easy exchangeable and loadable with different class loaders, the core data transfer objects were not, unless you serialize them, which of course was out of discussion. Now imagine, you have one core bundle, where every extension contributes its DTOs in form of a fragment, you end up with a global class space for all your DTOs. Nice on first glace, it becomes nasty soon, when you think about the implications. First of all, versioning is now only very limited available. Second, every new deployed fragment lets your whole application refresh, because everything depends on this core bundle and every fragment is attached to it - at least for me, no desirable solution.

The finish this (actually pretty long) post today, I can think of one last case, where it can help. Imagine, you have multiple versions of a package available and your bundle requires a distinct version, because of strange constraints, but can’t make these imports explicit, but dynamic with DynamicImport-Package, normally you don’t have a chance to provide a distinct version. With a fragment, you are able to inject a distinct version before the DynamicImport-Package definition is used in the class loading strategy.

However, I tried to show different ways of using fragments, besides the usual ones of providing translations or system dependant libraries. Everyone can of course do what ever he or she wants, but in my opinion, all these alternative usages are extremely dangerous and I can’t think of any sane reason to use them in real projects. Just because you can do something doesn’t mean it is go to do so. I gave it quiet a thought and I actually came to the conclusion, that the class loading behavior should be changed in a way that, no matter what happens, the bundle class path lookup should be performed entirely, before any attached fragment is asked. This would be a valid solution to prevent violations of the bundle contract in my opinion, but well… these are just my 2 cents. Take it or leave it :-)


Mirko

Share/Save/Bookmark

Java on the iPhone

After revealing details of the new SDK for the iPhone last Thursday, Sun decided to develop a JVM for the iPhone after Apple showed no intention to do so. Well, for some of you, this is not much of a deal. Java is available on many mobile phones, why care about one more or less? From my point of view, this makes a huge difference. OSGi, actually developed to improve the mobile sector and fight the short comings of J2ME, never really succeeded due to the lack of computing resources like memory or CPU power on former cell phones. With the iPhone, things might change.

(more…)

Share/Save/Bookmark