Wednesday, March 4, 2009

Buddy Classloading Equinox Osgi

Buddy class loading offers an integration strategy that does not require modifying the Java code of existing libraries(like hibernate) , thatuse the Class.forName(String) approach to dynamically discover and load classes.The mechanism works as follows:


A Bundle declares that it needs the help of other bundles to load classes The Bundle identifies the kind of help they need by specifying a buddy policy. The policy defines what kind of bundles will be considered to be buddies. When a bundle class loader fails to find a desired class through the normal OSGi delegation model (i.e. Import-Package, Require-Bundle, and local classpath), its buddy policy is invoked The invoked buddy policy discovers a set of buddies and consults each one in turn until either the class is found or the list is exhausted.

There are different buddy policies like registerd,global etc which can be mentioned in the manifest headers.


This buddy policy is spcific to equinox implementaion and may not be found in all Osgi implementataion.

The use cas eof this is each bundle need not mention an import and still can use the class of the bundle. Its use case is in packages like hibernate which do a class.forname on custom code .


http://wiki.eclipse.org/index.php/Context_Class_Loader_Enhancements

Fragment bundles in OSGi


Fragments are bundles that are attached to a host bundle by the Framework.Attaching is done as part of resolving: the Framework appends the relevantdefinitions of the fragment bundles to the host’s definitions before the hostis resolved. Fragments are therefore treated as part of the host, including any permitted headers.


These fragemnt bundles will not have a seperate class loader. these will belaoded by the same bundle class loader.For a bundle to be a fragment it has to mention fragment host in its manifest file.


This property of fragments can just be used for a logical seperation of classes , examples could be resource bundles which can be packed in to a seperate bundle.


Since these fragment bundles use the same class loader as the host bundlle there is no provision of seperately refreshing the fragment bundle

Ref : http://osgi.mjahn.net/2008/03/13/half-bundle-half-jar-%E2%80%93-the-nature-of-fragment-a-blessing-or-a-curse/

Bundles having same package structure for export :Require bundle Split packages

I was stuck in cases where i had two bundle having the same package structure and they wanted to share these classes.
Osgi just looks into only one of this package and then for any further requests it will look into this folder, if not found gives a class not found exception even though its present in the other bundle.
This case can be solved by using the concept of split packages.
The bundle which needs classes from multiple bundles having the same package structure should define those two bundles as Require-Bundle in its manifest headers in the order in which it should look for.
By doing so the environment ensures that both the bundles will be scanned one after the other to look for the requested classes.
Still i would prefer to refactor the jars than use this feature of require bundle.

Bundle Class Path - best way to start Osgi-Bundle Class PathIntra

bundle class path dependencies are declared in the Bundle-Classpathmanifest header. This declaration allows a bundle to declare its embedded class path using one or more JAR files or directories that are contained in the bundle’s JAR file.
This was the idle use case for me , where i converted only one jar into a bundle and gave all other jars in its bundle classpath.This gave me a flexibility where i needed to merge all the jars into one.
This will help as a starting point. All the class under the bundle classpath will be laoded by the single bundle classlaoder.
I tried the same with fragment bundles but with no luck , as it threw class not found exceptions in the cases which included RMi connections.

Order of search for a class in Osgi -> Resolving Process

1 If the class or resource is in a java.* package, the request is delegated tothe parent class loader; otherwise, the search continues with the nextstep. If the request is delegated to the parent class loader and the class orresource is not found, then the search terminates and the request fails.


2 If the class or resource is from a package included in the boot delegationlist (org.osgi.framework.bootdelegation), then the request is delegatedto the parent class loader. If the class or resource is found there, thesearch ends.


3 If the class or resource is in a package that is imported using Import-Package or was imported dynamically in a previous load, then therequest is delegated to the exporting bundle’s class loader; otherwise thesearch continues with the next step. If the request is delegated to anexporting class loader and the class or resource is not found, then thesearch terminates and the request fails.


4 If the class or resource is in a package that is imported from one or moreother bundles using Require-Bundle, the request is delegated to the classloaders of the other bundles, in the order in which they are specified inthis bundle’s manifest. This entails a depth-first strategy; all requiredbundles are searched before the bundle classpath is used. If the class orresource is not found, then the search continues with the next step.


5 The bundle’s own internal bundle class path is searched. If the class orresource is not found, then the search continues with the next step.


6 Each attached fragment’s internal bundle class path is searched. The fragmentsare searched in ascending bundle ID order. If the class or resourceis not found, then the search continues with the next step.


7 If the class or resource is in a package that is exported by the bundle orthe package is imported by the bundle (using Import-Package or Require-Bundle), then the search ends and the class or resource is not found.


8 Otherwise, if the class or resource is in a package that is imported usingDynamicImport-Package, then a dynamic import of the package is nowattempted. An exporter must conform to any implied package constraints.If an appropriate exporter is found, a wire is established so thatfuture loads of the package are handled in Step 3. If a dynamic wire is notestablished, then the request fails.


9 If the dynamic import of the package is established, the request is delegatedto the exporting bundle’s class loader. If the request is delegated toan exporting class loader and the class or resource is not found, then thesearch terminates and the request fails.

System packages and Extender packages in OSGi

The OSGi spec allows the Framework (through its system bundle) to export the relevant packages from its parent classloader as system packages using the org.osgi.framework.system.packages property.As repacking the hosting JDK as a bundle isn't a viable option, one can use this setting to have the system bundle (or the bundle with id 0) export these packages itself.


Extension Bundles :Another possible option is to enhance the system bundle through extension bundles. These act as fragments;they are not bundles of their own but rather are attached to a host. Once attached, the fragment content (including any permitted headers) is treated as part of the host. Extension bundles are a special kind of fragments that get attached only to the Systembundle in order to deliver optional parts of the Framework (such as the Start Level service).


The System package entry is added using org.osgi.framework.system.packages = \ i
n java6-server.profile in the lib directory of the dm server


In both the above cases the classes are loaded by the bootclassloader and not a seperate bundle classloader.Hence these are candidates when we are considering putting classes at the boot class path.

ref:http://blog.springsource.com/2009/01/19/exposing-the-boot-classpath-in-osgi/.

Class.forname and classloader.loadclass - whats bettr in OSGi

ClassLoader.loadClass or Class.forName seem to be synonyms for the same basic operation:
but class.forname does additional constraint checks which can cause some problems in the context of OSGi.So it does seem reasonable to have Class.forName behavior altered to avoid loader constraint checks.
However, if Class.forName is used to call the initiating class loader, the behavior with respect to cachinga nd the returned class is quite different. In this case, when the class is first defined, it is cached by the defining class loader as expected. But it is also cached by the initiating class loader which is not expected.
As a result, all calls to Class.forName to a initiating class loader always return the same class object (thefirst one loaded), even if the implementation of the initiating class loader does not define classes or directlyconsult its own cache.
My case where class.forname didnt wrk and classloader.loadclass worked
Scenario:
Bundle A->class AA, extends Server,calls init

class ToBeLoaded ,exports ToBeLoaded
Bundle B->class Server, method init()->tries to load class ToBeLoaded

Ref : http://blog.bjhargrave.com/2007/07/why-do-classforname-and.html
http://blog.bjhargrave.com/2007/09/classforname-caches-defined-class-in.html

http://www.jroller.com/navanee/entry/difference_between_class_forname_and

 
Free Domain Names @ .co.nr!