Ouertani Slim was born in Tunisia in 1981. Now he is a software engineer since 2004 and he is Java 6 and Spring certified with 100% and 94% respectively. He is very interested in Java technology, Scala and open source projects. He believes that programming is one of the hardest jobs and most beautiful in the world. Slim has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

Enterprise Libraries and OSGI

08.26.2008
| 7357 views |
  • submit to reddit
I will try here to explain why some enterprise libraries don't work with the OSGi concept. For this reason, I will create a simple Java library and client bundle to use it.

We start with the library, responsible for loading properties files. It contains one abstract class named ALoader with one static final method getResourceBundle that returns a ResourceBundle.
package com.jtunisie.osgi.load;

import java.util.ResourceBundle;

public abstract class ALoader {
public static final ResourceBundle getResourceBundle(String ressource){
return java.util.ResourceBundle.getBundle(ressource);
}
}

This class should work fine with a simple Java application.
Starting our client, we create one class named LibCustomer with three methods :

package com.jtunisie.osgi.loader.client.impl;

import com.jtunisie.osgi.loader.client.ILoader;
import com.jtunisie.osgi.loader.lib.ALoader;

public class LibCustomer extends ALoader implements ILoader {

@Override
public String getNameFromLib() {
return getResourceBundle("loader").getString("contry");
}
@Override
public String getNameFromLocale() {
return java.util.ResourceBundle.getBundle("loader").getString("contry");
}



public void init(){
System.out.println("local contry name : "+ getNameFromLocale());
System.out.println("lib contry name : "+getNameFromLib());
}

}

 

The init method will be called by Spring DM as the default init method.

Note that we have to add loader.properties file to src root file that contains one property :

contry=tunisie

Using maven to generate the two bundles we will get the following nested exception:

java.util.MissingResourceException: Can't find bundle for base name loader, locale en_US.

This means that library can't load properties file because it isn't visible. Why ?

In fact, the class loader concept isn't the same as a simple Java application - the tree concept isn't available here. The client bundle must import the library package otherwise the library is independent of client and it can't see resource file.

Many libraries such as hibernate, JPA and JAXB use the same thing with the class forName concept to load class with reflection, and due to invisibility of client to such libraries, the ClassNotFound exception is thrown.


OSGi R 4.1 isn't clear about this point, and some workaround is given by the Eclipse Equinox implementation. Let us adding a second chance to find resource file :

We mention that our library is Eclipse-BuddyPolicy registered which helps to find resource on the registered bundle. Our client will register by adding Eclipse-RegisterBuddy: com.jtunisie.osgi.loader.lib property.

If the OSGi class loader cycle fails to find the resource, our library will try to delegate the class loader to registered bundle wich is our client. Now if we try our client both methods work fine.

Conclusion


This is a brief introduction about the recurrent problem found when using external jars, and we need to take care about class loader before working with OSGi concept. It isn't as easy as a simple Java application but with some practice we can detect the source of ClassNotFoundExceptions - the workaround isn't always evident.


Source is available here :

svn checkout http://osgienterpriselibs.googlecode.com/svn/trunk/ osgienterpriselibs-read-only 

 

Published at DZone with permission of its author, Slim Ouertani.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)