Search code examples
javaosgiclasscastexceptionapache-felixosgi-bundle

ClassCastException while getting the service that has been registered in OSGi


I have recently starting working on OSGi framework. Below are the classes I have in my TestingBundle jar. Below is my Activator class for that Bundle.

public class Activator implements BundleActivator {

    private ServiceRegistration registration;

    @Override
    public void start(BundleContext context) throws Exception {

        registration = context.registerService(ITestFramework.class.getName(), new TestModelFramework(), null);

    }

    @Override
    public void stop(BundleContext context) throws Exception {


    }
}

Below is the interface.

public interface ITestFramework {

    public void speak();

}

Below is the class that is implementing the above Interface

public class TestModelFramework implements ITestFramework {

    public TestModelFramework() {
    //
    }

    @Override
    public void speak() {

    System.out.println("Hello World");

    }

}

Below is my main application code which will install the above bundle and then make a call to the above Service-

private static Framework framework = null;

static {
    try {
        FileUtils.deleteDirectory(new File("felix-cache"));
        FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();

        framework = frameworkFactory.newFramework(new HashMap<String, String>());
        framework.start();
    } catch (IOException e) {
        LOG.log(Level.SEVERE, "Exception in App::static block " +e);
    } catch (BundleException e) {
        LOG.log(Level.SEVERE, "Exception in App::static block " +e);
    }       
}

public App() {

    installTheBundles(); //this method will install and start my above bundle
    initializeModel();
}

private static void initializeModel() {

    try {

    ServiceReference serviceReference = framework.getBundleContext().getServiceReference(ITestFramework.class.getName());

// this line throws me an exception         
TestModelFramework service = (TestModelFramework) framework.getBundleContext().getService(serviceReference);

    service.speak();

    } catch (Exception e) {
        LOG.log(Level.SEVERE, "Exception in App::initializeModel " +e);
        e.printStackTrace();
    }
}

}

Below is the exception I always get-

SEVERE: Exception in App::initializeModel java.lang.ClassCastException: com.host.domain.app.modelling.framework.TestModelFramework incompatible with com.host.domain.app.modelling.framework.IModellingFramework

I am not sure what wrong I am doing here? Can anybody explain me what wrong I have done here?


Solution

  • The interface package, i.e. com.host.domain.app.modelling.framework must be exported by only one bundle. All other bundles that use that package should import it, rather than contain their own copy of it.

    The explanation for this is that, in Java, the identity of a class is defined by the fully-qualified name of that class and the ClassLoader that loaded it. If you load the interface from multiple bundles (and therefore multiple ClassLoaders) then each copy of the interface will be treated as different, incompatible interfaces.