ops4j / org.ops4j.pax.cdi

Contexts and Dependency Injection for OSGi
Apache License 2.0
34 stars 26 forks source link

@OsgiServiceProvider: ClassCastException with parameterized service types [PAXCDI-164] #123

Open ops4j-issues opened 9 years ago

ops4j-issues commented 9 years ago

Florian Brunner created PAXCDI-164

@OsgiServiceProvider should support services implementing parameterized interfaces:

@OsgiServiceProvider
public class SomeServiceImpl implements SomeService<SomeType> {

The current exception is:

java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager.getTypeNamesForBeanTypes(ComponentLifecycleManager.java:215)
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager.registerService(ComponentLifecycleManager.java:184)
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager.start(ComponentLifecycleManager.java:107)
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager$Proxy$_$$_WeldClientProxy.start(Unknown Source)
    at org.ops4j.pax.cdi.extension.impl.BeanBundleImpl.onInitialized(BeanBundleImpl.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:89)
    at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:79)
    at org.jboss.weld.injection.ObserverMethodInvocationStrategy$2.notify(ObserverMethodInvocationStrategy.java:89)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:299)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:284)
    at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:262)
    at org.jboss.weld.event.ObserverNotifier.notifySyncObservers(ObserverNotifier.java:217)
    at org.jboss.weld.event.ObserverNotifier.notify(ObserverNotifier.java:204)
    at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:120)
    at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:110)
    at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:675)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer$1.call(AbstractCdiContainer.java:155)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer$1.call(AbstractCdiContainer.java:147)
    at org.ops4j.pax.swissbox.core.ContextClassLoaderUtils.doWithClassLoader(ContextClassLoaderUtils.java:60)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer.finishStartup(AbstractCdiContainer.java:146)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer.start(AbstractCdiContainer.java:91)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.createContainer(CdiExtender.java:152)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.addingBundle(CdiExtender.java:106)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.addingBundle(CdiExtender.java:53)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:469)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:415)
    at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
    at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:183)
    at org.osgi.util.tracker.BundleTracker.open(BundleTracker.java:156)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.activate(CdiExtender.java:79)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.felix.scr.impl.helper.BaseMethod.invokeMethod(BaseMethod.java:231)
    at org.apache.felix.scr.impl.helper.BaseMethod.access$500(BaseMethod.java:39)
    at org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:624)
    at org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:508)
    at org.apache.felix.scr.impl.helper.ActivateMethod.invoke(ActivateMethod.java:149)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:315)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:127)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:871)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:838)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:850)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:931)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:895)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1480)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1401)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.trackAdding(ServiceTracker.java:1210)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.track(ServiceTracker.java:1148)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:1432)
    at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:987)
    at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:838)
    at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:545)
    at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4547)
    at org.apache.felix.framework.Felix.registerService(Felix.java:3521)
    at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:350)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:1003)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:992)
    at org.apache.felix.scr.impl.manager.RegistrationManager.changeRegistration(RegistrationManager.java:134)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:1044)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:841)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:419)
    at org.apache.felix.scr.impl.config.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:376)
    at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:172)
    at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
    at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
    at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
    at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
    at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
    at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:479)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:414)
    at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
    at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:443)
    at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:913)
    at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:834)
    at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:516)
    at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4531)
    at org.apache.felix.framework.Felix.startBundle(Felix.java:2169)
    at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1368)
    at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
    at java.lang.Thread.run(Thread.java:745)

