Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an OSGi Bundle from a Java Web Application in Tomcat

I am trying to invoke a method of an OSGi bundle from a Java Web Application. Both are supposed to run on Tomcat 7.

I already wrote a normal Java application that invokes methods from the OSGi bundle, as described on this site: http://drupal.osgibook.org/node/37.

To get the context of the Equinox environment I started it from the application and installed the bundles from within. Furthermore the context was used to retrieve a service reference of the running bundle and getting its service.

The runEquinox method of the EquinoxRunner class:

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

public BundleContext runEquinox([...]) throws Exception {
    [...]

    BundleContext bundleContext = EclipseStarter.startup(new String[]{"-console"}, null);
    bundleContext.installBundle("file:C:/.../plugins/myosgiclass.interface_1.0.0.201108301327.jar");
    Bundle bundleTranslationImpl =  bundleContext.installBundle("file:C:/.../plugins/myosgiclass.impl_1.0.0.201108301327.jar");
    bundleTranslationImpl.start();

    [...]
    return bundleContext;
}

and the invokeMethod of the ServiceRunner class:

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

[...]

public Object invokeMethod(BundleContext bundleContext, Object value, [...]){
    ServiceReference serviceReference = bundleContext.getServiceReference(MyOSGiClass.class.getName());
    Object result = null;
    if (serviceReference != null) {
        MyOSGiClass myOSGiClass = (MyOSGiClass) bundleContext.getService(serviceReference);
        if (myOSGiClass != null) result = myOSGiClass.method(value);
        bundleContext.ungetService(serviceReference);
    }
    return result;
}

Now, on Tomcat using the eclipse bridge, I don't know how to retrieve the right context of the Equinox environment. When I try running it on Tomcat with Equinox I get NoClassDefFound Exceptions. I would appreciate any advice on how to solve this problem.

Thanks a lot in advance. Cheers, Nic

like image 425
Nicolas Avatar asked Aug 31 '11 12:08

Nicolas


People also ask

Which is a difference between an OSGi bundle and a Java package?

The key difference with OSGi is that a JAR is now all private, adding metadata in the manifest makes it a bundle that can safely share with other bundles. OSGi makes sure violations are detected ahead of time. So, can a bundle be used in place of a jar in a JavaEE application? yes, it is a normal JAR.

What is the use of OSGi bundle?

OSGi facilitates creating and managing modular Java components (called bundles) that can be deployed in a container. As a developer, you use the OSGi specification and tools to create one or more bundles. OSGi defines the lifecycle for these bundles. It also hosts them and supports their interactions in a container.

What is an OSGi bundle?

OSGi is a Java framework for developing and deploying modular software programs and libraries. Each bundle is a tightly coupled, dynamically loadable collection of classes, jars, and configuration files that explicitly declare their external dependencies (if any).


2 Answers

When you embeds an OSGi framework like that and then want to access an OSGi service from the outer environment, you need to be sure that the service interface are the same inside and outside of OSGi.

So, configure your OSGi container to export the package of your service interface from Tomcat to OSGi. To achieve this, configure your OSGi framework with the 'FRAMEWORK_SYSTEMPACKAGES_EXTRA' property.

More info on http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html#ApacheFelixFrameworkLaunchingandEmbedding-hostservices (even if it's for Apache Felix, the embedding API is standardized).

like image 137
Clement Avatar answered Sep 28 '22 12:09

Clement


I have done this before using the EclipseStarter stuff with the bridge, and it was a lot of work to get the classpath stuff right which is the key. You also have to call EclipseStarter using reflection. It looks like they have standardized this since then so you don't need to use the EclipseStarter.

The key here (as briefly mentioned in the Felix article is that you have to have a shared classpath between your Tomcat environment and your OSGi environment. If you look in that article at the section starting with "Using Services Provided by Bundles", it seems to suggest what you want.

You will need to have an interface to what you are calling in your Tomcat (parent) classpath, and then you need to start the framework such that it uses your parent classpath first (which is likely not their launcher stuff works), and you need to exclude the bundle that provides the interface from the OSGi bundles. I accomplished this by making a separate OSGi bundle (the API bundle) that just had the interfaces, so when I wanted to use this setup in a context where my code was called from outside OSGi I would not provide that API bundle.

like image 20
Francis Upton IV Avatar answered Sep 28 '22 10:09

Francis Upton IV