I think that the most concise way to get what you want while still using DS is to use configuration to control the wiring.
Each of the tagged services should set a target filter for the reference that they want injected. This can be set using Config Admin, or just using the reference annotation: @Component(property = "tag = vanilla", immediate = true) public class C { @Reference(target="(tag=vanilla)" B b; } The injected services should then be created using Configuration Admin factory configurations, and setting the scope of anything that they use to prototype or prototype_required. @Component(configurationPid="foo", configurationPolicy=REQUIRED) public class B { @Reference(scope=PROTOTYPE) D d; } With the factory configuration for foo setting tag = vanilla. If you also need separate instances of D injected for each B then define them as prototype scope services. @Component(scope=PROTOTYPE) public class D { } You will now have a vanilla tagged C injected with a vanilla instance of B injected with its own instance of D. I hope this helps, despite the phone formatting! Tim Sent from my iPhone > On 14 Jul 2017, at 20:50, BJ Hargrave <hargr...@us.ibm.com> wrote: > > If you need to create unique component instances with specific service > property values, then you would need to use ComponentFactory. However, then > your components would need to reference the proper ComponentFactory and call > it to create the desired instance. > > @Component(factory="B") > public class B > { > private @Reference D d; > } > > @Component(property = "tag = chocolate", immediate = true) > public class A > { > private B b; > private ComponentContext cc; > @Activate > private void activate(ComponentContext context) { > cc = context; > } > @Reference(target="(component.factory=B)") > private void bFactory(ComponentFactory f) { > Dictionary<String,String> props = new HashMap<>(); > props.put("tag", cc.getProperties().get("tag")); > b = f.newInstance(props); > } > } > > This creates a new instance of B for each instance of A. You may not want > this. > -- > > BJ Hargrave > Senior Technical Staff Member, IBM // office: +1 386 848 1781 > OSGi Fellow and CTO of the OSGi Alliance // mobile: +1 386 848 3788 > hargr...@us.ibm.com > > > ----- Original message ----- > From: Mark Raynsford <list+org.o...@io7m.com> > Sent by: osgi-dev-boun...@mail.osgi.org > To: osgi-dev@mail.osgi.org > Cc: > Subject: [osgi-dev] Grouping services instantiated by Declarative Services > Date: Fri, Jul 14, 2017 3:04 PM > > Hello. > > I have a somewhat unusual problem that would be rather laborious to > explain here. In order to preserve the sanity of those reading this > email, I'll try to distill it down to something more abstract. > > I have a situation where I want to instantiate a tree of services, each > of which share a common "tag" property. When a service A declares a > reference to another service B, the exact instance of B that is used > depends on the value of the tag property on A. This needs to work > transitively. > > To try to illustrate what I mean, a contrived (and obviously > non-working example): > > @Component > public class D > { > > } > > @Component > public class B > { > private @Reference D d; > } > > @Component(property = "tag = chocolate", immediate = true) > public class A > { > private @Reference B b; > } > > @Component(property = "tag = vanilla", immediate = true) > public class C > { > private @Reference B b; > } > > @Component(property = "tag = vanilla", immediate = true) > public class E > { > private @Reference D d; > } > > The A, C, and E components are the "root" components in this example, > and the value of the "tag" property will define which specific > instances of D and B get referenced. For example, assuming an OSGi > system that magically implemented what I'm trying to do, the above > arrangement would produce a tree of instances like the following: > > http://ataxia.io7m.com/2017/07/14/groups.svg.png > > The process would probably go something like this: > > The A component has a "chocolate" tag and refers to B. The system > instantiates a new B with tag "chocolate" (because there isn't an > existing one) and returns a reference to it. The same occurs with D > for the reference in B. > > The C component has a "vanilla" tag and refers to B. The existing > instance of B with tag "chocolate" is ignored and a new B with tag > "vanilla" is instantiated and returned to C. The same occurs for the > reference to D in the "vanilla" B. > > The E component has a "vanilla" tag and refers to B. The existing > instance of B with tag "vanilla" satisfies the reference. > > Note that at no point do the definitions of B or D refer to "chocolate" > or "vanilla"; the tag is somehow magically propagated by those instances > that attempt to get a reference to B or D. Naturally, if a hypothetical > component G with tag "strawberry" asked for a reference to A, new > instances of A, B, and D would be instantiated with tag "strawberry". > > Is there some way to do this in DS without dropping down to the OSGi > APIs like ServiceTracker? I could probably do all of the above manually > somehow, but I'd prefer not to have to. > > M > > > attxrnvn.dat Type: application/pgp-signature > Name: attxrnvn.dat > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev > > > <attccrq0.dat> > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev