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 > >