ERROR: org.ops4j.pax.cdi.extender (39): [org.ops4j.pax.cdi.extender.impl.CdiExtender(33)] The activate method has thrown an exception
org.ops4j.lang.Ops4jException: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer.finishStartup(AbstractCdiContainer.java:178)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer.start(AbstractCdiContainer.java:91)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.createContainer(CdiExtender.java:152)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.addingBundle(CdiExtender.java:106)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.addingBundle(CdiExtender.java:53)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:469)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:415)
    at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
    at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:183)
    at org.osgi.util.tracker.BundleTracker.open(BundleTracker.java:156)
    at org.ops4j.pax.cdi.extender.impl.CdiExtender.activate(CdiExtender.java:79)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.felix.scr.impl.helper.BaseMethod.invokeMethod(BaseMethod.java:231)
    at org.apache.felix.scr.impl.helper.BaseMethod.access$500(BaseMethod.java:39)
    at org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:624)
    at org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:508)
    at org.apache.felix.scr.impl.helper.ActivateMethod.invoke(ActivateMethod.java:149)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:315)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:127)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:871)
    at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:838)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:850)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:931)
    at org.apache.felix.scr.impl.manager.DependencyManager$SingleStaticCustomizer.addedService(DependencyManager.java:895)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1480)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1401)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.trackAdding(ServiceTracker.java:1210)
    at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.track(ServiceTracker.java:1148)
    at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:1432)
    at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:987)
    at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:838)
    at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:545)
    at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4547)
    at org.apache.felix.framework.Felix.registerService(Felix.java:3521)
    at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:350)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:1003)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:992)
    at org.apache.felix.scr.impl.manager.RegistrationManager.changeRegistration(RegistrationManager.java:134)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:1044)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:841)
    at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:419)
    at org.apache.felix.scr.impl.config.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:376)
    at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:172)
    at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
    at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
    at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
    at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
    at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
    at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:479)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:414)
    at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
    at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:443)
    at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:913)
    at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:834)
    at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:516)
    at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4531)
    at org.apache.felix.framework.Felix.startBundle(Felix.java:2169)
    at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1368)
    at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager.getTypeNamesForBeanTypes(ComponentLifecycleManager.java:215)
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager.registerService(ComponentLifecycleManager.java:184)
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager.start(ComponentLifecycleManager.java:107)
    at org.ops4j.pax.cdi.extension.impl.component.ComponentLifecycleManager$Proxy$_$$_WeldClientProxy.start(Unknown Source)
    at org.ops4j.pax.cdi.extension.impl.BeanBundleImpl.onInitialized(BeanBundleImpl.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:89)
    at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:79)
    at org.jboss.weld.injection.ObserverMethodInvocationStrategy$2.notify(ObserverMethodInvocationStrategy.java:89)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:299)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:284)
    at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:262)
    at org.jboss.weld.event.ObserverNotifier.notifySyncObservers(ObserverNotifier.java:217)
    at org.jboss.weld.event.ObserverNotifier.notify(ObserverNotifier.java:204)
    at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:120)
    at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:110)
    at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:675)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer$1.call(AbstractCdiContainer.java:155)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer$1.call(AbstractCdiContainer.java:147)
    at org.ops4j.pax.swissbox.core.ContextClassLoaderUtils.doWithClassLoader(ContextClassLoaderUtils.java:60)
    at org.ops4j.pax.cdi.spi.AbstractCdiContainer.finishStartup(AbstractCdiContainer.java:146)
    ... 63 more

Affects: 0.11.0 Fixed in: 1.1.4 Votes: 0, Watches: 2

ops4j-issues commented 9 years ago

Florian Brunner commented

I'm working on this issue here: https://github.com/puce77/org.ops4j.pax.cdi/tree/PAXCDI-164-OsgiServiceProvider-Support-ParameterizedType

ops4j-issues commented 9 years ago

Florian Brunner commented

A pull request fixing this issue is available here: https://github.com/ops4j/org.ops4j.pax.cdi/pull/16

ops4j-issues commented 9 years ago

Harald Wellmann commented

I can't merge the pull request without tests.

Besides, it seems you only addressed the producer side which is easy. The consumer side is a bit harder, i.e. making sure that this works:

@Inject
@OsgiService
private SomeService<SomeType> myService;
ops4j-issues commented 9 years ago

Florian Brunner commented

I've provided the tests (including consumer side): https://github.com/ops4j/org.ops4j.pax.cdi/pull/16/files

ops4j-issues commented 9 years ago

Harald Wellmann commented

Yes, there is a test, but this is nowhere near the required coverage.

Take a look at
http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#assignable_parameters

How would you deal with this:

@OsgiServiceProvider
public class MyServiceImpl<Foo> implements MyService<Foo> {...}

@OsgiServiceProvider
public class MyServiceImpl<Foo> implements MyService<Bar> {...}

@Inject
@OsgiService
private MyService ip1;

@Inject
@OsgiService
private MyService<Object> ip2;

@Inject
@OsgiService
private MyService<Foo> ip3;

@Inject
@OsgiService
private MyService<Bar> ip4;

What about parameterized parameters, e.g. MyService<Map<Foo, List<String>>>?

Moreover, according to http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#managed_beans

If the managed bean class is a generic type, it must have scope @Dependent. If a managed bean with a parameterized bean class declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.

Since OSGi service beans have one of the OSGi scopes @SingletonScope, @BundleScoped or @PrototypeScope, parameterized OSGi service beans would be a logical contradiction.

ops4j-issues commented 9 years ago

Florian Brunner commented

This issue addresses one concrete ClassCastException. There might be a need for follow-up issues to reach full CDI conformity, but the current behavior (ClassCastException) is surely wrong and this patch solves this issue.

I have a concrete need for this: https://github.com/Drombler/drombler-fx/blob/%2337-cdi/drombler-fx-core-docking/src/main/java/org/drombler/fx/core/docking/impl/FXDockableFactory.java

Applying this patch solves the issue without having to fall back to raw types and thus improves the current state of PAX-CDI.

The test and the sample prove this.

ops4j-issues commented 9 years ago

Florian Brunner commented

I've changed the title of this issue to make it more clear.