How to write factory pattern in OSGi?

475 Views Asked by At

I have multiple Impl classes which implements the same service. I need to write a single factory class in osgi where I should write getter method to return appropriate Impl Object. Below is the code I tried. I am struck in factory class. Any ideas to proceed ?

public interface ServiceA {
   public void display();
}

@Component (description = "Test1 service", ds = true, immediate = true)
@Service (value = {ServiceA.class})
class Test1 implements ServiceA{

      public void display(){
        Log.debug("Test1");
      }
}

@Component (description = "Test2 service", ds = true, immediate = true)
@Service (value = {ServiceA.class})
class Test2 implements ServiceA{

      public void display(){
        Log.debug("Test2");
      }
}

//How to write factory ?
class Factory{

    public ServiceA getObject(String testType){
         if(testType.equals("Test1")){
             return Test1;
         }
         else{
             return Test2;
         }
    }
}
1

There are 1 best solutions below

0
On

Although it's not clear how your application intends to make use of these different service implementations, one way to do it is using service properties and then require that property when actually referencing these services at the service consumer, e.g.:

@Component (description = "Test1 service", ds = true, immediate = true)
@Service (value = {ServiceA.class})
@Property (name = "type", value = "test1")
class Test1 implements ServiceA{
    // ...
}

@Component (description = "Test2 service", ds = true, immediate = true)
@Service (value = {ServiceA.class})
@Property (name = "type", value = "test2")
class Test2 implements ServiceA{
    // ...
}

...and at the consumer side, you just add service selection criteria for the reference, e.g.:

@Component (...)
class MyConsumer {
    // ...

    @Reference(target="(type=test2)")
    ServiceA testService2;

    // ...
}

No factories needed! :)

For more information, have a look at this little article.

If you need to dynamically route to a specific service implementation based on runtime service request attributes, you can also hold a reference to all service implementations and map them using the desired property for fast selection, e.g.:

@Component (...)
class MyConsumer {
    // ...
    private final Map<String, ServiceA> services = // ...

    @Reference(
            cardinality = ReferenceCardinality.MULTIPLE,
            policy = ReferencePolicy.DYNAMIC,
            service = ServiceA.class,
            target = "(type=*)"
    )
    public void addServiceA(ServiceA instance, Map properties) {
        service.put(String.valueOf(properties.get("type")), instance);
    }

    public void removeServiceA(Map properties) {
        service.remove(String.valueOf(properties.get("type")));
    }

    // ...
}