0

If I want to have a service injected in iPojo using method injection I need to do

@Bind
public void bindService(MyService implementation) {
}

Based on the type of the argument it knows which impl to inject just based on the interface. If there are two impls of the same interface it will choose based on some algorithm (service rank?)

Now, if I need multiple intances of the service that need to be created on demand based on an event, I understand I'm supposed to use org.apache.felix.ipojo.Factory and construct the instances through it. The problem I have is that I have not found a way to specify which factory to have injected using only the Interface of the instances of the factory

In other words

@Bind
public void bindService(org.apache.felix.ipojo.Factory myFactory) {
}

is ambiguous. The only way I have found to get the factory injected is using @Bind(filter="(factory.name=myServiceFactoryImpl)" but this couples the consumer to a concrete provider, which defeats the whole point of OSGi services. What I want to do is in plain english "bind me to a factory whose instances implement the interface MyService". If there are again many providers' factories of the same interface, it should use the same disambiguation mechanism as when injecting instances directly. Is this possible?

Hilikus
  • 9,954
  • 14
  • 65
  • 118

2 Answers2

2

Just use a filter using the component.providedServiceSpecifications property listing the interface exposed by the created instances:

@Requires(filter="(component.providedServiceSpecifications=org.acme.Foo)")
Factory[] factories;
Clement
  • 2,817
  • 1
  • 12
  • 11
  • Hi Clement, I was awaiting for your comment as well. Thank you! i was hoping it would be something like this. I had tried `provides.specification=` without luck obviously. How can I possibly know that that was the right property to use? is there a way to list them? The one I tried was from the *factory* command output – Hilikus Dec 14 '14 at 18:41
  • You can get the exposed service properties by exposing the "Factory" service. Notice that handlers can add properties, and immutable properties are also exposed on the Factory service. – Clement Dec 16 '14 at 08:10
1

Simply use a factory interface like MyServiceFactory with one method MyService create();. Then write an implementation of the MyServiceFactory and publish it as an OSGi service. The client can then Bind the MyServviceFactory interface and create his service instances.

Christian Schneider
  • 19,420
  • 2
  • 39
  • 64
  • Yes, that would work, but then the question is, what's the point of `org.apache.felix.ipojo.Factory`? Because I would imagine it does more than just create instances. AFAIK it also controls the lifecycle of its instances – Hilikus Dec 12 '14 at 15:26
  • Like you said the ipojo Factory interface allows to do more than just create the instance. I would not use it outside your bundle though. It would expose the fact that you use ipojo. I would rather hide that so the consumer of your service is only exposed to standard java which results in lower coupling. – Christian Schneider Dec 12 '14 at 15:32
  • I'm glad you mentioned that point. That's one of my biggest complains of the ipojo.Factory. But again, if I implement my own factory then I lose the whole lifecycle management of ipojo. One concrete example, if the factory service disappear, the holders of the created instances would do what? – Hilikus Dec 12 '14 at 15:37
  • 1
    Generally a consumer of a service should never hold the service reference for a longer time. If you do then in case the provider bundle is removed the classes can not be cleaned up. So as a consumer you should monitor the factory service and clean up your references to instances when the factory goes away. For direct service refs you are expected to do the same btw. – Christian Schneider Dec 12 '14 at 16:04