Find Classloader for a given OSGi-Bundle or Having fun with FXML in OSGi


So this is something I wanted serval times already and now since Equinox 3.7 it is available. You get get the classloader used by bundle very simple.

My use case is that I have to pass an none OSGi-Aware lib (in my case JavaFX) the correct classloader when it creates instances using reflection. In my e(fx)clipse runtime I’d like to have support for loading FXML-Files when specified in the Application.e4xmi. Loading the FXML file from an external bundle is not a problem because one can pass it an URL.

The problem is that FXML files allow users to reference external classes like e.g. a controller instance and now in my case the class executing the loading is not the one that holds the controller and FXML loading fails. The only possibility to make this work is to temporarily change the context-classloader while the loading happens and reset it to once done so.

My problem is that at the position the FXML-Loading happens I have only 2 informations:

  • Bundle-Id
  • Bundle Relative FXML-File

So there’s the solution:

String bundleId = // ....
String fxmlFile = // ....

Bundle b = org.eclipse.core.runtime.Platform.getBundle(bundleId);
URL url = bundle.getResource(fxmlFile);

// This the important line and available since Equinox 3.7
ClassLoader loader = bundle.adapt(BundleWiring.class).getClassLoader();
ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
try {
  Thread.currentThread().setContextClassLoader(loader);
  // Load the fxml-File
} finally {
  Thread.currentThread().setContextClassLoader(originalLoader);
}

The better solution would be if the FXMLLoader would allow to pass a delegate which does the classloading and instantiation (this would the make DI-Frameworks useable as well) but until then e(fx)clipse will provide you helpers so that you don’t have to remember deal with such things in your OSGi-enabled JavaFX applications

Advertisements
This entry was posted in e(fx)clipse, Eclipse. Bookmark the permalink.

3 Responses to Find Classloader for a given OSGi-Bundle or Having fun with FXML in OSGi

  1. SeB says:

    I guess you meant,

    try {
    Thread.currentThread().setContextClassLoader(loader);

    instead of

    try {
    Thread.currentThread().setContextClassLoader(classloader);

    loader instead of classloader.

    • Tom Schindl says:

      Ups you are right – I had edited the code a bit when I copied it from I orginal sources a have introduced this error

  2. Pingback: e(fx)clipse 0.0.7 released | Tomsondev Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s