Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have a bunch of libraries and I have started exposing them as OSGi modules. However there were two requirements:

  • no new dependencies
  • the modules still had to run in non-OSGi environments

The first requirement is easily solved by using DS (declarative services) however the second seems slightly more difficult. I currently have a working solution but I'm not sure if it is a good one. I will explain my methodology using a simple example, any feedback on it is welcome.

Suppose you have a service class called MyService.

You also have 3 client services A, B and C that each require an instance of the service. OSGi would inject the instance as needed and all would be well. However consider running the module outside an OSGi container.

At this point you yourself are responsible for injecting the proper beans and (if necessary) manage the singletons that most osgi services are. So at this point you have to inject the proper singleton into three other objects. This can scale to unmanageable levels fast.

My solution consists of reusing the factory pattern:

public class MyServiceFactory {

    private static MyServiceFactory instance;

    public static MyServiceFactory getInstance() {
        if (instance == null)
            instance = new MyServiceFactory();
        return instance;
    }

    private MyService myService;

    public MyService getMyService() {
        // fall back to SPI
        if (myService == null) {
            ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);
            Iterator<MyService> iterator = serviceLoader.iterator();
            if (iterator.hasNext())
                myService = iterator.next();
            // if no SPI modules, you could for instance initialize a stub, a default,...
            else
                myService = new MyServiceStub();
        }
        return myService;
    }

    public void setMyService(MyService myService) {
        this.myService = myService;
    }

    public void unsetMyService(MyService myService) {
        this.myService = null;
    }

    @SuppressWarnings("unused")
    private void activate() {
        instance = this;
    }
    @SuppressWarnings("unused")
    private void deactivate() {
        instance = null;
    }
}

Any code that requires a MyService instance can simply do:

MyServiceFactory.getInstance().getMyService();

It will use an OSGi-managed instance when possible (the private activate/deactivate) or fall back to SPI when necessary.

Is this a good solution or are there better ones? Is it a solved problem where I somehow missed the obvious answer?

share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.