felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Felix Meschberger <fmesc...@adobe.com>
Subject Re: a question of Declarative Service specification
Date Fri, 17 Feb 2012 13:31:25 GMT
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 <fmeschbe@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
>> 
>> 


Mime
View raw message