[ https://issues.apache.org/jira/browse/FELIX-3090?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13093256#comment-13093256
]
Pierre De Rop commented on FELIX-3090:
--------------------------------------
But isn't it difficult to define the reference as optional ?
I mean for instance, if the factory component has many required dependencies and also provides
a service,
then this service might be registered when another component invokes newInstance...
So the registered service might be used while the required dependencies are not there.
Another point that is troubling me is that in the spec, chapter 112.5.5 (Factory Component),
it is stated the following:
"SCR must register a Component Factory service as soon as the component factory
becomes satisfied. The component factory is satisfied when the following
conditions are all satisfied:
• The component is enabled.
• Using the component properties specified by the component
description, all the component’s references are satisfied. A reference is
satisfied when the reference specifies optional cardinality or there is at
least one target service for the reference"
So, I don't understand why the component factory is currently registered, even if a reference
filter is not satisfied ?
For clarity, I have joined to this issue a maven sample code (sample.tgz), which illustrates
what I'm talking about:
- I have made a factory component "A", which depends on service "B" with target filter "(foo=B2)".
- I then have "AFactory" which tracks the "A" ComponentFactory.
This component will instantiate "A" when the component factory is injected.
- I then have two component "B1" which implements B(foo=B1), and "B2" which implements B(foo=B2).
Both B1 and B2 are disabled.
So, when running the framework, go the webconsole/component.
At this point, "A" and "AFactory" are both unsatisfied (because we don't have any B services).
Now, enable B1 -> this will trigger the A's component factory registration, and AFactory
will then catch it and will invoke
newInstance. However, because A required B2 (not B1), then the newInstance will throw:
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:17)
...
Finally; enable "B2" from webconsole: this will have no effect, and in the end, the "AFactory"
won't ever be able to instantiate "A".
So, am I making sense with this ? or am I missing something else ?
Thanks for your help.
> SCR factory components ignore reference target filters
> ------------------------------------------------------
>
> Key: FELIX-3090
> URL: https://issues.apache.org/jira/browse/FELIX-3090
> Project: Felix
> Issue Type: Bug
> Components: Declarative Services (SCR)
> Affects Versions: scr-1.6.0
> Reporter: Pierre De Rop
> Assignee: Felix Meschberger
>
> This issue is described in the following post:
> http://www.mail-archive.com/users@felix.apache.org/msg10925.html
> Basically, when a component is declaring a factory (in order to register a ComponentFactory
in the registry),
> then any extra Reference' target filters are not taken into acount.
> This is a problem because the ComponentFactory is registered in the registry even if
some References are not satisfied.
> Consider the following example (It uses the BND SCR annotations):
> @Component(factory = "AFactory")
> public class A {
> @Reference(name="YDependency", target = "(name=Z)")
> void bind(Y y) {
> System.out.println("A.bind(" + y + ")");
> }
> @Activate
> void start() {
> System.out.println("A.start");
> }
> }
> public interface Y {
> }
> @Component(properties = { "name=ZZZZZ" })
> public class YImpl implements Y {
> }
> @Component
> public class AFactory {
> @Reference(target = "(component.factory=AFactory)")
> void bind(ComponentFactory AFactory) {
> System.out.println("AFactory.bind(" + AFactory + ")");
> try {
> ComponentInstance ci = AFactory.newInstance(null);
> A a = (A) ci.getInstance();
> System.out.println("Created " + a);
> }
> catch (Throwable t) {
> t.printStackTrace();
> }
> }
> }
> Here, the "YDependency" Reference of the "A" component is not satisfied, but the ComponentFactory
for the
> "A" component is somehow registered, and when the "AFactory" component catches it, then
it get the following exception,
> when trying to instantiate the "A" component instance:
> 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$1(BaseMethod.java:219)
> at org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:591)
> at org.apache.felix.scr.impl.helper.BaseMethod$NotResolved.invoke(BaseMethod.java:548)
> at org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:472)
> 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:1013)
> at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:333)
> at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:157)
> at org.apache.felix.scr.impl.config.ImmediateComponentHolder.enableComponents(ImmediateComponentHolder.java:313)
> at org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:253)
> 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:807)
> at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:729)
> at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:610)
> at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:3879)
> at org.apache.felix.framework.Felix.startBundle(Felix.java:1850)
> at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1192)
> at org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:266)
> at java.lang.Thread.run(Thread.java:662)
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira