3

I have a List of classes that implement the IApplication interface:

public interface IApplication {
    public void start();
}
public class Configurator implements IApplication {
    public void start() {...};
}

public static void main(String[] args) {
    List<IApplication> apps = new ArrayList<IApplication>();
    apps.add(new Configurator());

    apps.get(0).start(); //ClassCastException   
}

When the last line in my Main function is executed, I get a ClassCastException:

java.lang.ClassCastException: Configurator cannot be cast to IApplication

Even if I instantiate a Configurator object as an IApplication, I get the the following error:

IApplication app = new Configurator();
app.start();

java.lang.IncompatibleClassChangeError: Class Configurator does not implement the requested interface IApplication

Should this not be allowed in Java? Could it be an issue where my Configuration class is not getting updated correctly with the implementation?ClassCastException from a List of objects which implement a common interface

McLovin
  • 1,455
  • 3
  • 19
  • 37
  • IApplication vs. Application? Is that intended? – Dirk Lachowski Aug 05 '15 at 22:08
  • @DirkLachowski no it wasn't. Fixed now – McLovin Aug 05 '15 at 22:16
  • 2
    Did you forget to recompile Configurator after you made it implement IApplication? – user253751 Aug 05 '15 at 22:17
  • @immibis No, I ensured that I recompiled and re-deployed Configurator. I am using OSGi so perhaps there is an issue going on behind the scenes? – McLovin Aug 05 '15 at 22:19
  • 2
    possible duplicate of [can't cast to implemented interface](http://stackoverflow.com/questions/8035877/cant-cast-to-implemented-interface) – user253751 Aug 05 '15 at 22:22
  • What does `System.out.println(Arrays.toString(Configurator.class.getInterfaces())` print? What about `System.out.println(Arrays.asList(Configurator.class.getInterfaces()).stream().map(Class::getClassLoader).collect(Collectors.toList())+" "+IApplication.class.getClassLoader())`? – user253751 Aug 05 '15 at 22:26
  • @immibis that output gives me: `[interface com.common.IApplicationConfigurator]` && `[Class Provider for bundle with BSN: com.configurator-plugin] Class Provider for bundle with BSN: com.configuration-management-common` – McLovin Aug 05 '15 at 22:45
  • The output of this is `null`: System.out.println( apps.getClass().getInterfaces()[0].getClassLoader()); – McLovin Aug 05 '15 at 22:50
  • There's nothing wrong here. Please provide the block of code in the `start()` method implementation. Also, I'd fall back on the comment above about re-compiling, the error message does not jive: `java.lang.ClassCastException: Configurator cannot be cast to Application` Why would it try to cast to something called "Application" when it is an iApplication? – TechTrip Aug 05 '15 at 22:56
  • Try fully qualifying the class names with the package and see what happens. – TechTrip Aug 05 '15 at 23:09

1 Answers1

2

You seem to have two different interfaces loaded from different bundles, both named IApplication. In OSGI, classes (and interfaces, and enums, and so on) from different bundles are always distinct, even if they have the same name and package name!

Configurator implements the IApplication interface from the bundle com.configurator-plugin, whereas your main method is referring to the IApplication interface from the bundle com.configuration-management-common.

If they're supposed to be the same interface, you should remove it from one of those bundles, and make sure it's exported from the other, and make sure the bundle that exports the interface is a dependency of the bundle that uses it.

There's no simple way to specify which bundle to load a class or interfaces from, since the Java language has no concept of bundles to start with. If they're supposed to be two different interfaces, I suggest you make sure they have different names (and then the problem should be clear).

user253751
  • 57,427
  • 7
  • 48
  • 90