I need multiton instance of a given OSGI component, i.e. some bundles will get the same instance of the implementation, and other bundles need another instance. I need to use XML files instead of annotations (like @Component) if possible. I am using a hybrid OSGI 4.3 platform consisting bundles from eclipse & felix.
Let's say, my service interface looks like this:
public interface SocketService {
// Does nothing if already listening on given port
public void startListening(int port);
public String getNextMessage();
}
Declarative XML file looks like as follows and works fine:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="SocketService">
<implementation class="declarativemultiton.service.impl.SocketServiceImpl"/>
<service>
<provide interface="declarativemultiton.service.SocketService"/>
</service>
</scr:component>
These are the consumer classes, with same same semantics:
public class Consumer1 {
public void activate() {
System.out.println("Consumer1 activated");
}
public void setSocketService(SocketService service) {
System.out.println("Consumer1 got SocketService@" + System.identityHashCode(service));
}
}
public class Consumer2 {
public void activate() {
System.out.println("Consumer2 activated");
}
public void setSocketService(SocketService service) {
System.out.println("Consumer2 got socketservice@" + System.identityHashCode(service));
}
}
And their component definition XML's:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Consumer1" immediate="true">
<implementation class="declarativemultiton.consumer1.Consumer1"/>
<reference bind="setSocketService" cardinality="1..1" interface="declarativemultiton.service.SocketService" name="SocketService" policy="static"/>
</scr:component>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Consumer2" immediate="true">
<implementation class="declarativemultiton.consumer2.Consumer2"/>
<reference bind="setSocketService" cardinality="1..1" interface="declarativemultiton.service.SocketService" name="SocketService" policy="static"/>
</scr:component>
Everthing works as expected, and both components get the same instance:
Socket Service Impl activated
Consumer1 got SocketService@1769618707
Consumer1 activated
Consumer2 got socketservice@1769618707
Consumer2 activated
I need Component1 and Component2 to acquire different SocketService instances, and Component2 and Component3 (not shown) to have same SocketService instance.
If I change the configuration-policy to "require" no consumer component gets activated:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="require" name="SocketService">
<implementation class="declarativemultiton.service.impl.SocketServiceImpl"/>
<service>
<provide interface="declarativemultiton.service.SocketService"/>
</service>
</scr:component>
This is where I am lost, I don't know how to pass configuration dynamically to the SocketService. I have been pulling my hair while reading about ConfigurationAdmin, ManagedService, ManagedServiceFactory, ComponentFactory etc. I could not found one concrete, concise solution. There are some conflicting approaches, like this answer https://stackoverflow.com/a/4129464/330464 says not to use ManagedService, but a Karaf Tutorial http://sully6768.blogspot.com.tr/2012/09/declarative-services-with-karaf-part-4.html addresses its use.