Search code examples
osgideclarative-services

Best practice for referencing OSGi DS in given bundle


My Requirement: I have a service which takes care of persistence in my project. Let me call this service as PersistenceProvider service and lets assume it's residing in "my.persistenceservice" bundle.

Now, I have another bundle named "my.persitenceconsumer" bundle which referencing PersistenceProvider service using bind() unbind() method of one of the class named MyPersistenseConsumer. So when "my.persistenceconsumer" bundle starts, it will get reference of PersistenceProvider service using bind() method and MyPersistenceConsumer can use PersistenceProvider service

But, I also need to use this PersistenceProvider service from different classes in "my.persitenceconsumer" bundle.

My QUESTION is: What is the best way to use such shared service within different classes (in same bundle)

One of the solution: I can add Activator class in "my.persitenceconsumer" bundle .. having static getInstance() method. Which can be called by MyPersistenceConsumer.bind() and stores PersistenceProvider with Activator. Latter all classes in "my.persitenceconsumer" bundle can use PersistenceProvider using Activator class.

Here is the code:

public class MyPersistenceConsumer {
  public void bindPersistenceProvider(PersistenceProvider ppRef) {
    MyPersistenceConsumerActivator.getInstance().bindPersistenceProvider(ppRef);
  }
}

public class MyPersistenceConsumerActivator {
  static MyPersistenceConsumerActivator instance;
  PersistenceProvider ppRef;

  public static getInstance() {
    return instance;
  }

  public void bindPersistenceProvider(PersistenceProvider ppRef) {
    this.ppRef = ppRef;
  }
  public PersistenceProvider getPersistenceProvider() {
    return ppRef;
  }

  public void start(BundleContext context) throws Exception {
        instance = this;
  }
}

public class MyClass1 {

  public void usePersistenceProvider(){
    PersistenceProvider pp Ref =
      MyPersistenceConsumerActivator.getInstance().getPersistenceProvider();
  }

}

public class MyClass2 {

  public void usePersistenceProvider(){
    PersistenceProvider pp Ref =
      MyPersistenceConsumerActivator.getInstance().getPersistenceProvider();
  }

}

At Last: Does above is good way .. or is there a better way?


Solution

  • Singletons are an evilness that DS tries to eliminate. Singletons create brittle systems, they have the same problems as global vars.

    The best solution is no-coupling. With DS I would use:

    @Component
    public class MyClass1 {
      @Reference
      void setPP( PersistenceProvider pp ) { ... }
    }
    

    And the same for MyClass2. If there is an instance relation between classes, pass the object around since you're already coupled then. As always, minimise coupling and maximise cohesion.

    Factories and singletons are the exact evils OSGi tries to prevent for very good reasons.