Hi, Am 17.02.2012 um 15:25 schrieb Pierre De Rop:
> Thank you Felix, I tested the fix and it's working fine. Cool. Thanks for the feedback, > > PS: will you close the issue, or should I ? I will close it once I cut the release. Regards Felix > > regards; > /Pierre > > On Fri, Feb 17, 2012 at 2:31 PM, Felix Meschberger <fmesc...@adobe.com>wrote: > >> Hi Pierre >> >> I committed a fix, if you like to check. Thanks. >> >> Regards >> Felix >> >> Am 17.02.2012 um 12:40 schrieb Pierre De Rop: >> >>> Hi Felix, >>> >>> Thanks a lot for reopening this issue. >>> >>> kind regards; >>> /Pierre >>> >>> On Fri, Feb 17, 2012 at 12:26 PM, Felix Meschberger <fmesc...@adobe.com >>> wrote: >>> >>>> Hi Pierre, >>>> >>>> Thanks for insisting ... >>>> >>>> I revert my earlier opinion and now think you are right: The >> satisfaction >>>> of the ComponentFactory service must include the target properties. >>>> >>>> The newInstance method may be provided with different target property >>>> values and cause the desired instance to not be satisfiable and thus >> fail. >>>> >>>> I have reopened the issue and will reconsider your patch. >>>> >>>> Regards >>>> Felix >>>> >>>> Am 16.02.2012 um 16:10 schrieb Pierre De Rop: >>>> >>>>> Hi everyone, >>>>> >>>>> This post is about a question regarding SCR and especially about SCR >>>>> Component Factory: >>>>> >>>>> When a component A is defined with a factory attribute, then SCR is >>>>> intended to register an org.osgi.service.component.ComponentFactory >>>> inside >>>>> the registry, in order to allow another component to be injected with >>>> that >>>>> ComponentFactory. This way, some other components may programatically >>>>> instantiate one (or several instances) of the component A. >>>>> >>>>> The question is: should the ComponentFactory be registered only once >> the >>>> A >>>>> component is satisfied >>>>> (that is: after all A required dependencies are available) ? >>>>> >>>>> I guess yes, because in DS spec, (112.2.4), it is stated the following: >>>>> >>>>> "... SCR must register a Component Factory service on behalf of the >>>>> component >>>>> as soon as the component factory is satisfied." >>>>> >>>>> I ask this question because I'm facing the following issue: >>>>> >>>>> I have a component A, which depends on B1(property=b2) like this: >>>>> >>>>> public interface B { >>>>> } >>>>> >>>>> @Component(factory = "A") >>>>> public class A /* implements something which required B2 */ { >>>>> @Reference(target = "(property=b2)") >>>>> void bind(B b, Map<?, ?> properties) { >>>>> System.out.println("A.bind(b=" + b + ", properties=" + properties >>>> + >>>>> ")"); >>>>> } >>>>> >>>>> @Activate >>>>> void start() { >>>>> System.out.println("A.start"); >>>>> } >>>>> } >>>>> >>>>> And here is the component which is in charge of instantiating A: >>>>> >>>>> @Component >>>>> public class AFactory { >>>>> @Reference(target = "(component.factory=A)") >>>>> void bind(ComponentFactory aFactory) { >>>>> System.out.println("AFactory: bound aFactory=" + aFactory); >>>>> try { >>>>> ComponentInstance ci = aFactory.newInstance(null); >>>>> A a = (A) ci.getInstance(); >>>>> System.out.println("AFactory: created instance of a: " + a); >>>>> } >>>>> catch (Throwable t) { >>>>> t.printStackTrace(); >>>>> } >>>>> } >>>>> } >>>>> >>>>> Now, I have B1, defined like this: >>>>> >>>>> @Component(properties = { "property=b1" }) >>>>> public class B1 implements B { >>>>> } >>>>> >>>>> and I then have B2 (which is the one required by A): >>>>> >>>>> @Component(enabled=false, properties = { "property=b2" }) >>>>> public class B2 implements B { >>>>> } >>>>> >>>>> Here, B2 is declared with "enabled=false", meaning that the component >> B2 >>>> is >>>>> not activated by default, at startup time. >>>>> So, B2 is meant to be manually enabled from web console. >>>>> >>>>> So, what I expect is the following: >>>>> >>>>> 1) When B2 is enabled from web console (using the "Component" menu), >> then >>>>> B2 is registered in the registry. >>>>> 2) At this point, I expect A to become satisfied, because A is >> depending >>>> of >>>>> service B2 (with property=b2). >>>>> 3) Then I expect the ComponentFactory of A to be registered in the OSGi >>>>> registry. >>>>> 4) Finally, AFactory is activated, and then instantiates A (using the >>>>> injected A ComponentFactory). >>>>> >>>>> The problem is that when I start the framework, it seems that the >>>> AFactory >>>>> component is immediately registered >>>>> with the ComponentFactory of A, while at this point A is not yet >>>> satisfied >>>>> (because at startup, only B1 is available, and >>>>> B2 is not yet available). So when AFactory instantiates A (using >>>>> ComponentFactory.newInstance), I then get the exception: >>>>> >>>>> g! AFactory: bound aFactory=Component: test.scr.factory.A (1) >>>>> org.osgi.service.component.ComponentException: Failed activating >>>> component >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.ComponentFactoryImpl.newInstance(ComponentFactoryImpl.java:120) >>>>> at test.scr.factory.AFactory.bind(AFactory.java:15) >>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >>>>> at >>>>> >>>> >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) >>>>> at >>>>> >>>> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) >>>>> at java.lang.reflect.Method.invoke(Method.java:597) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.helper.BaseMethod.invokeMethod(BaseMethod.java:227) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.helper.BaseMethod.access$500(BaseMethod.java:38) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:595) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.helper.BaseMethod$NotResolved.invoke(BaseMethod.java:552) >>>>> at >>>>> org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:476) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.invokeBindMethod(DependencyManager.java:1028) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.bind(DependencyManager.java:944) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.open(DependencyManager.java:868) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.ImmediateComponentManager.createImplementationObject(ImmediateComponentManager.java:200) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.ImmediateComponentManager.createComponent(ImmediateComponentManager.java:118) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:1140) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:334) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.serviceAdded(DependencyManager.java:283) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.serviceChanged(DependencyManager.java:170) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:932) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:793) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:543) >>>>> at >>>>> org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4260) >>>>> at >>>> org.apache.felix.framework.Felix.registerService(Felix.java:3275) >>>>> at >>>>> >>>> >> org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:346) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.ComponentFactoryImpl.registerService(ComponentFactoryImpl.java:173) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.registerComponentService(AbstractComponentManager.java:508) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:1157) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:334) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.serviceAdded(DependencyManager.java:283) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.DependencyManager.serviceChanged(DependencyManager.java:170) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:932) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:793) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:543) >>>>> at >>>>> org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4260) >>>>> at >>>> org.apache.felix.framework.Felix.registerService(Felix.java:3275) >>>>> at >>>>> >>>> >> org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:346) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:456) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.registerComponentService(AbstractComponentManager.java:508) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:1157) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:334) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:158) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.config.ImmediateComponentHolder.enableComponents(ImmediateComponentHolder.java:313) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:241) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:147) >>>>> at >>>>> >>>> >> org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:111) >>>>> at >>>>> org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:274) >>>>> at >>>>> org.apache.felix.scr.impl.Activator.bundleChanged(Activator.java:192) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:868) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:789) >>>>> at >>>>> >>>> >> org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:514) >>>>> at >>>> org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4244) >>>>> at org.apache.felix.framework.Felix.startBundle(Felix.java:1923) >>>>> at >>>>> org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1191) >>>>> at >>>>> >>>> >> org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:295) >>>>> at java.lang.Thread.run(Thread.java:662) >>>>> >>>>> And after I enable B2 from webconsole, then nothing happens, and >> AFactory >>>>> is not injected with the A Component Factory anymore. >>>>> >>>>> Am I making sense with all this ? Is there really an issue in SCR to be >>>>> reported in jira ? >>>>> (I reported this in an old issue FELIX-3090 which is currently closed, >>>> but >>>>> I still feel there is something to it). >>>>> >>>>> thanks for your help; >>>>> >>>>> /pierre >>>> >>>> >> >>