Joe Almore
Joe Almore

Reputation: 4311

OSGi - Low Level Service API

I am reading a book about Modular Apps with OSGi and I am building some prototypes and so. There is a point in the book where the author says that one should avoid any use of the Low Level Service API for Registering Services and for Dependency Management, and encourage his readers to use a Dependency Framework instead (e.g. Dependency Manager).

That is good, except for the point that the author does not say why? or at least I didn't get any reason of considerable weight to do so. So, I have the following code:

httpService = context.getService(context.getServiceReference(HttpService.class));

Which gets an instance of the HttpService service using Low Level API, and there is this approach using DependencyManager:

dependencyManager.add(createComponent()
                          .setImplementation(ResourceRegistration.class)
                          .add(createServiceDependency()
                                       .setService(HttpService.class)
                                       .setRequired(true)));

Which sets a SericeDependency to the class ResoureRegistration, otherwise I would have to get the service as written above (using Low Level Service API).

Now, without considering how many lines you have to write to get the same dependency injected in your code, is there any considerable reason to not (or at least avoid) the use of Low Level Service API?

I have to say that, I am using the Low Level API and avoiding the use of (what I consider) unnecessary additional frameworks to avoid making a "fat" final release with a bunch of frameworks and unnecessary bundles, which some people say these are needed because they save you a couple lines of code by assuming the charge of a couple more black-box bundles in your deployment.

The author also states that, using Low Level Service API "we have to check for deregistered services ourselves". And my other question is, and by implementing a Dependency Framework will we avoid this check?

Thanks for your time.-

Upvotes: 3

Views: 148

Answers (2)

kapex
kapex

Reputation: 29949

The "Dependency Manager" is only one of many component frameworks. Most articles, tutorials and code examples I've read so far, use either Declarative Services or Blueprint, so I've got the impression that the Dependency Manager is one of the lesser used frameworks. That isn't necessarily bad though, if it provides feature that other frameworks don't.

The programmatic approach of the Dependency Manager seems close to the low level API. It probably has it's purpose somewhere, but I have yet to find it.

Most frameworks use a DI/annotation based approach instead. You simply annotate classes with @Component and attributes with @Reference (or getter/setter methods) and the framework handles everything from component instantiation to binding and unbinding services. Accessing a service becomes something like this:

@Reference
private MyService myService;

Check out "Declarative Services" for a not to complicated framework. There is also Blueprint and iPOJO. I think for larger applications you are going to need a framework to keep sane. Also keep in mind that most of those frameworks do a lot at built time. I don't think they are that "fat".

httpService = context.getService(context.getServiceReference(HttpService.class));

The problem here is, what if there is no HttpService at this point? Sure, you can check that - but how are you going to know when it will be available, so you can register you servlets later? You would need to write a ServiceTracker for that, which is complicated and a lot of boilerplate code.

At least use the whiteboard pattern, where you register your Servlets as services and the HttpService will discover them when it is available. You could do that without a framework by using the bundle context. I think it's still way easier to use a framework though and simply put @Service @Component in front of your class instead of doing everything by hand.

Upvotes: 1

Christian Schneider
Christian Schneider

Reputation: 19606

The problem with context.getService() is that you may not use the service object you get over any longer periods of time. The reason is in the dynamics of OSGi.

If the bundle that published the service is stopped then it unregisters the service. After the service is unregistered you should not use it anymore. In the worst case the fact that you still hold a reference on the service object would make it impossible for the garbage collector to clean up the classloader of the uninstalled bundle. Even worse would be if you call a method on the (now invalid) service. The service method would be executed but the resources the service need and even its classloader may now be invalid. So You would get exceptions and also memory leaks.

If you really want to use the low level API then you have to do getService() shortly before you need the service and ungetService() asap after. This is very inconvenient though and pollutes your own code with OSGi calls. This is why very few people use the APIs like this.

If you want to stick with OSGi APIs you can use the ServiceTracker. It allows you to either always get a valid service object using getService() or react on the services as they appear and disappear using the callbacks addingService and removedService.

Frameworks like dependencymanager, declarative services and blueprint manage those dynamics for you.

For example if you define a @Component in declarative services with a mandatory @Reference then your whole component will only come up when all needed services are there and if a service changes you will get the new one injected. As far as I know dependencymanager does a similar thing.

Blueprint is a little less dynamic. It will only inject once but it will inject you a proxy that always points to the valid service or blocks if none is there.

All this is done to shield you from handling the complexities of service dynamics. As a rough guideline I would only use the low level APIs if you write a technical OSGi library or framework yourself and may not depend on added dependencies. For business applications you should never work without one of the frameworks.

Upvotes: 2

Related Questions